commit-gnue
[Top][All Lists]
Advanced

[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)





reply via email to

[Prev in Thread] Current Thread [Next in Thread]