[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r7360 - in trunk/gnue-appserver: src tests
From: |
johannes |
Subject: |
[gnue] r7360 - in trunk/gnue-appserver: src tests |
Date: |
Wed, 13 Apr 2005 09:00:04 -0500 (CDT) |
Author: johannes
Date: 2005-04-13 09:00:02 -0500 (Wed, 13 Apr 2005)
New Revision: 7360
Modified:
trunk/gnue-appserver/src/data.py
trunk/gnue-appserver/src/geasInstance.py
trunk/gnue-appserver/src/geasRpcServer.py
trunk/gnue-appserver/src/repository.py
trunk/gnue-appserver/tests/data.py
Log:
Full support of fish-hooks, so order of inserts and deletes doesn't matter
Modified: trunk/gnue-appserver/src/data.py
===================================================================
--- trunk/gnue-appserver/src/data.py 2005-04-13 09:17:19 UTC (rev 7359)
+++ trunk/gnue-appserver/src/data.py 2005-04-13 14:00:02 UTC (rev 7360)
@@ -912,13 +912,15 @@
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
+ @param constraints: dictionary of master-tables for the given table
"""
- if len (constraints):
+ if constraints:
cdict = self.__constraints.setdefault (table.lower (), {})
- for item in constraints:
- cdict [item.lower ()] = True
+ for (reftable, refitems) in constraints.items ():
+ elements = cdict.setdefault (reftable.lower (), {})
+ for item in refitems:
+ elements [item] = True
# ---------------------------------------------------------------------------
@@ -1026,6 +1028,7 @@
tables = {}
data = {}
+ fishes = {}
gDebug (1, "Constraints: %s" % self.__constraints)
gDebug (1, "Unordered : %s" % records)
@@ -1046,8 +1049,11 @@
for (table, deps) in tables.items ():
if self.__constraints.has_key (table):
for constraint in self.__constraints [table]:
- if constraint != table and tables.has_key (constraint):
- deps.append (constraint)
+ if tables.has_key (constraint):
+ if constraint != table:
+ deps.append (constraint)
+ else:
+ fishes [table] = self.__constraints [table] [table]
# Now create an ordered sequence taking care of dependencies
order = []
@@ -1077,13 +1083,88 @@
# And finally flatten everything to a sequence of tuples
result = []
+ extend = result.extend
+
for table in order:
- result.extend (data [table])
+ if table in fishes:
+ extend (self.__fishSort (table, data [table], fishes [table]))
+ else:
+ extend (data [table])
return result
# ---------------------------------------------------------------------------
+ # Create an order within a table so it does not violate fish-hook constraints
+ # ---------------------------------------------------------------------------
+
+ def __fishSort (self, table, rows, constraints):
+ """
+ Sort all given rows of a table to not violate the given constraints.
+
+ @param table: name of the table
+ @param rows: sequence of tuples (table, rowid)
+ @param constraints: dictionary with all constraints per row
+
+ @result: ordered sequence of tuples (table, rowid)
+
+ @raises CircularReferenceError: if the given data contains reference cycles
+ """
+
+ # First create a dependency tree for all rows, holding a sequence of those
+ # rowids which must be processed before the current row
+ dTree = {}
+ for (t, row) in rows:
+ deps = dTree.setdefault (row, [])
+
+ r = record (self.__cache, self.__connections, self.__database, table,
row)
+ for depField in constraints:
+ value = r.getField (depField)
+ if value and value not in deps:
+ deps.append (value)
+
+ # After we have created a complete dependency tree, we need to remove all
+ # those rows from the master-sequences, which do not have a key in the tree
+ # itself. Usually these are rows not contained in the current operation
+ # (insertion/deletion) so we can assume that they do exist. Otherwise it
+ # would not be possible to set a reference in a newly inserted record to an
+ # existing record.
+ for deps in dTree.values ():
+ for row in deps [:]:
+ if not row in dTree:
+ deps.remove (row)
+
+ # Now create an ordered sequence taking care of dependencies
+ order = []
+
+ while dTree:
+ addition = []
+
+ for (detail, masters) in dTree.items ():
+ # If a row has no masters, add it to the result
+ if not len (masters):
+ addition.append (detail)
+
+ # and remove that row from all dependency sequence it occurs
+ for ref in dTree.values ():
+ if detail in ref:
+ ref.remove (detail)
+
+ # finally remove it from the dictionary
+ del dTree [detail]
+
+ # If no row without a dependency was found, but there are still
+ # entries in the dependency tree, they *must* have circular references
+ if not len (addition) and len (dTree):
+ raise CircularReferenceError
+
+ order.extend (addition)
+
+ return zip ([table] * len (order), order)
+
+
+
+ # ---------------------------------------------------------------------------
# Undo all changes
# ---------------------------------------------------------------------------
Modified: trunk/gnue-appserver/src/geasInstance.py
===================================================================
--- trunk/gnue-appserver/src/geasInstance.py 2005-04-13 09:17:19 UTC (rev
7359)
+++ trunk/gnue-appserver/src/geasInstance.py 2005-04-13 14:00:02 UTC (rev
7360)
@@ -103,7 +103,7 @@
self.__record = record
self.__classdef = classdef
- self.__connection.setConstraints (classdef.table, classdef.masters.keys ())
+ self.__connection.setConstraints (classdef.table, classdef.masters)
# ---------------------------------------------------------------------------
Modified: trunk/gnue-appserver/src/geasRpcServer.py
===================================================================
--- trunk/gnue-appserver/src/geasRpcServer.py 2005-04-13 09:17:19 UTC (rev
7359)
+++ trunk/gnue-appserver/src/geasRpcServer.py 2005-04-13 14:00:02 UTC (rev
7360)
@@ -40,7 +40,7 @@
from gnue.appserver import geasConfiguration
-_GC_DEBUG = False # Set this to True to activate garbage collection debugging
+_GC_DEBUG = True # Set this to True to activate garbage collection debugging
# =============================================================================
# RPC application class
Modified: trunk/gnue-appserver/src/repository.py
===================================================================
--- trunk/gnue-appserver/src/repository.py 2005-04-13 09:17:19 UTC (rev
7359)
+++ trunk/gnue-appserver/src/repository.py 2005-04-13 14:00:02 UTC (rev
7360)
@@ -546,14 +546,15 @@
# Add a given class as master of the class
# ---------------------------------------------------------------------------
- def addMasterClass (self, aMaster):
+ def addMasterClass (self, aProperty, aMaster):
"""
- This function adds a given class to the dictionary of master-classes.
+ Add a given class to the dictionary of master-classes.
+ @param aProperty: name of the property holding the pointer to master-class
@param aMaster: class wrapper instance to be added
"""
- self.masters [aMaster.fullName] = aMaster
+ self.masters.setdefault (aMaster.fullName, []).append (aProperty)
# ---------------------------------------------------------------------------
@@ -667,7 +668,7 @@
# If the property is a reference to another class, the referenced class
# is a master of this class
if r is not None:
- classes [self.gnue_class].addMasterClass (r)
+ classes [self.gnue_class].addMasterClass (self.fullName, r)
Modified: trunk/gnue-appserver/tests/data.py
===================================================================
--- trunk/gnue-appserver/tests/data.py 2005-04-13 09:17:19 UTC (rev 7359)
+++ trunk/gnue-appserver/tests/data.py 2005-04-13 14:00:02 UTC (rev 7360)
@@ -486,6 +486,10 @@
spocksId = orgCrew [-1].getField (u'gnue_id')
self.connection.deleteRecord (u'address_person', spocksId)
+ # And the captain becomes the senior of Checkov
+ orgCrew [-2].putField (u'address_senior',
+ u'00000000000000000000000000001100')
+
# And a new crew member signs on
new = self.connection.insertRecord (u'address_person')
new.initialized ()
@@ -553,6 +557,10 @@
(u'Pavel Andreievich Chekov', u'RU')]
self.assertEqual (expected, secData)
+ self.connection.setConstraints (u'address_person',
+ {u'address_country': {u'address_country': True},
+ u'address_person': {u'address_senior': True}})
+
self.remove = [(u'address_person', new.getField (u'gnue_id')),
(u'address_country', oz.getField (u'gnue_id'))]
@@ -582,14 +590,20 @@
spock.putField (u'address_meettime', u'6:30')
spock.putField (u'address_lastmeeting', u'2270-05-17 08:00')
spock.putField (u'address_human', False)
+ spock.putField (u'address_senior', u'00000000000000000000000000001100')
# This is a bit hackish cause we're changing the primary key
- spock.putField (u'gnue_id', '00000000000000000000000000001101')
+ spock.putField (u'gnue_id', u'00000000000000000000000000001101')
# Reset the country for McCoy to the US
mccoy = self.connection.findRecord (u'address_person',
u'00000000000000000000000000001102', [u'address_country'])
mccoy.putField (u'address_country', u'000000000000000000000020000000E3')
+ # Reassign Spock as Checkov's senior
+ checkov = self.connection.findRecord (u'address_person',
+ u'00000000000000000000000000001103', [u'address_senior'])
+ checkov.putField (u'address_senior', u'00000000000000000000000000001101')
+
# And remove newly added records
for (table, row) in self.remove:
self.connection.deleteRecord (table, row)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7360 - in trunk/gnue-appserver: src tests,
johannes <=