Author: phd
Date: 2007-03-02 08:48:25 -0700 (Fri, 02 Mar 2007)
New Revision: 2377
Modified:
home/phd/SQLObject/paramstyles/sqlobject/col.py
home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py
home/phd/SQLObject/paramstyles/sqlobject/main.py
home/phd/SQLObject/paramstyles/sqlobject/mysql/mysqlconnection.py
home/phd/SQLObject/paramstyles/sqlobject/sqlbuilder.py
Log:
Merged patches from the revisions 2360:2376 from the trunk
Modified: home/phd/SQLObject/paramstyles/sqlobject/col.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/col.py 2007-03-02 15:42:13 UTC (rev 2376)
+++ home/phd/SQLObject/paramstyles/sqlobject/col.py 2007-03-02 15:48:25 UTC (rev 2377)
@@ -112,6 +112,7 @@
creationOrder,
dbName=None,
default=NoDefault,
+ defaultSQL=None,
foreignKey=None,
alternateID=False,
alternateMethodName=None,
@@ -178,6 +179,7 @@
self.name = name
self.soClass = soClass
self._default = default
+ self.defaultSQL = defaultSQL
self.customSQLType = sqlType
# deal with foreign keys
@@ -293,6 +295,8 @@
result.append('NOT NULL')
if self.unique or self.alternateID:
result.append('UNIQUE')
+ if self.defaultSQL is not None:
+ result.append("DEFAULT %s" % self.defaultSQL)
return result
def _sqlType(self):
@@ -594,6 +598,11 @@
class SOIntCol(SOCol):
# 3-03 @@: support precision, maybe max and min directly
+ def __init__(self, **kw):
+ self.length = popKey(kw, 'length')
+ self.unsigned = bool(popKey(kw, 'unsigned'))
+ self.zerofill = bool(popKey(kw, 'unsigned'))
+ SOCol.__init__(self, **kw)
def autoConstraints(self):
return [consts.isInt]
@@ -602,12 +611,54 @@
return [IntValidator(name=self.name)] + \
super(SOIntCol, self).createValidators()
+ def addSQLAttrs(self, str):
+ _ret = str
+ if str is None or len(str) < 1:
+ return None
+
+ if self.length >= 1:
+ _ret = "%s(%d)" % (_ret, self.length)
+ if self.unsigned:
+ _ret = _ret + " UNSIGNED"
+ if self.zerofill:
+ _ret = _reg + " ZEROFILL"
+ return _ret
+
def _sqlType(self):
- return 'INT'
+ return self.addSQLAttrs("INT")
class IntCol(Col):
baseClass = SOIntCol
+class SOTinyIntCol(SOIntCol):
+ def _sqlTyps(self):
+ return self.addSQLAttrs("TINYINT")
+
+class TinyIntCol(Col):
+ baseClass = SOTinyIntCol
+
+class SOSmallIntCol(SOIntCol):
+ def _sqlTyps(self):
+ return self.addSQLAttrs("SMALLINT")
+
+class SmallIntCol(Col):
+ baseClass = SOSmallIntCol
+
+class SOMediumIntCol(SOIntCol):
+ def _sqlTyps(self):
+ return self.addSQLAttrs("MEDIUMINT")
+
+class MediumIntCol(Col):
+ baseClass = SOMediumIntCol
+
+class SOBigIntCol(SOIntCol):
+ def _sqlTyps(self):
+ return self.addSQLAttrs("BIGINT")
+
+class BigIntCol(Col):
+ baseClass = SOBigIntCol
+
+
class BoolValidator(validators.Validator):
def to_python(self, value, state):
@@ -940,6 +991,43 @@
baseClass = SOEnumCol
+class SetValidator(validators.Validator):
+ """
+ Translates Python tuples into SQL comma-delimited SET strings.
+ """
+
+ def to_python(self, value, state):
+ if not isinstance(value, str):
+ raise validators.Invalid("expected a value string, got % instead" % \
+ (value), value, state)
+ return tuple(value.split(","))
+
+ def from_python(self, value, state):
+ if not isinstance(value, tuple):
+ value = (value,)
+ return ",".join([v for v in value])
+
+class SOSetCol(SOCol):
+ def __init__(self, **kw):
+ self.setValues = popKey(kw, 'setValues', None)
+ assert self.setValues is not None, \
+ 'You must provide a setValues keyword argument'
+ super(SOSetCol, self).__init__(**kw)
+
+ def autoConstraints(self):
+ return [consts.isString, consts.InList(self.setValues)]
+
+ def createValidators(self):
+ return [SetValidator(name = self.name, setValues = self.setValues)] + \
+ super(SOSetCol, self).createValidators()
+
+ def _mysqlType(self):
+ return "SET(%s)" % ', '.join([sqlbuilder.sqlrepr(v, 'mysql') for v in self.enumValues])
+
+class SetCol(Col):
+ baseClass = SOSetCol
+
+
if datetime_available:
class DateTimeValidator(validators.DateValidator):
def to_python(self, value, state):
@@ -1063,7 +1151,6 @@
% DATETIME_IMPLEMENTATION)
now = staticmethod(now)
-
if datetime_available:
class DateValidator(DateTimeValidator):
def to_python(self, value, state):
@@ -1180,6 +1267,21 @@
baseClass = SOTimeCol
+class SOTimestampCol(SODateTimeCol):
+ """
+ Necessary to support MySQL's use of TIMESTAMP versus DATETIME types
+ """
+
+ def __init__(self, **kw):
+ SOCol.__init__(self, **kw)
+
+ def _mysqlType(self):
+ return 'TIMESTAMP'
+
+class TimestampCol(Col):
+ baseClass = SOTimestampCol
+
+
try:
from decimal import Decimal
except ImportError:
@@ -1355,6 +1457,7 @@
class PickleCol(BLOBCol):
baseClass = SOPickleCol
+
def popKey(kw, name, default=None):
if not kw.has_key(name):
return default
Modified: home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py 2007-03-02 15:42:13 UTC (rev 2376)
+++ home/phd/SQLObject/paramstyles/sqlobject/dbconnection.py 2007-03-02 15:48:25 UTC (rev 2377)
@@ -555,12 +555,13 @@
self.query(self._SO_createJoinTableSQL(join))
def _SO_createJoinTableSQL(self, join):
- return ('CREATE TABLE %s (\n%s %s,\n%s %s\n)' %
+ return ('CREATE TABLE %s (\n%s %s,\n%s %s\n) %s' %
(join.intermediateTable,
join.joinColumn,
self.joinSQLType(join),
join.otherColumn,
- self.joinSQLType(join)))
+ self.joinSQLType(join),
+ self.getDBOptions(join)))
def _SO_dropJoinTable(self, join):
self.query("DROP TABLE %s" % join.intermediateTable)
@@ -606,10 +607,18 @@
def createTableSQL(self, soClass):
constraints = self.createReferenceConstraints(soClass)
extraSQL = self.createSQL(soClass)
- createSql = ('CREATE TABLE %s (\n%s\n)' %
- (soClass.sqlmeta.table, self.createColumns(soClass)))
+ createSql = ('CREATE TABLE %s (\n%s\n) %s' %
+ (soClass.sqlmeta.table, self.createColumns(soClass),
+ self.getDBOptions(soClass)))
return createSql, constraints + extraSQL
+ def getDBOptions(self, soClass):
+ if soClass.sqlmeta.engineSQL is not None and \
+ len(soClass.sqlmeta.engineSQL) > 0:
+ return "ENGINE = %s" % soClass.sqlmeta.engineSQL
+ else:
+ return ""
+
def createColumns(self, soClass):
columnDefs = [self.createIDColumn(soClass)] \
+ [self.createColumn(soClass, col)
Modified: home/phd/SQLObject/paramstyles/sqlobject/main.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/main.py 2007-03-02 15:42:13 UTC (rev 2376)
+++ home/phd/SQLObject/paramstyles/sqlobject/main.py 2007-03-02 15:48:25 UTC (rev 2377)
@@ -200,6 +200,8 @@
# Default is false, but we set it to true for the *instance*
# when necessary: (bad clever? maybe)
expired = False
+ # Engine SQL; currently used for MySQL engine ("MyISAM", "InnoDB", etc.)
+ engineSQL = None
# This is a mapping from column names to SOCol (or subclass)
# instances:
@@ -1231,7 +1233,8 @@
default = column.default
# If we don't get it, it's an error:
- if default is NoDefault:
+ # If we specified an SQL DEFAULT, then we should use that
+ if default is NoDefault and column.defaultSQL is not None:
raise TypeError, "%s() did not get expected keyword argument %s" % (self.__class__.__name__, column.name)
# Otherwise we put it in as though they did pass
# that keyword:
@@ -1453,6 +1456,7 @@
continue
if join.soClass.__name__ > join.otherClass.__name__:
continue
+ join.engineSQL = cls.sqlmeta.engineSQL
joins.append(join)
return joins
_getJoinsToCreate = classmethod(_getJoinsToCreate)
Modified: home/phd/SQLObject/paramstyles/sqlobject/mysql/mysqlconnection.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/mysql/mysqlconnection.py 2007-03-02 15:42:13 UTC (rev 2376)
+++ home/phd/SQLObject/paramstyles/sqlobject/mysql/mysqlconnection.py 2007-03-02 15:48:25 UTC (rev 2377)
@@ -236,6 +236,10 @@
'varchar': False}
elif t.startswith('datetime'):
return col.DateTimeCol, {}
+ elif t.startswith('date'):
+ return col.DateCol, {}
+ elif t.startswith('timestamp'):
+ return col.TimestampCol, {}
elif t.startswith('bool'):
return col.BoolCol, {}
elif t.startswith('tinyblob'):
Modified: home/phd/SQLObject/paramstyles/sqlobject/sqlbuilder.py
===================================================================
--- home/phd/SQLObject/paramstyles/sqlobject/sqlbuilder.py 2007-03-02 15:42:13 UTC (rev 2376)
+++ home/phd/SQLObject/paramstyles/sqlobject/sqlbuilder.py 2007-03-02 15:48:25 UTC (rev 2377)
@@ -369,10 +369,14 @@
SQLObjectField.__init__(self, tableName, fieldName, original)
self.column = column
def __eq__(self, other):
+ if other is None:
+ return ISNULL(self)
if isinstance(other, unicode):
other = other.encode(self.column.dbEncoding)
return SQLOp('=', self, other)
def __ne__(self, other):
+ if other is None:
+ return ISNOTNULL(self)
if isinstance(other, unicode):
other = other.encode(self.column.dbEncoding)
return SQLOp('<>', self, other)
|