summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/databases/mysql.py
diff options
context:
space:
mode:
authorJason Kirtland <jek@discorporate.us>2007-11-09 19:55:31 +0000
committerJason Kirtland <jek@discorporate.us>2007-11-09 19:55:31 +0000
commit681c8fc51c92c5998642fcef0ec9e9b079ccf1f5 (patch)
tree9f9f772a78b10f4564c93472bb2e128289273a80 /lib/sqlalchemy/databases/mysql.py
parentc1d5cdb94092a4ca54c837a2ce272eea85f22de9 (diff)
downloadsqlalchemy-681c8fc51c92c5998642fcef0ec9e9b079ccf1f5.tar.gz
- mysql float types now do an end run around the base class and respect precision=None and length=None
- Added the mysteriously missing mysql cast support - Added mysql REAL synonym for schema generation
Diffstat (limited to 'lib/sqlalchemy/databases/mysql.py')
-rw-r--r--lib/sqlalchemy/databases/mysql.py100
1 files changed, 86 insertions, 14 deletions
diff --git a/lib/sqlalchemy/databases/mysql.py b/lib/sqlalchemy/databases/mysql.py
index f8c52b2e1..eb8dede05 100644
--- a/lib/sqlalchemy/databases/mysql.py
+++ b/lib/sqlalchemy/databases/mysql.py
@@ -365,10 +365,10 @@ class MSDecimal(MSNumeric):
return self._extend("DECIMAL(%(precision)s, %(length)s)" % {'precision': self.precision, 'length' : self.length})
-class MSDouble(MSNumeric):
+class MSDouble(sqltypes.Float, _NumericType):
"""MySQL DOUBLE type."""
- def __init__(self, precision=10, length=2, asdecimal=True, **kw):
+ def __init__(self, precision=None, length=None, asdecimal=True, **kw):
"""Construct a DOUBLE.
precision
@@ -389,8 +389,14 @@ class MSDouble(MSNumeric):
if ((precision is None and length is not None) or
(precision is not None and length is None)):
- raise exceptions.ArgumentError("You must specify both precision and length or omit both altogether.")
- super(MSDouble, self).__init__(precision, length, asdecimal=asdecimal, **kw)
+ raise exceptions.ArgumentError(
+ "You must specify both precision and length or omit "
+ "both altogether.")
+
+ _NumericType.__init__(self, **kw)
+ sqltypes.Float.__init__(self, asdecimal=asdecimal)
+ self.length = length
+ self.precision = precision
def get_col_spec(self):
if self.precision is not None and self.length is not None:
@@ -401,10 +407,42 @@ class MSDouble(MSNumeric):
return self._extend('DOUBLE')
+class MSReal(MSDouble):
+ """MySQL REAL type."""
+
+ def __init__(self, precision=None, length=None, asdecimal=True, **kw):
+ """Construct a REAL.
+
+ precision
+ Total digits in this number. If length and precision are both None,
+ values are stored to limits allowed by the server.
+
+ length
+ The number of digits after the decimal point.
+
+ unsigned
+ Optional.
+
+ zerofill
+ Optional. If true, values will be stored as strings left-padded with
+ zeros. Note that this does not effect the values returned by the
+ underlying database API, which continue to be numeric.
+ """
+ MSDouble.__init__(self, precision, length, asdecimal, **kw)
+
+ def get_col_spec(self):
+ if self.precision is not None and self.length is not None:
+ return self._extend("REAL(%(precision)s, %(length)s)" %
+ {'precision': self.precision,
+ 'length' : self.length})
+ else:
+ return self._extend('REAL')
+
+
class MSFloat(sqltypes.Float, _NumericType):
"""MySQL FLOAT type."""
- def __init__(self, precision=10, length=None, asdecimal=False, **kw):
+ def __init__(self, precision=None, length=None, asdecimal=False, **kw):
"""Construct a FLOAT.
precision
@@ -423,12 +461,13 @@ class MSFloat(sqltypes.Float, _NumericType):
underlying database API, which continue to be numeric.
"""
- self.length = length
_NumericType.__init__(self, **kw)
- sqltypes.Float.__init__(self, precision, asdecimal=asdecimal)
+ sqltypes.Float.__init__(self, asdecimal=asdecimal)
+ self.length = length
+ self.precision = precision
def get_col_spec(self):
- if hasattr(self, 'length') and self.length is not None:
+ if self.length is not None and self.precision is not None:
return self._extend("FLOAT(%s, %s)" % (self.precision, self.length))
elif self.precision is not None:
return self._extend("FLOAT(%s)" % (self.precision,))
@@ -1284,6 +1323,8 @@ colspecs = {
sqltypes.NCHAR: MSNChar,
sqltypes.TIMESTAMP: MSTimeStamp,
sqltypes.BLOB: MSBlob,
+ MSDouble: MSDouble,
+ MSReal: MSReal,
_BinaryType: _BinaryType,
}
@@ -1798,15 +1839,46 @@ class MySQLCompiler(compiler.DefaultCompiler):
sql_operators.mod: '%%'
})
- def visit_cast(self, cast, **kwargs):
- if isinstance(cast.type, (sqltypes.Date, sqltypes.Time,
- sqltypes.DateTime)):
- return super(MySQLCompiler, self).visit_cast(cast, **kwargs)
+ def visit_typeclause(self, typeclause):
+ type_ = typeclause.type.dialect_impl(self.dialect)
+ if isinstance(type_, MSInteger):
+ if getattr(type_, 'unsigned', False):
+ return 'UNSIGNED INTEGER'
+ else:
+ return 'SIGNED INTEGER'
+ elif isinstance(type_, (MSChar, MSDecimal, MSDateTime,
+ MSDate, MSTime)):
+ return type_.get_col_spec()
+ elif isinstance(type_, (MSText, MSNChar, MSNVarChar)):
+ return 'CHAR'
+ elif type(type_) is MSString:
+ if getattr(type_, 'length'):
+ return 'CHAR(%s)' % type_.length
+ else:
+ return 'CHAR'
+ elif isinstance(type_, _BinaryType):
+ return 'BINARY'
+ elif isinstance(type_, MSNumeric):
+ return type_.get_col_spec().replace('NUMERIC', 'DECIMAL')
+ elif isinstance(type_, MSTimeStamp):
+ return 'DATETIME'
+ elif isinstance(type_, (MSDateTime, MSDate, MSTime)):
+ return type_.get_col_spec()
else:
- # so just skip the CAST altogether for now.
- # TODO: put whatever MySQL does for CAST here.
+ return None
+
+ def visit_cast(self, cast, **kwargs):
+ # No cast until 4, no decimals until 5.
+ type_ = self.process(cast.typeclause)
+ if type_ is None:
return self.process(cast.clause)
+ if self.stack and self.stack[-1].get('select'):
+ # not sure if we want to set the typemap here...
+ self.typemap.setdefault("CAST", cast.type)
+ return 'CAST(%s AS %s)' % (self.process(cast.clause), type_)
+
+
def get_select_precolumns(self, select):
if isinstance(select._distinct, basestring):
return select._distinct.upper() + " "