[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
r5769 - in trunk: gnue-appserver/samples gnue-appserver/src gnue-common/
From: |
johannes |
Subject: |
r5769 - in trunk: gnue-appserver/samples gnue-appserver/src gnue-common/src/datasources gnue-common/src/datasources/drivers/appserver/appserver |
Date: |
Thu, 29 Apr 2004 12:57:47 -0500 (CDT) |
Author: johannes
Date: 2004-04-29 12:57:46 -0500 (Thu, 29 Apr 2004)
New Revision: 5769
Modified:
trunk/gnue-appserver/samples/sample.gfd
trunk/gnue-appserver/src/data.py
trunk/gnue-appserver/src/geasInstance.py
trunk/gnue-appserver/src/geasList.py
trunk/gnue-appserver/src/geasSession.py
trunk/gnue-common/src/datasources/GConditions.py
trunk/gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py
Log:
Calculated fields are now supported as conditions; GCondition-trees can be
evaluated now; removed multiple rereads of records from geasList.
Modified: trunk/gnue-appserver/samples/sample.gfd
===================================================================
--- trunk/gnue-appserver/samples/sample.gfd 2004-04-29 03:49:56 UTC (rev
5768)
+++ trunk/gnue-appserver/samples/sample.gfd 2004-04-29 17:57:46 UTC (rev
5769)
@@ -1,14 +1,51 @@
<?xml version="1.0" encoding="iso8859-1"?>
<form title="GNUe Application Server test">
- <datasource name="dtsPerson" connection="appserver" table="address_person"/>
+ <parameter name="von" default="2270-07-15 09:00"/>
+ <parameter name="bis" default="2270-09-15 20:00"/>
+ <datasource name="dtsPerson" connection="appserver" table="address_person">
+ <!--
+ <condition>
+ <and>
+ <between>
+ <cfield name="address_nextmeeting"/>
+ <cparam name="von"/>
+ <cparam name="bis"/>
+ </between>
+ <or>
+ <like>
+ <cfield name="address_street"/>
+ <cconst value="%street"/>
+ </like>
+ <or>
+ <eq>
+ <cfield name="address_zip"/>
+ <cconst value="6890"/>
+ </eq>
+ <eq>
+ <cfield name="address_zip"/>
+ <cconst value="6850"/>
+ </eq>
+ </or>
+ </or>
+ <ne>
+ <cfield name="address_name"/>
+ <cconst value="foo"/>
+ </ne>
+ </and>
+ </condition>
+ -->
+ </datasource>
<datasource name="dtsCountry" connection="appserver" table="address_country"
cache="250"/>
- <datasource name="dtsMCountry" connection="appserver"
table="address_country"/>
+ <datasource name="dtsMCountry" connection="appserver"
+ table="address_country"/>
<trigger name="showRecord" type="NAMED"><![CDATA[
- retval = dtsPerson.call("address_show", {})
- if retval is not None:
- print "retval =", retval
+ setParameter('next', blkPerson.inpHuman.get ())
+ dtsPerson.createResultSet ()
+ # retval = dtsPerson.call("address_show", {})
+ # if retval is not None:
+ # print "retval =", retval
]]></trigger>
<logic>
<block name="blkPerson" datasource="dtsPerson">
Modified: trunk/gnue-appserver/src/data.py
===================================================================
--- trunk/gnue-appserver/src/data.py 2004-04-29 03:49:56 UTC (rev 5768)
+++ trunk/gnue-appserver/src/data.py 2004-04-29 17:57:46 UTC (rev 5769)
@@ -308,8 +308,11 @@
condition_tree = None
else:
- raise GConditions.ConditionError, _("Invalid condition format")
+ condition_tree = conditions
+ # else:
+ # raise GConditions.ConditionError, _("Invalid condition format")
+
return datasource.createResultSet (condition_tree)
# -----------------------------------------------------------------------------
@@ -319,8 +322,11 @@
def _find (connections, database, table, row, fields):
content = {None: (table, None, None, fields)}
- conditions = [['eq', ''], ['field', u'gnue_id'], ['const', row]]
- resultSet = _createResultSet (connections, database, content, conditions, [])
+ condition = GConditions.GCondition ()
+ eq = GConditions.GCeq (condition)
+ GConditions.GCField (eq, 'gnue_id')
+ GConditions.GCConst (eq, row)
+ resultSet = _createResultSet (connections, database, content, condition, [])
resultSet.firstRecord ()
return resultSet
@@ -381,12 +387,11 @@
Alias names, table names, and field names all must be Unicode strings.
- @param conditions: The conditions. May be a GCondition tree, a list in
- prefix notation, or a dictionary. Field values in conditions must be
- in native Python type; in case of strings they must be Unicode. Field
- names in conditions must be Unicode. In case aliases are defined in
- the content paramter, field names in conditions must be in the format
- 'alias.field'.
+ @param conditions: The conditions. May be a GCondition tree Field values in
+ conditions must be in native Python type; in case of strings they must
+ be Unicode. Field names in conditions must be Unicode. In case
+ aliases are defined in the content paramter, field names in conditions
+ must be in the format 'alias.field'.
@param order: A list of Unicode strings telling the field names to order
by. In case aliases are defined in the content parameter, these field
Modified: trunk/gnue-appserver/src/geasInstance.py
===================================================================
--- trunk/gnue-appserver/src/geasInstance.py 2004-04-29 03:49:56 UTC (rev
5768)
+++ trunk/gnue-appserver/src/geasInstance.py 2004-04-29 17:57:46 UTC (rev
5769)
@@ -316,3 +316,9 @@
if value is None:
raise PropertyValueError (prop.fullName, None)
+
+ def __getitem__ (self, key):
+ return self.__getValue (key)
+
+ def has_key (self, key):
+ return self.__classdef.properties.has_key (key)
Modified: trunk/gnue-appserver/src/geasList.py
===================================================================
--- trunk/gnue-appserver/src/geasList.py 2004-04-29 03:49:56 UTC (rev
5768)
+++ trunk/gnue-appserver/src/geasList.py 2004-04-29 17:57:46 UTC (rev
5769)
@@ -34,58 +34,96 @@
# Initalize
# ---------------------------------------------------------------------------
- def __init__ (self, session, classdef, connection, recordset, propertylist):
+ def __init__ (self, session, classdef, connection, recordset, propertylist,
+ condition):
self.__session = session
self.__classdef = classdef
self.__connection = connection
self.__recordset = recordset
self.__prefetch = propertylist # property names to be prefetched
+ self.__condition = condition
+ self.__instances = []
+ self.__isComplete = False
+
# ---------------------------------------------------------------------------
- # Get the first instance in the list
+ # fill up the instance-cache with up to count instances
# ---------------------------------------------------------------------------
- def firstInstance (self):
- record = self.__recordset.firstRecord ()
- if record is not None:
- return geasInstance.geasInstance (self.__session, self.__connection,
- record, self.__classdef)
- else:
- return None
+ def __fillup (self, count):
+ """
+ This function fills the internal list of instances with up to count
+ elements. If @count is 0 all available instances are added to the list.
+ """
+ if self.__isComplete:
+ return
+ while len (self.__instances) < count or not count:
+ if self.__getInstance (len (self.__instances) == 0) is None:
+ break
+
+
# ---------------------------------------------------------------------------
- # Get the next instance in the list
+ # Get the next usable instance and add it to the instance list
# ---------------------------------------------------------------------------
- def nextInstance (self):
- record = self.__recordset.nextRecord ()
+ def __getInstance (self, fromStart = False):
+ """
+ This function fetches the next usable instance from the recordset according
+ to the list's condition. This instance will be added to the internal list
+ of instances and returned as the functions result.
+ """
+
+ if fromStart:
+ record = self.__recordset.firstRecord ()
+ else:
+ record = self.__recordset.nextRecord ()
+
+ self.__isComplete = record is None
+
if record is not None:
- return geasInstance.geasInstance (self.__session, self.__connection,
- record, self.__classdef)
+ instance = geasInstance.geasInstance (self.__session, self.__connection,
+ record, self.__classdef)
+ if self.__condition is not None:
+ if not self.__condition.eval (instance):
+ return self.__getInstance ()
+
+ self.__instances.append (instance)
+ return instance
+
else:
return None
+
# ---------------------------------------------------------------------------
# Get the length of the list (the number of entries)
# ---------------------------------------------------------------------------
def count (self):
- return self.__recordset.count ()
+ """
+ This function returns the number of instances available in this list.
+ """
+ self.__fillup (0)
+ return len (self.__instances)
+
# ---------------------------------------------------------------------------
# Fetch data from the database backend
# ---------------------------------------------------------------------------
def fetch (self, start, count):
- # negative value for start means starting from the end of the list
+ """
+ This function returns @count instances skipping the first @start instances.
+ If @start is negative, the starting point is from the end of the list.
+ """
+
if start < 0:
- start = self.count () + start
+ self.__fillup (0)
+ else:
+ self.__fillup (start + count)
+
result = []
- c = 0
- instance = self.firstInstance ()
- while (instance != None) and (c < start + count):
- if c >= start:
- result.append (instance.get (self.__prefetch))
- c += 1
- instance = self.nextInstance ()
+ for pos in range (start, min (start + count, len (self.__instances))):
+ result.append (self.__instances [pos].get (self.__prefetch))
+
return result
Modified: trunk/gnue-appserver/src/geasSession.py
===================================================================
--- trunk/gnue-appserver/src/geasSession.py 2004-04-29 03:49:56 UTC (rev
5768)
+++ trunk/gnue-appserver/src/geasSession.py 2004-04-29 17:57:46 UTC (rev
5769)
@@ -29,8 +29,10 @@
from gnue.appserver import data
import geasList, geasInstance
-from gnue.common.datasources.GConditions import buildTreeFromPrefix,
getXMLelements, GCField
+from gnue.common.datasources import GConditions
+from mx import DateTime
+
class InstanceNotFoundError (gException):
def __init__ (self, classname, objectId):
msg = u_("Instance '%(objectId)s' of class '%(classname)s' not found") \
@@ -38,6 +40,15 @@
'classname': classname }
gException.__init__ (self, msg)
+class ReferenceError (gException):
+ def __init__ (self, name, part):
+ msg = u_("Cannot resolve property name '%(name)s' because "
+ "'%(part)s' is not a reference property") \
+ % {'name': name,
+ 'part': part}
+ gException.__init__ (self, msg)
+
+
# =============================================================================
# Session class
# =============================================================================
@@ -97,8 +108,7 @@
for e in elements [:-1]:
p = c.properties [e]
if not p.isReference:
- raise gException, u_("Cannot resolve property name '%(name)s' because "
- "'%(part)s' is not a reference property")
+ raise ReferenceError, (propertyname, p.fullName)
c = p.referencedClass
# do we already have a link?
found = False
@@ -131,19 +141,15 @@
def __convertCondition (self, classdef, condition, contentdict):
- if isinstance (condition, ListType) and condition:
- if (isinstance (condition [0], StringType) or \
- isinstance (condition [0], UnicodeType)) and \
- condition [0] == 'field':
- if len (condition) == 2 and \
- (isinstance (condition [1], StringType) or \
- isinstance (condition [1], UnicodeType)):
- condition [1] = self.__getFieldname (classdef, condition [1],
- contentdict, False)
+ if condition is not None:
+ if isinstance (condition, GConditions.GCField):
+ condition.name = self.__getFieldname (classdef, condition.name,
+ contentdict, False)
else:
- for i in condition:
- self.__convertCondition (classdef, i, contentdict)
+ for child in condition._children:
+ self.__convertCondition (classdef, child, contentdict)
+
# ---------------------------------------------------------------------------
# Log into the application server
# ---------------------------------------------------------------------------
@@ -198,6 +204,8 @@
classdef = self.__getClassdef (classname)
+ (dsCond, asCond) = self.__splitCondition (conditions, classdef)
+
# Start to build the content dictionary for self.__connection.query()
content = {}
content [u't0'] = (classdef.table, None, None, [u'gnue_id'])
@@ -205,16 +213,19 @@
for p in propertylist:
self.__getFieldname (classdef, p, content, True)
- self.__convertCondition (classdef, conditions, content)
+ if asCond is not None:
+ self.__addConditionToContent (classdef, content, asCond)
+ self.__convertCondition (classdef, dsCond, content)
+
sortlist = []
for p in sortorder:
sortlist.append (self.__getFieldname (classdef, p, content, False))
- recordset = self.__connection.query (content, conditions, sortlist)
+ recordset = self.__connection.query (content, dsCond, sortlist)
list = geasList.geasList (self, classdef, self.__connection, recordset,
- [u'gnue_id'] + propertylist)
+ [u'gnue_id'] + propertylist, asCond)
self.__listcount += 1
self.__lists [self.__listcount] = list
@@ -352,3 +363,136 @@
result.append (instance.call (procdef, parameters))
return result
+
+
+ # ---------------------------------------------------------------------------
+ # Split a condition into a datasource- and an appserver-condition
+ # ---------------------------------------------------------------------------
+
+ def __splitCondition (self, condition, classdef):
+ """
+ This function splits up a given condition into a condition which is handled
+ by the datasource, and another one which has to be processed by appserver.
+ """
+
+ if isinstance (condition, ListType):
+ cTree = GConditions.buildTreeFromPrefix (condition)
+ else:
+ cTree = condition
+
+ dbTrees = []
+ asTrees = []
+ forest = []
+
+ if len (cTree._children):
+ # NOTE: the first element of a condition tree is a GCondition object
+ self.__splitIntoAnd (cTree._children [0], forest)
+
+ for tree in forest:
+ if self.__dbHandlesTree (tree, classdef):
+ dbTrees.append (tree)
+ else:
+ asTrees.append (tree)
+
+ # now create the final trees
+ dbCond = None
+ asCond = None
+
+ # TODO: this could be improved, maybe using something like combineCondition
+ # will do that later
+ if len (dbTrees):
+ dbCond = GConditions.GCondition ()
+ comb = GConditions.GCand (dbCond)
+
+ for tree in dbTrees:
+ comb._children.append (tree)
+ tree.parent = comb
+
+ if len (asTrees):
+ asCond = GConditions.GCondition ()
+ comb = GConditions.GCand (asCond)
+ for tree in asTrees:
+ comb._children.append (tree)
+ tree.parent = comb
+
+ return (dbCond, asCond)
+
+
+ # ---------------------------------------------------------------------------
+ # Split a condition tree into separate parts
+ # ---------------------------------------------------------------------------
+
+ def __splitIntoAnd (self, tree, forest):
+ """
+ This function splits a condition tree into several independant subtrees
+ which can be re-combined via AND.
+ """
+ if isinstance (tree, GConditions.GCand):
+ for child in tree._children:
+ self.__splitIntoAnd (child, forest)
+ else:
+ forest.append (tree)
+
+
+ # ---------------------------------------------------------------------------
+ # Determine wether a condition tree can be handled by the datasource or not
+ # ---------------------------------------------------------------------------
+
+ def __dbHandlesTree (self, tree, classdef):
+ """
+ This function traverses the given condition tree and determines if it can
+ be handled be the datasource completely.
+ """
+ if isinstance (tree, GConditions.GCField):
+ return self.__usable (tree, classdef)
+ else:
+ for child in tree._children:
+ res = self.__dbHandlesTree (child, classdef)
+ if not res:
+ return res
+
+ return True
+
+
+ # ---------------------------------------------------------------------------
+ # Return wether a GCField must be handled by appserver or datasource
+ # ---------------------------------------------------------------------------
+ def __usable (self, element, classdef):
+ return not self.__getPropertyDef (element.name, classdef).isCalculated
+
+
+ # ---------------------------------------------------------------------------
+ # Get the property definition for a given property
+ # ---------------------------------------------------------------------------
+
+ def __getPropertyDef (self, propertyname, classdef):
+ """
+ This function gets the property definition for a given propertyname,
+ resolving references.
+ """
+ cDef = classdef
+ parts = propertyname.split ('.')
+ for prop in parts [:-1]:
+ pDef = cDef.properties [prop]
+ if not pDef.isReference:
+ raise ReferenceError, (propertyname, prop)
+ cDef = pDef.referencedClass
+
+ return cDef.properties [parts [-1]]
+
+
+ # ---------------------------------------------------------------------------
+ # Add all GCField elements of a tree to the content dictionary
+ # ---------------------------------------------------------------------------
+
+ def __addConditionToContent (self, classdef, content, tree):
+ """
+ This function adds all GCField instances in a condition tree to the given
+ content dictionary.
+ """
+ if isinstance (tree, GConditions.GCField):
+ self.__getFieldname (classdef, tree.name, content, True)
+ else:
+ for child in tree._children:
+ self.__addConditionToContent (classdef, content, child)
+
Modified: trunk/gnue-common/src/datasources/GConditions.py
===================================================================
--- trunk/gnue-common/src/datasources/GConditions.py 2004-04-29 03:49:56 UTC
(rev 5768)
+++ trunk/gnue-common/src/datasources/GConditions.py 2004-04-29 17:57:46 UTC
(rev 5769)
@@ -23,15 +23,13 @@
#
# DESCRIPTION:
#
+# $Id: $
#
-# NOTES:
-#
-# HISTORY:
-#
from gnue.common.definitions.GObjects import GObj
from gnue.common.formatting import GTypecast
-import types,string
+import mx.DateTime
+import types, string
class ConditionError (gException):
pass
@@ -39,11 +37,77 @@
class ConditionNotSupported (ConditionError):
pass
+class MalformedConditionTreeError (ConditionError):
+ pass
+class ArgumentCountError (MalformedConditionTreeError):
+ def __init__ (self, element, wanted):
+ msg = u_("Conditionelement '%(element)s' was expected to have '%(wanted)d'"
+ "arguments, but only has %(real)d'") \
+ % {'element': element.__class__.split ('.') [-1],
+ 'wanted' : wanted,
+ 'real' : len (element._children)}
+ MalformedConditionTreeError.__init__ (self, msg)
+
+class MissingFieldError (ConditionError):
+ def __init__ (self, element):
+ msg = u_("The field '%(field)s' has no entry in the given lookup-table") \
+ % {'field': element.name }
+ ConditionError.__init__ (self, msg)
+
+
+class UnificationError (gException):
+ pass
+
+class ConversionRuleError (UnificationError):
+ def __init__ (self, value1, value2):
+ msg = u_("No unification rule for combination '%(type1)s' and "
+ "'%(type2)s'") \
+ % {'type1': type (value1).__name__,
+ 'type2': type (value2).__name__}
+ UnificationError.__init__ (self, msg)
+
+class ConversionError (UnificationError):
+ def __init__ (self, value1, value2):
+ msg = u_("Value '%(value1)s' of type '%(type1)s' cannot be converted "
+ "into type '%(type2)s'") \
+ % {'value1': value1,
+ 'type1' : type (value1).__name__,
+ 'type2' : type (value2).__name__}
+ UnificationError.__init__ (self, msg)
+
+
class GCondition(GObj):
def __init__(self, parent=None, type="GCCondition"):
GObj.__init__(self, parent, type=type)
+ # ---------------------------------------------------------------------------
+ # Evaluate a condition tree using the given lookup dictionary
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ """
+ This function evaluates the condition tree using the dictionary @lookup for
+ retrieving field values.
+ """
+ self._needChildren (1)
+ return self._children [0].eval (lookup)
+
+
+ # ---------------------------------------------------------------------------
+ # Make sure an element of the tree has the requested number of children
+ # ---------------------------------------------------------------------------
+
+ def _needChildren (self, number):
+ """
+ This function verifies if a condition element has a given number of
+ children. If not an ArgumentCountError will be raised.
+ """
+ if len (self._children) != number:
+ raise ArgumentCountError, (self, number)
+
+
+
class GConditions(GCondition):
def __init__(self, parent=None, type="GCConditions"):
GCondition.__init__(self, parent, type=type)
@@ -52,12 +116,30 @@
def __init__(self, parent=None, type="GConditionElement"):
GCondition.__init__(self, parent, type=type)
+
class GCField (GConditionElement):
def __init__(self, parent, name=None, datatype="char"):
GConditionElement.__init__(self, parent, 'GCCField')
self.type = datatype
self.name = name
+ # ---------------------------------------------------------------------------
+ # Evaluate a field element
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ """
+ This function returns the fields value in the given lookup dictionary. If
+ this dictionary has no key for the field a MissingFieldError will be
+ raised.
+ """
+ if not lookup.has_key (self.name):
+ raise MissingFieldError, (self.name)
+
+ return lookup [self.name]
+
+
+
class GCParam (GConditionElement):
def __init__(self, parent, name=None, datatype="char"):
GConditionElement.__init__(self, parent, 'GCCParam')
@@ -67,16 +149,44 @@
def getValue(self):
return ""
+ def eval (self, lookup):
+ raise ConditionError, u_("Object can't evaluate!")
+
+
class GCConst (GConditionElement):
def __init__(self, parent, value=None, datatype="char"):
GConditionElement.__init__(self, parent, 'GCCConst')
self.type = datatype
self.value = value
+ # ---------------------------------------------------------------------------
+ # Evaluate a constant
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ """
+ This function returns the constants value
+ """
+ return self.value
+
+
class GCadd(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCadd')
+ def eval (self, lookup):
+ """
+ This function creates the sum of all it's children. A unify is used to
+ ensure all children evaluate to a numeric type.
+ """
+ result = 0
+ for child in self._children:
+ values = []
+ unify ([child.eval (lookup), 0], values)
+ result += values [0]
+ return result
+
+
class GCsub(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCsub')
@@ -89,72 +199,230 @@
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCdiv')
+
+
class GCand(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCand')
+ # ---------------------------------------------------------------------------
+ # Evaluate an 'AND' condition
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ """
+ This function concatenates all children of this element by a logical AND.
+ The iteration stops on the first 'false' result.
+ """
+ for child in self._children:
+ if not child.eval (lookup):
+ return False
+
+ return True
+
+
class GCor(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCor')
+ # ---------------------------------------------------------------------------
+ # Evaluate an OR tree
+ # ---------------------------------------------------------------------------
+ def eval (self, lookup):
+ """
+ This function concatenates all children of this element by a logical OR.
+ The iteration stops on the first 'true' result.
+ """
+ for child in self._children:
+ if child.eval (lookup):
+ return True
+
+ return False
+
+
class GCnot(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCnot')
+ # ---------------------------------------------------------------------------
+ # Evaluate the element
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ """
+ This function logically inverts the child's evaluation
+ """
+ self._needChildren (1)
+ return not self._children [0].eval (lookup)
+
+
class GCnegate(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCnegate')
+ def eval (self, lookup):
+ self._needChildren (1)
+ values = []
+ unify ([self._children [0].eval (lookup), 0], values)
+ return -values [0]
+
+
class GCeq(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCeq')
+ # ---------------------------------------------------------------------------
+ # evaluate EQ relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (2)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [0] == result [1]
+
+
class GCne(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCne')
+ # ---------------------------------------------------------------------------
+ # evaluate NE relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (2)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [0] != result [1]
+
+
class GCgt(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCgt')
+ # ---------------------------------------------------------------------------
+ # evaluate GT relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (2)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [0] > result [1]
+
+
+
class GCge(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCge')
+ # ---------------------------------------------------------------------------
+ # evaluate NE relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (2)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [0] >= result [1]
+
+
+
class GClt(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GClt')
+ # ---------------------------------------------------------------------------
+ # evaluate LT relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (2)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [0] < result [1]
+
+
+
class GCle(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCle')
+ # ---------------------------------------------------------------------------
+ # evaluate LE relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (2)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [0] <= result [1]
+
+
+
class GClike(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GClike')
+ def eval (self, lookup):
+ self._needChildren (2)
+ return True
+
class GCnotlike(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCnotlike')
+ def eval (self, lookup):
+ self._needChildren (2)
+ return True
+
+
class GCbetween(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCbetween')
+ # ---------------------------------------------------------------------------
+ # evaluate beetween relation
+ # ---------------------------------------------------------------------------
+
+ def eval (self, lookup):
+ self._needChildren (3)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return result [1] <= result [0] <= result [2]
+
+
class GCnotbetween(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCnotbetween')
+ def eval (self, lookup):
+ self._needChildren (3)
+ result = []
+ unify ([v.eval (lookup) for v in self._children], result)
+ return not (result [1] <= result [0] <= result [2])
+
+
class GCnull(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCnull')
+ def eval (self, lookup):
+ self._needChildren (1)
+ return self._children [0].eval (lookup) is None
+
+
class GCnotnull(GConditionElement):
def __init__(self, parent=None):
GConditionElement.__init__(self, parent, 'GCnotnull')
+ def eval (self, lookup):
+ self._needChildren (1)
+ return not self._children [0].eval (lookup) is None
+
# build an impossible condition GCondition={0=1}
GCimpossible=GCondition()
_h=GCeq(GCimpossible)
@@ -347,7 +615,7 @@
if type(cond1) == type({}):
cond1 = buildConditionFromDict(cond1)
if type(cond2) == type({}):
- cond1 = buildConditionFromDict(cond2)
+ cond2 = buildConditionFromDict(cond2)
if not len(cond1._children):
cond1._children = cond2._children
@@ -404,6 +672,8 @@
return parent[0];
+def newbuildPrefixFromTree (element):
+ pass
def buildPrefixFromTree(conditionTree):
if type(conditionTree) != types.InstanceType:
@@ -472,3 +742,153 @@
'by the condition to prefix table conversion.') % otype
raise ConditionNotSupported, tmsg
+
+# -----------------------------------------------------------------------------
+# Unify all elements in values to the same type
+# -----------------------------------------------------------------------------
+
+def unify (values, result):
+ """
+ This function converts all values in the sequence @values to the same types
+ pushing the results into the sequence @result.
+ """
+
+ checktype (values, types.ListType)
+
+ if not len (values):
+ return
+
+ elif len (values) == 1:
+ result.append (values [0])
+ return
+
+ if isinstance (values [0], types.StringType):
+ values [0] = unicode (values [0])
+ if isinstance (values [1], types.StringType):
+ values [1] = unicode (values [1])
+
+ v1 = values [0]
+ v2 = values [1]
+
+ if type (v1) == type (v2):
+ result.append (v1)
+ values.remove (v1)
+ unify (values, result)
+
+ else:
+ # String-Conversions
+ if isinstance (v1, types.UnicodeType) or isinstance (v2,
types.UnicodeType):
+ if isinstance (v1, types.UnicodeType):
+ oldValue = v1
+ chkValue = v2
+ else:
+ oldValue = v2
+ chkValue = v1
+
+ # String to Integer, Long or Float
+ if isinstance (chkValue, types.IntType) or \
+ isinstance (chkValue, types.LongType) or \
+ isinstance (chkValue, types.FloatType):
+ try:
+ if oldValue.upper () in ['TRUE', 'T']:
+ newValue = 1
+ elif oldValue.upper () in ['FALSE', 'F']:
+ newValue = 0
+ else:
+ newValue = int (oldValue)
+
+ except ValueError:
+
+ try:
+ newValue = float (oldValue)
+
+ except ValueError:
+ raise ConversionError, (oldValue, chkValue)
+
+ # String to DateTime
+ elif isinstance (chkValue, mx.DateTime.DateTimeType) or \
+ isinstance (chkValue, mx.DateTime.DateTimeDeltaType):
+
+ try:
+ newValue = mx.DateTime.Parser.DateTimeFromString (oldValue)
+
+ except ValueError:
+ raise ConversionError, (oldValue, chkValue)
+
+ else:
+ raise ConversionRuleError, (oldValue, chkValue)
+
+ # Integer conversions
+ elif isinstance (v1, types.IntType) or isinstance (v2, types.IntType):
+ if isinstance (v1, types.IntType):
+ oldValue = v1
+ chkValue = v2
+ else:
+ oldValue = v2
+ chkValue = v1
+
+ # Integer to Float
+ if isinstance (chkValue, types.FloatType):
+ newValue = float (oldValue)
+
+ elif isinstance (chkValue, types.LongType):
+ newValue = long (oldValue)
+
+ else:
+ raise ConversionRuleError, (oldValue, chkValue)
+
+ # Long conversions
+ elif isinstance (v1, types.LongType) or isinstance (v2, types.LongType):
+ if isinstance (v1, types.LongType):
+ oldValue = v1
+ chkValue = v2
+ else:
+ oldValue = v2
+ chkValue = v1
+
+ # Long into Float
+ if isinstance (chkValue, types.FloatType):
+ newValue = float (oldValue)
+ else:
+ raise ConversionRuleError, (oldValue, chkValue)
+
+ else:
+ raise ConversionRuleError, (v1, v2)
+
+ values [oldValue == v2] = newValue
+ unify (values, result)
+
+
+# =============================================================================
+# Module self test code
+# =============================================================================
+
+if __name__ == '__main__':
+ import sys
+ from mx.DateTime import *
+
+ def check (x, y):
+ print "unify: %s (%s) vs %s (%s)" % (x, type (x), y, type (y))
+ res = []
+ vals = []
+ if x != 0: vals.append (x)
+ if y != 0: vals.append (y)
+
+ try:
+ unify (vals, res)
+ print "result:", ["%s (%s)" % (r, type (r).__name__) for r in res], "\n"
+
+ except:
+ print sys.exc_info () [0], sys.exc_info () [1]
+
+ check (u'17', 5)
+ check (5, '18')
+ check (now (), '2004-08-15 14:00')
+ check ('13.0', 12)
+ check ('15', '')
+ check (7L, '12')
+ check (7L, '12.2')
+ check (1, 'True')
+ check (0, 0)
+ check (1, 0)
+ check (None, 0)
Property changes on: trunk/gnue-common/src/datasources/GConditions.py
___________________________________________________________________
Name: svn:keywords
+ +svn:Id
Modified:
trunk/gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py
2004-04-29 03:49:56 UTC (rev 5768)
+++ trunk/gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py
2004-04-29 17:57:46 UTC (rev 5769)
@@ -82,9 +82,8 @@
def _createResultSet (self, conditions = {}, readOnly = 0,
masterRecordSet = None, sql = ''):
- rscond = GConditions.combineConditions (conditions, self._staticCondition)
- if rscond:
- filter = self._buildQuery (rscond)
+ if conditions is not None:
+ filter = self._buildQuery (conditions)
else:
filter = []
@@ -107,3 +106,16 @@
fetchcount = self.cache,
readOnly = readOnly,
masterRecordSet = masterRecordSet)
+
+ # ---------------------------------------------------------------------------
+ # debug method: dump a complete condition tree
+ # ---------------------------------------------------------------------------
+
+ def __dumpTree (self, element, level = 0):
+ print "%2d: %s (%s) [%s]" % (level, element.__class__, hex(id(element)),
+ hex(id(element._parent)))
+ nlevel = level + 1
+ print " -> %s" % [hex (id (x)) for x in element._children]
+
+ for ch in element._children:
+ self.__dumpTree (ch, nlevel)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- r5769 - in trunk: gnue-appserver/samples gnue-appserver/src gnue-common/src/datasources gnue-common/src/datasources/drivers/appserver/appserver,
johannes <=