Author: phd
Date: 2005-10-05 12:53:53 +0000 (Wed, 05 Oct 2005)
New Revision: 1077
Added:
SQLObject/trunk/sqlobject/tests/test_cyclic_reference.py
Modified:
SQLObject/trunk/sqlobject/col.py
SQLObject/trunk/sqlobject/dbconnection.py
SQLObject/trunk/sqlobject/main.py
SQLObject/trunk/sqlobject/manager/command.py
SQLObject/trunk/sqlobject/postgres/pgconnection.py
SQLObject/trunk/sqlobject/sqlite/sqliteconnection.py
SQLObject/trunk/sqlobject/tests/dbtest.py
Log:
Applied a patch made by J. Paulo Fernandes Farias <jpa...@gm...>
that allows to create tables that mutually reference each other.
Modified: SQLObject/trunk/sqlobject/col.py
===================================================================
--- SQLObject/trunk/sqlobject/col.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/col.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -730,6 +730,10 @@
def postgresCreateSQL(self):
sql = SOKeyCol.postgresCreateSQL(self)
+ return sql
+
+ def postgresCreateReferenceConstraint(self):
+ sTName = self.soClass.sqlmeta.table
other = findClass(self.foreignKey, self.soClass.sqlmeta.registry)
tName = other.sqlmeta.table
idName = other.sqlmeta.idName
@@ -742,16 +746,16 @@
action = 'ON DELETE RESTRICT'
else:
action = ''
- constraint = ('CONSTRAINT %(colName)s_exists '
+ constraint = ('ALTER TABLE %(sTName)s ADD CONSTRAINT %(colName)s_exists '
'FOREIGN KEY (%(colName)s) '
'REFERENCES %(tName)s (%(idName)s) '
'%(action)s' %
{'tName': tName,
'colName': self.dbName,
'idName': idName,
- 'action': action})
- sql = ', '.join([sql, constraint])
- return sql
+ 'action': action,
+ 'sTName': sTName})
+ return constraint
def sybaseCreateSQL(self):
sql = SOKeyCol.sybaseCreateSQL(self)
Modified: SQLObject/trunk/sqlobject/dbconnection.py
===================================================================
--- SQLObject/trunk/sqlobject/dbconnection.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/dbconnection.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -513,11 +513,25 @@
assert 0, 'Implement in subclasses'
def createTable(self, soClass):
- self.query(self.createTableSQL(soClass))
+ createSql, constraints = self.createTableSQL(soClass)
+ self.query(createSql)
+ return constraints
+
+ def createReferenceConstraints(self, soClass):
+ refConstraints = [self.createReferenceConstraint(soClass, column) \
+ for column in soClass.sqlmeta.columnList \
+ if isinstance(column, col.SOForeignKey)]
+ refConstraintDefs = [constraint \
+ for constraint in refConstraints \
+ if constraint]
+ return refConstraintDefs
+
def createTableSQL(self, soClass):
- return ('CREATE TABLE %s (\n%s\n)' %
+ constraints = self.createReferenceConstraints(soClass)
+ createSql = ('CREATE TABLE %s (\n%s\n)' %
(soClass.sqlmeta.table, self.createColumns(soClass)))
+ return createSql, constraints
def createColumns(self, soClass):
columnDefs = [self.createIDColumn(soClass)] \
@@ -525,6 +539,9 @@
for col in soClass.sqlmeta.columnList]
return ",\n".join([" %s" % c for c in columnDefs])
+ def createReferenceConstraint(self, soClass, col):
+ assert 0, "Implement in subclasses"
+
def createColumn(self, soClass, col):
assert 0, "Implement in subclasses"
Modified: SQLObject/trunk/sqlobject/main.py
===================================================================
--- SQLObject/trunk/sqlobject/main.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/main.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -1305,24 +1305,25 @@
conn = connection or cls._connection
if ifNotExists and conn.tableExists(cls.sqlmeta.table):
return
- conn.createTable(cls)
+ constraints = conn.createTable(cls)
if createJoinTables:
cls.createJoinTables(ifNotExists=ifNotExists,
connection=conn)
if createIndexes:
cls.createIndexes(ifNotExists=ifNotExists,
connection=conn)
+ return constraints
createTable = classmethod(createTable)
def createTableSQL(cls, createJoinTables=True, connection=None,
createIndexes=True):
conn = connection or cls._connection
- sql = conn.createTableSQL(cls)
+ sql, constraints = conn.createTableSQL(cls)
if createJoinTables:
sql += '\n' + cls.createJoinTablesSQL(connection=conn)
if createIndexes:
sql += '\n' + cls.createIndexesSQL(connection=conn)
- return sql
+ return sql, constraints
createTableSQL = classmethod(createTableSQL)
def createJoinTables(cls, ifNotExists=False, connection=None):
Modified: SQLObject/trunk/sqlobject/manager/command.py
===================================================================
--- SQLObject/trunk/sqlobject/manager/command.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/manager/command.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -502,11 +502,20 @@
def command(self):
classes = self.classes()
+ allConstraints = []
for cls in classes:
if self.options.verbose >= 1:
print '-- %s from %s' % (
cls.__name__, cls.__module__)
- print cls.createTableSQL().strip() + ';\n'
+ createSql, constraints = cls.createTableSQL()
+ print createSql.strip() + ';\n'
+ allConstraints.append(constraints)
+ for constraints in allConstraints:
+ if constraints:
+ for constraint in constraints:
+ if constraint:
+ print constraint.strip() + ';\n'
+
class CommandList(Command):
@@ -540,6 +549,7 @@
created = 0
existing = 0
dbs_created = []
+ constraints = {}
for soClass in self.classes(require_some=True):
if (self.options.create_db
and soClass._connection not in dbs_created):
@@ -548,6 +558,8 @@
else:
print '(simulating; cannot create database)'
dbs_created.append(soClass._connection)
+ if soClass._connection not in constraints.keys():
+ constraints[soClass._connection] = []
exists = soClass._connection.tableExists(soClass.sqlmeta.table)
if v >= 1:
if exists:
@@ -562,12 +574,22 @@
if self.options.interactive:
if self.ask('Create %s' % soClass.__name__):
created += 1
- soClass.createTable()
+ tableConstraints = soClass.createTable()
+ if tableConstraints:
+ constraints[soClass._connection].append(tableConstraints)
+
else:
print 'Cancelled'
else:
created += 1
- soClass.createTable()
+ tableConstraints = soClass.createTable()
+ if tableConstraints:
+ constraints[soClass._connection].append(tableConstraints)
+ for connection in constraints.keys():
+ for constraintList in constraints[connection]:
+ for constraint in constraintList:
+ if constraint:
+ connection.query(constraint)
if v >= 1:
print '%i tables created (%i already exist)' % (
created, existing)
Modified: SQLObject/trunk/sqlobject/postgres/pgconnection.py
===================================================================
--- SQLObject/trunk/sqlobject/postgres/pgconnection.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/postgres/pgconnection.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -138,6 +138,9 @@
def createColumn(self, soClass, col):
return col.postgresCreateSQL()
+ def createReferenceConstraint(self, soClass, col):
+ return col.postgresCreateReferenceConstraint()
+
def createIndexSQL(self, soClass, index):
return index.postgresCreateIndexSQL(soClass)
Modified: SQLObject/trunk/sqlobject/sqlite/sqliteconnection.py
===================================================================
--- SQLObject/trunk/sqlobject/sqlite/sqliteconnection.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/sqlite/sqliteconnection.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -116,6 +116,9 @@
def createColumn(self, soClass, col):
return col.sqliteCreateSQL()
+ def createReferenceConstraint(self, soClass, col):
+ return None
+
def createIDColumn(self, soClass):
return '%s INTEGER PRIMARY KEY' % soClass.sqlmeta.idName
Modified: SQLObject/trunk/sqlobject/tests/dbtest.py
===================================================================
--- SQLObject/trunk/sqlobject/tests/dbtest.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/tests/dbtest.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -137,7 +137,7 @@
sql = instance.createSQL
else:
sql = None
- newSQL = soClass.createTableSQL()
+ newSQL, constraints = soClass.createTableSQL()
if sql != newSQL:
if sql is not None:
instance.destroySelf()
@@ -164,7 +164,7 @@
if sql:
soClass._connection.query(sql)
else:
- sql = soClass.createTableSQL()
+ sql, constraints = soClass.createTableSQL()
soClass.createTable()
cls(tableName=soClass.sqlmeta.table,
createSQL=sql,
Added: SQLObject/trunk/sqlobject/tests/test_cyclic_reference.py
===================================================================
--- SQLObject/trunk/sqlobject/tests/test_cyclic_reference.py 2005-10-04 19:41:23 UTC (rev 1076)
+++ SQLObject/trunk/sqlobject/tests/test_cyclic_reference.py 2005-10-05 12:53:53 UTC (rev 1077)
@@ -0,0 +1,48 @@
+from sqlobject import *
+from sqlobject.tests.dbtest import *
+
+class TestCyclicReferenceA(SQLObject):
+ class sqlmeta(sqlmeta):
+ idName = 'test_id_here'
+ table = 'test_cyclic_reference_a_table'
+ name = StringCol()
+ number = IntCol()
+ time = DateTimeCol()
+ short = StringCol(length=10)
+ blobcol = BLOBCol()
+ fkeyb = ForeignKey('TestCyclicReferenceB')
+
+class TestCyclicReferenceB(SQLObject):
+ class sqlmeta(sqlmeta):
+ idName = 'test_id_here'
+ table = 'test_cyclic_reference_b_table'
+ name = StringCol()
+ number = IntCol()
+ time = DateTimeCol()
+ short = StringCol(length=10)
+ blobcol = BLOBCol()
+ fkeya = ForeignKey('TestCyclicReferenceA')
+
+def test_cyclic_reference():
+ conn = getConnection()
+ TestCyclicReferenceA.setConnection(conn)
+ TestCyclicReferenceB.setConnection(conn)
+ TestCyclicReferenceA.dropTable(ifExists=True, cascade=True)
+ assert not conn.tableExists(TestCyclicReferenceA.sqlmeta.table)
+ TestCyclicReferenceB.dropTable(ifExists=True, cascade=True)
+ assert not conn.tableExists(TestCyclicReferenceB.sqlmeta.table)
+
+ constraints = TestCyclicReferenceA.createTable(ifNotExists=True)
+ print constraints
+ assert conn.tableExists(TestCyclicReferenceA.sqlmeta.table)
+ constraints += TestCyclicReferenceB.createTable(ifNotExists=True)
+ print constraints
+ assert conn.tableExists(TestCyclicReferenceB.sqlmeta.table)
+
+ for constraint in constraints:
+ conn.query(constraint)
+
+ TestCyclicReferenceA.dropTable(ifExists=True, cascade=True)
+ assert not conn.tableExists(TestCyclicReferenceA.sqlmeta.table)
+ TestCyclicReferenceB.dropTable(ifExists=True, cascade=True)
+ assert not conn.tableExists(TestCyclicReferenceB.sqlmeta.table)
|