from sqlalchemy import types as sqltypes
from decimal import Decimal as _python_Decimal
from sqlalchemy.types import INTEGER, BIGINT, SMALLINT, DECIMAL, NUMERIC, \
- FLOAT, TIMESTAMP
+ FLOAT, TIMESTAMP, DATETIME, DATE
from sqlalchemy.dialects.mssql import information_schema as ischema
])
-class MSNumeric(sqltypes.Numeric):
+class _MSNumeric(sqltypes.Numeric):
def result_processor(self, dialect):
if self.asdecimal:
def process(value):
def __init__(self):
super(REAL, self).__init__(precision=24)
-MSReal = REAL
class TINYINT(sqltypes.Integer):
__visit_name__ = 'TINYINT'
-MSTinyInteger = TINYINT
# MSSQL DATE/TIME types have varied behavior, sometimes returning
-# strings. MSDate/MSTime check for everything, and always
+# strings. MSDate/TIME check for everything, and always
# filter bind parameters into datetime objects (required by pyodbc,
# not sure about other dialects).
-class DATE(sqltypes.DATE):
+class _MSDate(sqltypes.Date):
def bind_processor(self, dialect):
def process(value):
if type(value) == datetime.date:
else:
return value
return process
-MSDate = DATE
class TIME(sqltypes.TIME):
def __init__(self, precision=None, **kwargs):
return value
return process
-MSTime = TIME
class _DateTimeBase(object):
def bind_processor(self, dialect):
return value
return process
-class DATETIME(_DateTimeBase, sqltypes.DATETIME):
+class _MSDateTime(_DateTimeBase, sqltypes.DateTime):
pass
-MSDateTime = DATETIME
class SMALLDATETIME(_DateTimeBase, sqltypes.DateTime):
__visit_name__ = 'SMALLDATETIME'
-MSSmallDateTime = SMALLDATETIME
class DATETIME2(_DateTimeBase, sqltypes.DateTime):
__visit_name__ = 'DATETIME2'
def __init__(self, precision=None, **kwargs):
self.precision = precision
-MSDateTime2 = DATETIME2
# TODO: is this not an Interval ?
def __init__(self, precision=None, **kwargs):
self.precision = precision
-MSDateTimeOffset = DATETIMEOFFSET
class _StringType(object):
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.Text.__init__(self, *args, **kw)
-MSText = TEXT
class NTEXT(_StringType, sqltypes.UnicodeText):
"""MSSQL NTEXT type, for variable-length unicode text up to 2^30
_StringType.__init__(self, collation)
length = kwargs.pop('length', None)
sqltypes.UnicodeText.__init__(self, length, **kwargs)
-MSNText = NTEXT
class VARCHAR(_StringType, sqltypes.VARCHAR):
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.VARCHAR.__init__(self, *args, **kw)
-MSString = VARCHAR
class NVARCHAR(_StringType, sqltypes.NVARCHAR):
"""MSSQL NVARCHAR type.
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.NVARCHAR.__init__(self, *args, **kw)
-MSNVarchar = NVARCHAR
class CHAR(_StringType, sqltypes.CHAR):
"""MSSQL CHAR type, for fixed-length non-Unicode data with a maximum
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.CHAR.__init__(self, *args, **kw)
-MSChar = CHAR
class NCHAR(_StringType, sqltypes.NCHAR):
"""MSSQL NCHAR type.
collation = kw.pop('collation', None)
_StringType.__init__(self, collation)
sqltypes.NCHAR.__init__(self, *args, **kw)
-MSNChar = NCHAR
class BINARY(sqltypes.Binary):
__visit_name__ = 'BINARY'
-MSBinary = BINARY
class VARBINARY(sqltypes.Binary):
__visit_name__ = 'VARBINARY'
-MSVarBinary = VARBINARY
class IMAGE(sqltypes.Binary):
__visit_name__ = 'IMAGE'
-MSImage = IMAGE
class BIT(sqltypes.TypeEngine):
__visit_name__ = 'BIT'
-MSBit = BIT
-class MSBoolean(sqltypes.Boolean):
+class _MSBoolean(sqltypes.Boolean):
def result_processor(self, dialect):
def process(value):
if value is None:
class MONEY(sqltypes.TypeEngine):
__visit_name__ = 'MONEY'
-MSMoney = MONEY
-class SMALLMONEY(MSMoney):
+class SMALLMONEY(sqltypes.TypeEngine):
__visit_name__ = 'SMALLMONEY'
-MSSmallMoney = SMALLMONEY
class UNIQUEIDENTIFIER(sqltypes.TypeEngine):
__visit_name__ = "UNIQUEIDENTIFIER"
-MSUniqueIdentifier = UNIQUEIDENTIFIER
class SQL_VARIANT(sqltypes.TypeEngine):
__visit_name__ = 'SQL_VARIANT'
+
+# old names.
+MSNumeric = _MSNumeric
+MSDateTime = _MSDateTime
+MSDate = _MSDate
+MSBoolean = _MSBoolean
+MSReal = REAL
+MSTinyInteger = TINYINT
+MSTime = TIME
+MSSmallDateTime = SMALLDATETIME
+MSDateTime2 = DATETIME2
+MSDateTimeOffset = DATETIMEOFFSET
+MSText = TEXT
+MSNText = NTEXT
+MSString = VARCHAR
+MSNVarchar = NVARCHAR
+MSChar = CHAR
+MSNChar = NCHAR
+MSBinary = BINARY
+MSVarBinary = VARBINARY
+MSImage = IMAGE
+MSBit = BIT
+MSMoney = MONEY
+MSSmallMoney = SMALLMONEY
+MSUniqueIdentifier = UNIQUEIDENTIFIER
MSVariant = SQL_VARIANT
+colspecs = {
+ sqltypes.Numeric : _MSNumeric,
+ sqltypes.DateTime : _MSDateTime,
+ sqltypes.Date : _MSDate,
+ sqltypes.Time : TIME,
+ sqltypes.Boolean : _MSBoolean,
+}
+
+ischema_names = {
+ 'int' : INTEGER,
+ 'bigint': BIGINT,
+ 'smallint' : SMALLINT,
+ 'tinyint' : TINYINT,
+ 'varchar' : VARCHAR,
+ 'nvarchar' : NVARCHAR,
+ 'char' : CHAR,
+ 'nchar' : NCHAR,
+ 'text' : TEXT,
+ 'ntext' : NTEXT,
+ 'decimal' : DECIMAL,
+ 'numeric' : NUMERIC,
+ 'float' : FLOAT,
+ 'datetime' : DATETIME,
+ 'datetime2' : DATETIME2,
+ 'datetimeoffset' : DATETIMEOFFSET,
+ 'date': DATE,
+ 'time': TIME,
+ 'smalldatetime' : SMALLDATETIME,
+ 'binary' : BINARY,
+ 'varbinary' : VARBINARY,
+ 'bit': BIT,
+ 'real' : REAL,
+ 'image' : IMAGE,
+ 'timestamp': TIMESTAMP,
+ 'money': MONEY,
+ 'smallmoney': SMALLMONEY,
+ 'uniqueidentifier': UNIQUEIDENTIFIER,
+ 'sql_variant': SQL_VARIANT,
+}
+
+
class MSTypeCompiler(compiler.GenericTypeCompiler):
def _extend(self, spec, type_):
"""Extend a string-type declaration with standard SQL
pass
-colspecs = {
- sqltypes.Numeric : MSNumeric,
- sqltypes.DateTime : DATETIME,
- sqltypes.Date : DATE,
- sqltypes.Time : TIME,
- sqltypes.Boolean : MSBoolean,
-}
-
-ischema_names = {
- 'int' : INTEGER,
- 'bigint': BIGINT,
- 'smallint' : SMALLINT,
- 'tinyint' : TINYINT,
- 'varchar' : VARCHAR,
- 'nvarchar' : NVARCHAR,
- 'char' : CHAR,
- 'nchar' : NCHAR,
- 'text' : TEXT,
- 'ntext' : NTEXT,
- 'decimal' : DECIMAL,
- 'numeric' : NUMERIC,
- 'float' : FLOAT,
- 'datetime' : DATETIME,
- 'datetime2' : DATETIME2,
- 'datetimeoffset' : DATETIMEOFFSET,
- 'date': DATE,
- 'time': TIME,
- 'smalldatetime' : SMALLDATETIME,
- 'binary' : BINARY,
- 'varbinary' : VARBINARY,
- 'bit': BIT,
- 'real' : REAL,
- 'image' : IMAGE,
- 'timestamp': TIMESTAMP,
- 'money': MONEY,
- 'smallmoney': SMALLMONEY,
- 'uniqueidentifier': UNIQUEIDENTIFIER,
- 'sql_variant': SQL_VARIANT,
-}
-
class MSSQLCompiler(compiler.SQLCompiler):
extract_map = compiler.SQLCompiler.extract_map.copy()
from sqlalchemy.engine import base as engine_base, default
from sqlalchemy import types as sqltypes
-from sqlalchemy.types import DATE, DATETIME
+from sqlalchemy.types import DATE, DATETIME, BOOLEAN, TIME
RESERVED_WORDS = set(
['accessible', 'add', 'all', 'alter', 'analyze','and', 'as', 'asc',
return value
return process
-class TIME(sqltypes.TIME):
+class _MSTime(sqltypes.Time):
"""MySQL TIME type."""
__visit_name__ = 'TIME'
return value
return process
-class BOOLEAN(sqltypes.Boolean):
+class _MSBoolean(sqltypes.Boolean):
"""MySQL BOOLEAN type."""
__visit_name__ = 'BOOLEAN'
return process
# old names
-MSBoolean = BOOLEAN
+MSBoolean = _MSBoolean
+MSTime = _MSTime
MSSet = SET
MSEnum = ENUM
MSLongBlob = LONGBLOB
MSText = TEXT
MSYear = YEAR
MSTimeStamp = TIMESTAMP
-MSTime = TIME
MSBit = BIT
MSSmallInteger = SMALLINT
MSTinyInteger = TINYINT
sqltypes.Numeric: NUMERIC,
sqltypes.Float: FLOAT,
sqltypes.Binary: _BinaryType,
- sqltypes.Boolean: BOOLEAN,
- sqltypes.Time: TIME,
+ sqltypes.Boolean: _MSBoolean,
+ sqltypes.Time: _MSTime,
}
# Everything 3.23 through 5.1 excepting OpenGIS types.
class LONG(sqltypes.Text):
__visit_name__ = 'LONG'
-class OracleBoolean(sqltypes.Boolean):
+class _OracleBoolean(sqltypes.Boolean):
def result_processor(self, dialect):
def process(value):
if value is None:
return process
colspecs = {
- sqltypes.Boolean : OracleBoolean,
+ sqltypes.Boolean : _OracleBoolean,
}
ischema_names = {
"""
-from sqlalchemy.dialects.oracle.base import OracleDialect, OracleRaw, OracleBoolean, RESERVED_WORDS
+from sqlalchemy.dialects.oracle.base import OracleDialect, RAW, _OracleBoolean, RESERVED_WORDS
from sqlalchemy.engine.default import DefaultExecutionContext
from sqlalchemy.engine import base
from sqlalchemy import types as sqltypes, util
import datetime
-class OracleDate(sqltypes.Date):
+class _OracleDate(sqltypes.Date):
def bind_processor(self, dialect):
return None
return value.date()
return process
-class OracleDateTime(sqltypes.DateTime):
+class _OracleDateTime(sqltypes.DateTime):
def result_processor(self, dialect):
def process(value):
if value is None or isinstance(value, datetime.datetime):
# Oracle does not support TIME columns
# only if cx_oracle contains TIMESTAMP
-class OracleTimestamp(sqltypes.TIMESTAMP):
+class _OracleTimestamp(sqltypes.TIMESTAMP):
def result_processor(self, dialect):
def process(value):
if value is None or isinstance(value, datetime.datetime):
value.day,value.hour, value.minute, value.second)
return process
-class LOBMixin(object):
+class _LOBMixin(object):
def result_processor(self, dialect):
- super_process = super(LOBMixin, self).result_processor(dialect)
+ super_process = super(_LOBMixin, self).result_processor(dialect)
if not dialect.auto_convert_lobs:
return super_process
lob = dialect.dbapi.LOB
return value
return process
-class OracleText(LOBMixin, sqltypes.Text):
+class _OracleText(_LOBMixin, sqltypes.Text):
def get_dbapi_type(self, dbapi):
return dbapi.CLOB
-class OracleUnicodeText(LOBMixin, sqltypes.UnicodeText):
+class _OracleUnicodeText(_LOBMixin, sqltypes.UnicodeText):
def get_dbapi_type(self, dbapi):
return dbapi.NCLOB
-class OracleBinary(LOBMixin, sqltypes.Binary):
+class _OracleBinary(_LOBMixin, sqltypes.Binary):
def get_dbapi_type(self, dbapi):
return dbapi.BLOB
return None
-class cxOracleRaw(LOBMixin, OracleRaw):
+class _OracleRaw(_LOBMixin, RAW):
pass
colspecs = {
- sqltypes.DateTime : OracleDateTime,
- sqltypes.Date : OracleDate,
- sqltypes.Binary : OracleBinary,
- sqltypes.Boolean : OracleBoolean,
- sqltypes.Text : OracleText,
- sqltypes.UnicodeText : OracleUnicodeText,
- sqltypes.TIMESTAMP : OracleTimestamp,
- OracleRaw: cxOracleRaw,
+ sqltypes.DateTime : _OracleDateTime,
+ sqltypes.Date : _OracleDate,
+ sqltypes.Binary : _OracleBinary,
+ sqltypes.Boolean : _OracleBoolean,
+ sqltypes.Text : _OracleText,
+ sqltypes.UnicodeText : _OracleUnicodeText,
+ sqltypes.TIMESTAMP : _OracleTimestamp,
+ RAW: _OracleRaw,
}
class Oracle_cx_oracleExecutionContext(DefaultExecutionContext):
from sqlalchemy import types as sqltypes
from sqlalchemy.dialects.postgres.base import PGDialect, PGCompiler
-class PGNumeric(sqltypes.Numeric):
+class _PGNumeric(sqltypes.Numeric):
def bind_processor(self, dialect):
return None
colspecs = util.update_copy(
PGDialect.colspecs,
{
- sqltypes.Numeric : PGNumeric,
- sqltypes.Float: sqltypes.Float, # prevents PGNumeric from being used
+ sqltypes.Numeric : _PGNumeric,
+ sqltypes.Float: sqltypes.Float, # prevents _PGNumeric from being used
}
)
from sqlalchemy import types as sqltypes
from sqlalchemy.dialects.postgres.base import PGDialect, PGCompiler
-class PGNumeric(sqltypes.Numeric):
+class _PGNumeric(sqltypes.Numeric):
def bind_processor(self, dialect):
return None
colspecs = util.update_copy(
PGDialect.colspecs,
{
- sqltypes.Numeric : PGNumeric,
- sqltypes.Float: sqltypes.Float, # prevents PGNumeric from being used
+ sqltypes.Numeric : _PGNumeric,
+ sqltypes.Float: sqltypes.Float, # prevents _PGNumeric from being used
}
)
out of the box functionality for translating values between Python `datetime` objects
and a SQLite-supported format. SQLAlchemy's own :class:`~sqlalchemy.types.DateTime`
and related types provide date formatting and parsing functionality when SQlite is used.
-The implementation classes are :class:`SLDateTime`, :class:`SLDate` and :class:`SLTime`.
+The implementation classes are :class:`_SLDateTime`, :class:`_SLDate` and :class:`_SLTime`.
These types represent dates and times as ISO formatted strings, which also nicely
support ordering. There's no reliance on typical "libc" internals for these functions
so historical dates are fully supported.
from sqlalchemy.sql import compiler, functions as sql_functions
from sqlalchemy.util import NoneType
-class NumericMixin(object):
+from sqlalchemy.types import BLOB, BOOLEAN, CHAR, DATE, DATETIME, DECIMAL,\
+ FLOAT, INTEGER, NUMERIC, SMALLINT, TEXT, TIME,\
+ TIMESTAMP, VARCHAR
+
+
+class _NumericMixin(object):
def bind_processor(self, dialect):
type_ = self.asdecimal and str or float
def process(value):
return value
return process
-class SLNumeric(NumericMixin, sqltypes.Numeric):
+class _SLNumeric(_NumericMixin, sqltypes.Numeric):
pass
-class SLFloat(NumericMixin, sqltypes.Float):
+class _SLFloat(_NumericMixin, sqltypes.Float):
pass
# since SQLite has no date types, we're assuming that SQLite via ODBC
# or JDBC would similarly have no built in date support, so the "string" based logic
# would apply to all implementing dialects.
-class DateTimeMixin(object):
+class _DateTimeMixin(object):
def _bind_processor(self, format, elements):
def process(value):
if not isinstance(value, (NoneType, datetime.date, datetime.datetime, datetime.time)):
return None
return process
-class SLDateTime(DateTimeMixin, sqltypes.DateTime):
+class _SLDateTime(_DateTimeMixin, sqltypes.DateTime):
__legacy_microseconds__ = False
def bind_processor(self, dialect):
def result_processor(self, dialect):
return self._result_processor(datetime.datetime, self._reg)
-class SLDate(DateTimeMixin, sqltypes.Date):
+class _SLDate(_DateTimeMixin, sqltypes.Date):
def bind_processor(self, dialect):
return self._bind_processor(
"%4.4d-%2.2d-%2.2d",
def result_processor(self, dialect):
return self._result_processor(datetime.date, self._reg)
-class SLTime(DateTimeMixin, sqltypes.Time):
+class _SLTime(_DateTimeMixin, sqltypes.Time):
__legacy_microseconds__ = False
def bind_processor(self, dialect):
return self._result_processor(datetime.time, self._reg)
-class SLBoolean(sqltypes.Boolean):
+class _SLBoolean(sqltypes.Boolean):
def bind_processor(self, dialect):
def process(value):
if value is None:
return process
colspecs = {
- sqltypes.Boolean: SLBoolean,
- sqltypes.Date: SLDate,
- sqltypes.DateTime: SLDateTime,
- sqltypes.Float: SLFloat,
- sqltypes.Numeric: SLNumeric,
- sqltypes.Time: SLTime,
+ sqltypes.Boolean: _SLBoolean,
+ sqltypes.Date: _SLDate,
+ sqltypes.DateTime: _SLDateTime,
+ sqltypes.Float: _SLFloat,
+ sqltypes.Numeric: _SLNumeric,
+ sqltypes.Time: _SLTime,
}
ischema_names = {
d. If a TypeEngine class doesn't provide any of this, it should be
*removed* from the dialect.
-2. the TypeEngine classes are *no longer* used for:
+2. the TypeEngine classes are *no longer* used for generating DDL. Dialects
+now have a TypeCompiler subclass which uses the same visit_XXX model as
+other compilers.
- a. generating DDL
-
3. the "ischema_names" and "colspecs" dictionaries are now required members on
the Dialect class.
4. The names of types within dialects are now important. If a dialect-specific type
is a subclass of an existing generic type and is only provided for bind/result behavior,
-the current mixed case naming can remain, i.e. PGNumeric for Numeric - in this case,
-end users would never need to use PGNumeric directly. However, if a dialect-specific
+the current mixed case naming can remain, i.e. _PGNumeric for Numeric - in this case,
+end users would never need to use _PGNumeric directly. However, if a dialect-specific
type is specifying a type *or* arguments that are not present generically, it should
match the real name of the type on that backend, in uppercase. E.g. postgres.INET,
mysql.ENUM, postgres.ARRAY.
Or follow this handy flowchart:
- is the type in types.py as an UPPERCASE type ?
- | |
- | yes ---> does your type need special behavior or arguments ? no ----> don't make a
- | ^ yes type, make sure the dialect's
- | no | base.py imports the types.py
- | | | UPPERCASE name into its namespace
- v is it v
- no -------- a native yes -----> build new type
- DB type? |
- v
- is this type native to the database ?
- (i.e. BIT is native to MySQL, "Boolean" is *not* native to Oracle)
- yes no
- | |
- v v
- name the type THE SAME name the type using
- as that of the DB, MixedCase, i.e.
- using UPPERCASE OracleBoolean
- (i.e. BIT, NCHAR, INTERVAL) |
- | |
- +----------------+----------------+
- |
- v
- the type should is the name of this type
- subclass the <----- yes identical to an UPPERCASE name
- UPPERCASE in types.py?
- type in types.py no
- (i.e. class BLOB(types.BLOB)) |
- v
- subclass the closest
- MixedCase type types.py,
- i.e.
- class DATETIME2(types.DateTime),
- class BIT(types.TypeEngine)
+ is the type meant to provide bind/result is the type the same name as an
+ behavior to a generic type (i.e. MixedCase) ---- no ---> UPPERCASE type in types.py ?
+ type in types.py ? | |
+ | no yes
+ yes | |
+ | | does your type need special
+ | +<--- yes --- behavior or arguments ?
+ | | |
+ | | no
+ name the type using | |
+ _MixedCase, i.e. v V
+ _OracleBoolean. it name the type don't make a
+ stays private to the dialect identically as that type, make sure the dialect's
+ and is invoked *only* via within the DB, base.py imports the types.py
+ the colspecs dict. using UPPERCASE UPPERCASE name into its namespace
+ | (i.e. BIT, NCHAR, INTERVAL).
+ | Users can import it.
+ | |
+ v v
+ subclass the closest is the name of this type
+ MixedCase type types.py, identical to an UPPERCASE
+ i.e. <--- no ------- name in types.py ?
+ class _DateTime(types.DateTime),
+ class DATETIME2(types.DateTime), |
+ class BIT(types.TypeEngine). yes
+ |
+ v
+ the type should
+ subclass the
+ UPPERCASE
+ type in types.py
+ (i.e. class BLOB(types.BLOB))
+
+
+Example 1. pysqlite needs bind/result processing for the DateTime type in types.py,
+which applies to all DateTimes and subclasses. It's named _SLDateTime and
+subclasses types.DateTime.
+
+Example 2. MS-SQL has a TIME type which takes a non-standard "precision" argument
+that is rendered within DDL. So it's named TIME in the MS-SQL dialect's base.py,
+and subclasses types.TIME. Users can then say mssql.TIME(precision=10).
+Example 3. MS-SQL dialects also need special bind/result processing for date
+But its DATE type doesn't render DDL differently than that of a plain
+DATE, i.e. it takes no special arguments. Therefore we are just adding behavior
+to types.Date, so it's named _MSDate in the MS-SQL dialect's base.py, and subclasses
+types.Date.
+
+Example 4. MySQL has a SET type, there's no analogue for this in types.py. So
+MySQL names it SET in the dialect's base.py, and it subclasses types.String, since
+it ultimately deals with strings.
+
+Example 5. Postgresql has a DATETIME type. The DBAPIs handle dates correctly,
+and no special arguments are used in PG's DDL beyond what types.py provides.
+Postgresql dialect therefore imports types.DATETIME into its base.py.
Ideally one should be able to specify a schema using names imported completely from a
dialect, all matching the real name on that backend:
a. The string name should be matched to the most specific type possible within
sqlalchemy.types, unless there is no matching type within sqlalchemy.types in which
case it points to a dialect type. *It doesn't matter* if the dialect has it's
- own subclass of that type with special bind/result behavior - reflect to the generic type
- as much as possible, since the correct bind/result behavior is always invoked when needed
- regardless of the type being generic or dialect-specific.
+ own subclass of that type with special bind/result behavior - reflect to the types.py
+ UPPERCASE type as much as possible. With very few exceptions, all types
+ should reflect to an UPPERCASE type.
b. If the dialect contains a matching dialect-specific type that takes extra arguments
which the generic one does not, then point to the dialect-specific type. E.g.
mssql.VARCHAR takes a "collation" parameter which should be preserved.
- c. For an exact or almost exact match, point to the uppercase type. i.e. "float"
- should point to "FLOAT", "varchar" should point to "VARCHAR"
-
- d. for a non-match, point to the lowercase type. i.e. "long" should point to "Text",
- "special varchar with sprinkles" points to "String".
-
5. DDL, or what was formerly issued by "get_col_spec()", is now handled exclusively by
a subclass of compiler.GenericTypeCompiler.
b. the visit_UPPERCASE methods on GenericTypeCompiler should *not* be overridden with
methods that produce a different DDL name. Uppercase types don't do any kind of
- "guessing" - if the user says he wants TIMESTAMP, that's the DDL which should render,
- regardless of whether the DB accepts it.
+ "guessing" - if visit_TIMESTAMP is called, the DDL should render as TIMESTAMP in
+ all cases, regardless of whether or not that type is legal on the backend database.
c. the visit_UPPERCASE methods *should* be overridden with methods that add additional
arguments and flags to those types.
d. the visit_lowercase methods are overridden to provide an interpretation of a generic
type. E.g. visit_binary() might be overridden to say "return self.visit_BIT(type_)".
- e. when overriding a visit_lowercase method to return a different type, it should not
- represent the DDL string within the body of the method; it should call the appropriate
- visit_UPPERCASE name.
+ e. visit_lowercase methods should *never* render strings directly - it should always
+ be via calling a visit_UPPERCASE() method.
meta = MetaData(testing.db)
t = Table('bool_table', meta,
Column('id', Integer, primary_key=True),
- Column('boo', sqlite.SLBoolean))
+ Column('boo', Boolean))
try:
meta.create_all()
def test_time_microseconds(self):
dt = datetime.datetime(2008, 6, 27, 12, 0, 0, 125) # 125 usec
eq_(str(dt), '2008-06-27 12:00:00.000125')
- sldt = sqlite.SLDateTime()
+ sldt = sqlite._SLDateTime()
bp = sldt.bind_processor(None)
eq_(bp(dt), '2008-06-27 12:00:00.000125')
(table1.c.name, 'name', 'mytable.name', None),
(table1.c.myid==12, 'mytable.myid = :myid_1', 'mytable.myid = :myid_1', 'anon_1'),
(func.hoho(table1.c.myid), 'hoho(mytable.myid)', 'hoho(mytable.myid)', 'hoho_1'),
- (cast(table1.c.name, sqlite.SLNumeric), 'CAST(mytable.name AS NUMERIC)', 'CAST(mytable.name AS NUMERIC)', 'anon_1'),
+ (cast(table1.c.name, Numeric), 'CAST(mytable.name AS NUMERIC)', 'CAST(mytable.name AS NUMERIC)', 'anon_1'),
(t1.c.col1, 'col1', 'mytable.col1', None),
(column('some wacky thing'), 'some wacky thing', '"some wacky thing"', '')
):
class AdaptTest(TestBase):
- def testmsnvarchar(self):
- # TODO: migrate these tests to dialect modules
-
- dialect = mssql.dialect()
- # run the test twice to ensure the caching step works too
- for x in range(0, 1):
- col = Column('', Unicode(length=10))
- dialect_type = col.type.dialect_impl(dialect)
- assert isinstance(dialect_type, mssql.MSNVarchar)
- eq_(dialect.type_compiler.process(dialect_type), 'NVARCHAR(10)')
-
- def testmysqlbinary(self):
- # TODO: migrate these tests to dialect modules
-
- dialect = mysql.MySQLDialect()
- t1 = mysql.MSVarBinary
- t2 = mysql.MSVarBinary()
- assert isinstance(dialect.type_descriptor(t1), mysql.MSVarBinary)
- assert isinstance(dialect.type_descriptor(t2), mysql.MSVarBinary)
-
- def teststringadapt(self):
- """test that String with no size becomes TEXT, *all* others stay as varchar/String"""
-
- # TODO: migrate these tests to dialect modules
-
- postgres_dialect = postgres.PGDialect()
- firebird_dialect = firebird.FBDialect()
-
- for dialect, start, test in [
- (postgres_dialect, String(), String),
- (postgres_dialect, VARCHAR(), String),
- (postgres_dialect, String(50), String),
- (postgres_dialect, Unicode(), String),
- (postgres_dialect, UnicodeText(), Text),
- (postgres_dialect, NCHAR(), String),
-# (firebird_dialect, String(), firebird.FBString),
-# (firebird_dialect, VARCHAR(), firebird.FBString),
-# (firebird_dialect, String(50), firebird.FBString),
-# (firebird_dialect, Unicode(), firebird.FBString),
-# (firebird_dialect, UnicodeText(), firebird.FBText),
-# (firebird_dialect, NCHAR(), firebird.FBString),
- ]:
- assert isinstance(start.dialect_impl(dialect), test), "wanted %r got %r" % (test, start.dialect_impl(dialect))
-
def test_uppercase_rendering(self):
"""Test that uppercase types from types.py always render as their type.