[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r6901 - in trunk/gnue-appserver/src: . language
From: |
johannes |
Subject: |
[gnue] r6901 - in trunk/gnue-appserver/src: . language |
Date: |
Fri, 14 Jan 2005 02:34:51 -0600 (CST) |
Author: johannes
Date: 2005-01-14 02:34:49 -0600 (Fri, 14 Jan 2005)
New Revision: 6901
Modified:
trunk/gnue-appserver/src/data.py
trunk/gnue-appserver/src/geasFilter.py
trunk/gnue-appserver/src/geasSession.py
trunk/gnue-appserver/src/language/Object.py
Log:
Indirect properties are linked in using "LEFT OUTER JOINS", access to indirect
properties with intermediate 'NULL' values is possible (like foo.bar.baz)
without an exception
Modified: trunk/gnue-appserver/src/data.py
===================================================================
--- trunk/gnue-appserver/src/data.py 2005-01-14 03:23:01 UTC (rev 6900)
+++ trunk/gnue-appserver/src/data.py 2005-01-14 08:34:49 UTC (rev 6901)
@@ -444,31 +444,36 @@
def _createDatasource (connections, database, content, order = None):
# build table list, field list, and join condition
+ master = []
tables = []
fields = []
conditions = None
for (alias, (table, fk_alias, fk_field, fieldlist)) in content.items ():
if alias:
- tables.append (table + ' ' + alias)
+ if not fk_alias:
+ master.append ((None, table + ' ' + alias))
fields.extend ([alias + '.' + field for field in fieldlist])
else:
- tables.append (table)
+ master.append ((None, table))
fields.extend (fieldlist)
+
if fk_alias:
- # FIXME: Instead of a condition we better create a 'LEFT JOIN' later
- c = GConditions.buildTreeFromList (
- ['eq', ['field', alias + u'.gnue_id'],
- ['field', fk_alias + u'.' + fk_field]])
- if conditions:
- conditions = GConditions.combineConditions (conditions, c)
- else:
- conditions = c
+ table = u"LEFT JOIN %s %s ON %s.gnue_id = %s.%s" % \
+ (table, alias, alias, fk_alias, fk_field)
+ tables.append ((alias, table))
+ # After building up the table sequences we need to make sure they're sorted
+ # by their alias, otherwise the left outer joins won't work.
+ master.sort ()
+ tables.sort ()
+
# prepare attributes of the datasource
attributes = {}
attributes ['name'] = ''
attributes ['database'] = database
- attributes ['table'] = string.join (tables, ', ')
+ attributes ['table'] = "%s %s" % \
+ (string.join ([m [1] for m in master], ','),
+ string.join ([t [1] for t in tables], ' '))
attributes ['primarykey'] = 'gnue_id'
# give the backend a hint that it's working for appserver :)
@@ -936,23 +941,31 @@
else:
id = self.__resultSet.current [u'gnue_id']
- # build the record object
- r = record (self.__cache, self.__connections, self.__database, table, id)
- r._fill (alias, fields, self.__resultSet.current)
- records [alias] = r
+ if id:
+ # build the record object
+ r = record (self.__cache, self.__connections, self.__database,
+ table, id)
+ r._fill (alias, fields, self.__resultSet.current)
+ records [alias] = r
- # the table having no join condition is the "main" table
- if not fk_alias:
- result = r
+ # the table having no join condition is the "main" table
+ if not fk_alias:
+ result = r
# iterate again to put the foreign keys in the cache
for (alias, (table, fk_alias, fk_field, fields)) in self.__content.items():
if fk_alias:
- (records [fk_alias])._cache (fk_field,
- (records [alias]).getField (u'gnue_id'))
+ if records.has_key (alias):
+ value = records [alias].getField (u'gnue_id')
+ else:
+ value = None
+ if records.has_key (fk_alias):
+ records [fk_alias]._cache (fk_field, value)
+
return result
+
# ---------------------------------------------------------------------------
# Return the first record
# ---------------------------------------------------------------------------
Modified: trunk/gnue-appserver/src/geasFilter.py
===================================================================
--- trunk/gnue-appserver/src/geasFilter.py 2005-01-14 03:23:01 UTC (rev
6900)
+++ trunk/gnue-appserver/src/geasFilter.py 2005-01-14 08:34:49 UTC (rev
6901)
@@ -89,7 +89,7 @@
fields.sort ()
classdef = self.__sm.classes.find (fId)
- master = classdef.gnue_filter
+ master = classdef.gnue_filter and classdef.gnue_filter or None
if master is not None:
master = self.__sm.classes.find (master.gnue_id).fullName
@@ -127,7 +127,7 @@
# First get all filters defined in class repository
for klass in self.__sm.classes.values ():
- if klass.gnue_filter is not None:
+ if klass.gnue_filter:
self.__addFilter (klass.gnue_filter)
result = []
@@ -156,7 +156,7 @@
if not self.__fDict.has_key (filterId):
self.__fDict [filterId] = []
- if filterClass.gnue_filter is not None:
+ if filterClass.gnue_filter:
refId = filterClass.gnue_filter.gnue_id
if not refId in self.__fDict [filterId]:
self.__fDict [filterId].append (refId)
Modified: trunk/gnue-appserver/src/geasSession.py
===================================================================
--- trunk/gnue-appserver/src/geasSession.py 2005-01-14 03:23:01 UTC (rev
6900)
+++ trunk/gnue-appserver/src/geasSession.py 2005-01-14 08:34:49 UTC (rev
6901)
@@ -469,7 +469,7 @@
instance = geasInstance.geasInstance (self, self.__connection, record,
classdef)
- if classdef.gnue_filter is not None:
+ if classdef.gnue_filter:
fId = classdef.gnue_filter.gnue_id
fName = self.sm.classes.find (fId).fullName
instance.put ([fName], [self.__filterValue (fId)])
@@ -667,7 +667,7 @@
else:
raise ConditionDataTypeError, condition
- if classdef.gnue_filter is not None:
+ if classdef.gnue_filter:
useFilter = True
filterName = self.sm.classes.find (classdef.gnue_filter.gnue_id).fullName
cList = cTree.findChildrenOfType ('GCCField', allowAllChildren = True)
@@ -726,7 +726,7 @@
def __filterCondition (self, classdef):
- if classdef.gnue_filter is not None:
+ if classdef.gnue_filter:
filterId = classdef.gnue_filter.gnue_id
filterName = self.sm.classes.find (filterId).fullName
filterCond = GConditions.buildConditionFromDict ( \
Modified: trunk/gnue-appserver/src/language/Object.py
===================================================================
--- trunk/gnue-appserver/src/language/Object.py 2005-01-14 03:23:01 UTC (rev
6900)
+++ trunk/gnue-appserver/src/language/Object.py 2005-01-14 08:34:49 UTC (rev
6901)
@@ -92,6 +92,13 @@
# Convert reference fields to object references
if '_' in datatype and value is not None:
return Object (self.__session, datatype, value)
+
+ elif value is None:
+ if '_' in datatype:
+ return NullObject ()
+ else:
+ return None
+
else:
return value
@@ -177,3 +184,111 @@
self.__session.getSessionManager ().delete (
self.__session.getSessionId (), self.__class, [self.objectId])
self.objectId = None
+
+
+# =============================================================================
+# Class implementing None values for reference-properties
+# =============================================================================
+
+class NullObject:
+
+ # ---------------------------------------------------------------------------
+ # Property access method
+ # ---------------------------------------------------------------------------
+
+ def __getattr__ (self, attr):
+ """
+ This function simulates access to a property of the instance by returning
+ itself, so a following, property access will still work.
+
+ @return: self
+ """
+ return self
+
+
+ # ---------------------------------------------------------------------------
+ # Truth-test
+ # ---------------------------------------------------------------------------
+
+ def __nonzero__ (self):
+ """
+ A NullObject instance always has a truth-value of 'False' (like None has).
+ This is used for constructs like: "if x: ..."
+ """
+ return False
+
+
+ # ---------------------------------------------------------------------------
+ # Rich comparison
+ # ---------------------------------------------------------------------------
+
+ def __cmp__ (self, other):
+ """
+ An instance of NullObject is True if, and only if, the object compared with
+ is None. This comparison is usually used for sorting.
+ """
+
+ return cmp (None, other)
+
+ # ---------------------------------------------------------------------------
+ # Comparison: equality
+ # ---------------------------------------------------------------------------
+
+ def __eq__ (self, other):
+ """
+ An instance of NullObject is equal only to None
+ """
+
+ return other is None
+
+
+ # ---------------------------------------------------------------------------
+ # Comparison: inequality
+ # ---------------------------------------------------------------------------
+
+ def __ne__ (self, other):
+ """
+ An instance of NullObject is equal only to None
+ """
+
+ return other is not None
+
+
+ # ---------------------------------------------------------------------------
+ # Official string representation
+ # ---------------------------------------------------------------------------
+
+ def __repr__ (self):
+ """
+ This function returns the official string representation of an instance
+ """
+
+ return "<NullObject at %s>" % hex (id (self))
+
+
+ # ---------------------------------------------------------------------------
+ # Informal string represenation
+ # ---------------------------------------------------------------------------
+
+ def __str__ (self):
+ """
+ The informal representation is just 'empty'
+ """
+ return ''
+
+
+# =============================================================================
+# Small unit test
+# =============================================================================
+
+if __name__ == '__main__':
+ x = NullObject ()
+ print x is None
+ print x == None
+ if x:
+ print "ok"
+ else:
+ print "nope"
+
+ print "x.y=", x.y
+ print "x.a.b.c=", x.a.b.c, repr (x.a.b.c)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r6901 - in trunk/gnue-appserver/src: . language,
johannes <=