[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r7233 - trunk/gnue-appserver/src
From: |
johannes |
Subject: |
[gnue] r7233 - trunk/gnue-appserver/src |
Date: |
Sun, 20 Mar 2005 08:08:14 -0600 (CST) |
Author: johannes
Date: 2005-03-20 08:08:13 -0600 (Sun, 20 Mar 2005)
New Revision: 7233
Modified:
trunk/gnue-appserver/src/data.py
trunk/gnue-appserver/src/geasInstance.py
Log:
commit () takes care of constraints automatically
Modified: trunk/gnue-appserver/src/data.py
===================================================================
--- trunk/gnue-appserver/src/data.py 2005-03-20 12:35:44 UTC (rev 7232)
+++ trunk/gnue-appserver/src/data.py 2005-03-20 14:08:13 UTC (rev 7233)
@@ -600,6 +600,7 @@
self.__confirmedCache = None
self.__confirmedInserts = []
self.__confirmedDeletes = []
+ self.__constraints = {}
self.__uuidType = gConfig ('uuidtype').lower ()
@@ -666,18 +667,7 @@
return recordset (self.__cache, self.__connections, self.__database,
content, _conditionTree (conditions), order)
- # ---------------------------------------------------------------------------
- # Generate a new object id
- # ---------------------------------------------------------------------------
- def __generateId (self):
-
- if self.__uuidType == 'time':
- return UUID.generateTimeBased ()
- else:
- return UUID.generateRandom ()
-
-
# ---------------------------------------------------------------------------
# Create a new record
# ---------------------------------------------------------------------------
@@ -690,7 +680,11 @@
"""
checktype (table, UnicodeType)
- id = self.__generateId ()
+ if self.__uuidType == 'time':
+ id = UUID.generateTimeBased ()
+ else:
+ id = UUID.generateRandom ()
+
r = record (self.__cache, self.__connections, self.__database, table, id)
self.__cache.write (table, id, u'gnue_id', None, 0) # old id is None
self.__cache.write (table, id, u'gnue_id', id, 1) # new id
@@ -769,6 +763,24 @@
# ---------------------------------------------------------------------------
+ # Add constraints for a table
+ # ---------------------------------------------------------------------------
+
+ def setConstraints (self, table, constraints):
+ """
+ Add constraints for a given table.
+
+ @param table: name of the table to add constraints for
+ @param constraints: sequence of master-tables for the given table
+ """
+
+ if len (constraints):
+ cdict = self.__constraints.setdefault (table.lower (), {})
+ for item in constraints:
+ cdict [item.lower ()] = True
+
+
+ # ---------------------------------------------------------------------------
# Write all changes back to the database
# ---------------------------------------------------------------------------
@@ -784,10 +796,10 @@
recNo = 0
# first perform all inserts
- for (table, row) in self.__inserted [:]:
- recNo += 1
- if self.__cache.status (table, row) == 'inserted':
+ if self.__inserted:
+ for (table, row) in self.__orderInserts ():
fields = tables [table] [row]
+ recNo += 1
backend.insert (table, fields, recNo)
self.__inserted.remove ((table, row))
@@ -797,6 +809,7 @@
self.__cache.makeClean (table, row)
+
# second perform all updates
for (table, rows) in tables.items ():
for (row, fields) in rows.items ():
@@ -808,10 +821,11 @@
self.__cache.makeClean (table, row)
# perform all deletes
- for (table, row) in self.__deleted:
- recNo += 1
- backend.delete (table, {'gnue_id': row}, recNo)
- self.__cache.remove (table, row)
+ if len (self.__deleted):
+ for (table, row) in self.__orderDeletes ():
+ recNo += 1
+ backend.delete (table, {'gnue_id': row}, recNo)
+ self.__cache.remove (table, row)
self.__deleted = []
@@ -829,6 +843,108 @@
# ---------------------------------------------------------------------------
+ # Create an ordered sequence of new records
+ # ---------------------------------------------------------------------------
+
+ def __orderInserts (self):
+ """
+ Order all records scheduled for insertion, so constraint violations are
+ avoided.
+
+ @return: sequence of (table, row) tuples in a sane order for insertion
+ """
+
+ records = [(table, row) for (table, row) in self.__inserted \
+ if self.__cache.status (table, row) == 'inserted']
+ return self.__orderByDependency (records)
+
+
+ # ---------------------------------------------------------------------------
+ # Order all records scheduled for deletion
+ # ---------------------------------------------------------------------------
+
+ def __orderDeletes (self):
+ """
+ Order all records scheduled for deletion, so constraint violations are
+ avoided.
+
+ @return: sequence of (table, row) tuples in a sane order for deletion
+ """
+
+ order = self.__orderByDependency (self.__deleted)
+ # since we do deletes we need a reversed order
+ order.reverse ()
+
+ return order
+
+
+ # ---------------------------------------------------------------------------
+ # Order a sequence of (table, row) tuples by their dependencies
+ # ---------------------------------------------------------------------------
+
+ def __orderByDependency (self, records):
+ """
+ Order a sequence of records (table, row) so their dependencies given by
+ setConstraints () are fullfilled. The result starts with elements having no
+ dependency at all.
+
+ @param records: sequence with (table, row) tuples
+ @return: ordered sequence with (table, row) tuples
+ """
+
+ tables = {}
+ data = {}
+
+ # First create a dictionary with all tables scheduled for processing
+ for (table, row) in records:
+
+ tables [table] = []
+ rows = data.setdefault (table, [])
+ rows.append ((table, row))
+
+ # Now, add all those constraints which are also scheduled for insertion.
+ # This eliminates constraints which are currently NULL.
+ for (table, deps) in tables.items ():
+ if self.__constraints.has_key (table):
+ for constraint in self.__constraints [table].keys ():
+ if tables.has_key (constraint):
+ deps.append (constraint)
+
+ # Now create an ordered sequence taking care of dependencies
+ order = []
+
+ while tables:
+ addition = []
+
+ for (table, deps) in tables.items ():
+ # If a table has no dependencies, add it to the result
+ if not len (deps):
+ addition.append (table)
+
+ # and remove that table from all other tables dependency sequence
+ for ref in tables.values ():
+ if table in ref:
+ ref.remove (table)
+
+ # finally remove it from the dictionary
+ del tables [table]
+
+ # If no tables without a dependency was found, but there are still
+ # entries in the tables dictionary, they *must* have circular references
+ if not len (addition) and len (tables):
+ raise CircularReferencesError
+
+ order.extend (addition)
+
+ # And finally flatten everything to a sequence of tuples
+ result = []
+ for table in order:
+ result.extend (data [table])
+
+ return result
+
+
+ # ---------------------------------------------------------------------------
# Undo all changes
# ---------------------------------------------------------------------------
Modified: trunk/gnue-appserver/src/geasInstance.py
===================================================================
--- trunk/gnue-appserver/src/geasInstance.py 2005-03-20 12:35:44 UTC (rev
7232)
+++ trunk/gnue-appserver/src/geasInstance.py 2005-03-20 14:08:13 UTC (rev
7233)
@@ -103,6 +103,9 @@
self.__record = record
self.__classdef = classdef
+ self.__connection.setConstraints (classdef.table, classdef.masters.keys ())
+
+
# ---------------------------------------------------------------------------
# Convert a value into the given type if possible
# ---------------------------------------------------------------------------
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7233 - trunk/gnue-appserver/src,
johannes <=