Changeset 47

Show
Ignore:
Timestamp:
03/08/04 19:23:17 (5 years ago)
Author:
ed
Message:

updates to all the bizobj and cursor classes. Does not contain merge's with Paul's changes. Still has unresolved issues with the new() method, due to lack of type information in the cursor.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/classes/dBizobj.py

    r27 r47  
    22import dConnection 
    33import dCursorMixin 
     4import types 
     5 
    46 
    57### TODO ### - Change to Gadfly 
     
    1416    # is useful for parameterized queries 
    1517    noDataOnLoad = 0 
     18    # Holds the params to be merged with the sql in the cursor 
     19    _params = () 
    1620    # Reference to the cursor object  
    1721    _cursor = None 
     
    2024    # Base class to instantiate for the cursor object 
    2125    ### TODO ### - change to Gadfly for default 
    22     cursorBaseClass = cursors.DictCursor 
     26    #cursorBaseClass = cursors.DictCursor 
     27    cursorBaseClass = cursors.Cursor 
    2328    # Reference to the parent bizobj to this one. 
    2429    _parent = None 
    2530    # Collection of child bizobjs for this 
    26     _children = [] 
     31    __children = [] 
    2732    # Name of field that is the PK  
    2833    keyField = "" 
     
    7883            # Need to raise an exception here! 
    7984            pass 
     85         
     86        # Need to set this so that different instances don't mix up the references 
     87        # contained in this list. 
     88        self.__children = [] 
    8089     
    8190     
    8291    def getCursorClass(self, main, secondary): 
    83         class result(main, secondary): 
     92        class cursorMix(main, secondary): 
     93            superMixin = main 
     94            superCursor = secondary 
    8495            def __init__(self, *args, **kwargs): 
    8596                if hasattr(main, "__init__"): 
     
    8899                if hasattr(secondary, "__init__"): 
    89100                    apply(secondary.__init__,(self,) + args, kwargs) 
    90         return  result 
     101        return  cursorMix 
    91102     
    92103 
     
    194205         
    195206            # Iterate through the child bizobjs, telling them to save themselves. 
    196             for child in self._children: 
     207            for child in self.__children: 
    197208                if child.isChanged(): 
    198209                    # No need to start another transaction. And since this is a child bizobj,  
     
    240251        if ret == k.FILE_OK: 
    241252            # Tell each child to cancel themselves 
    242             for child in self._children: 
     253            for child in self.__children: 
    243254                ret = child.cancel(allRows) 
    244255                if not ret == k.FILE_OK: 
     
    260271        self._errorMsg = "" 
    261272         
    262         if not self.beforeDelete() or self.beforePointerMove(): 
     273        if not self.beforeDelete() or not self.beforePointerMove(): 
    263274            return k.FILE_CANCEL 
    264275         
    265276        if self.deleteChildLogic == k.REFINTEG_RESTRICT: 
    266277            # See if there are any child records 
    267             for child in self._children: 
     278            for child in self.__children: 
    268279                if child.getRowCount() > 0: 
    269280                    self.addToErrorMsg("Deletion prohibited - there are related child records.") 
     
    271282         
    272283        ret = self._cursor.delete() 
    273 ### TODO - add this logic to the cursor's Delete 
    274 #       * If adding a new record, just revert it. 
    275 #       IF IsAdding(This.cAlias) 
    276 #           lnRetVal = This.oBehavior.Cancel() 
    277  
    278         if ret == k.FILE_OK: 
    279             if self._cursor.rowcount == 0: 
     284 
     285        if ret == k.FILE_OK: 
     286            if self._cursor.getRowCount() == 0: 
    280287                # Hook method for handling the deletion of the last record in the cursor. 
    281288                self.onDeleteLastRecord() 
     
    283290            # ensure that any changed data they may have is reverted. They are then requeried to 
    284291            # populate them with data for the current record in this bizobj. 
    285             for child in self._children: 
     292            for child in self.__children: 
    286293                if self.deleteChildLogic == k.REFINTEG_CASCADE: 
    287294                    child.deleteAll() 
     
    302309    def deleteAll(self): 
    303310        """ Iterate through all the rows in the bizobj's cursor, deleting each one-by-one""" 
    304         while self._cursor.rowcount > 0: 
     311        while self._cursor.getRowCount() > 0: 
    305312            self.first() 
    306313            ret = self.delete() 
     
    328335            if self.newChildOnNew: 
    329336                # Add records to all children set to have records created on a new parent record. 
    330                 for child in self._children: 
     337                for child in self.__children: 
    331338                    if child.newRecordOnNewParent: 
    332339                        child.new() 
     
    370377        self.afterRequery(ret) 
    371378        return ret 
     379     
     380     
     381    def setParams(self, params): 
     382        """ accepts a tuple that will be merged with the sql statement using the '%' 
     383        string format function. """ 
     384#       if params != types.TupleType: 
     385#           params = tuple(params) 
     386        self._params = params 
    372387     
    373388     
     
    390405        if not ret: 
    391406            # see if any child bizobjs have changed 
    392             for child in self._children: 
     407            for child in self.__children: 
    393408                ret = ret and child.isChanged() 
    394409         
     
    403418    def onNew(self): 
    404419        """ Populates the record with any default values """ 
    405         self._cursor.setDefaultVals(self.defaultValues()
     420        self._cursor.setDefaults(self.defaultValues
    406421         
    407422        # Call the custom hook method 
     
    417432        """ During the creation of the form, child bizobjs are added by the parent. 
    418433        This stores the child reference here, and sets the reference to the parent in the child. """ 
    419         if child not in self._children: 
    420             self._children.append(child) 
     434        if child not in self.__children: 
     435            self.__children.append(child) 
    421436            child.setParent(self) 
    422437     
     
    430445        """ Called to assure that all child bizobjs have had their data sets refreshed to  
    431446        match the current status. """ 
    432         if len(self._children) == 0: 
     447        if len(self.__children) == 0: 
    433448            return k.REQUERY_SUCCESS 
    434449        if self.beforeChildRequery(): 
    435450            ret = k.REQUERY_SUCCESS 
    436             for child in self._children: 
     451            for child in self.__children: 
    437452                ret = child.requery() 
    438453                if not ret == k.REQUERY_SUCCESS: 
     
    445460            self.addToErrorMsg(self._cursor.getErrorMsg()) 
    446461             
    447         self.afterRequeryAllChildren(
     462        self.afterChildRequery(ret
    448463        return ret 
    449464     
     
    478493        use this method to create a tuple to be passed to the cursor, where  
    479494        it will be used to modify the query using standard printf syntax. """ 
    480         return None 
     495        return self._params 
    481496     
    482497     
  • trunk/classes/dCursorMixin.py

    r26 r47  
    1515    # Holds the dict used for adding new blank records 
    1616    _blank = {} 
     17    # Last executed sql statement 
     18    lastSQL = "" 
     19    # Last executed sql params 
     20    lastParams = None 
    1721     
    1822     
     
    3438     
    3539     
     40    def execute(self, sql, params=None): 
     41        """ 
     42        The idea here is to let the super class do the actual work in retrieving the data. However,  
     43        many cursor classes can only return row information as a list, not as a dictionary. This 
     44        method will detect that, and convert the results to a dictionary. 
     45        """ 
     46         
     47        self.superCursor.execute(self, sql, params) 
     48         
     49        if self._rows: 
     50            if type(self._rows[0]) == types.TupleType: 
     51                # Need to convert each row to a Dict 
     52                tmpRows = [] 
     53                # First, get the description property and extract the field names from that 
     54                fldNames = [] 
     55                for fld in self.description: 
     56                    fldNames.append(fld[0]) 
     57                fldcount = len(fldNames) 
     58                # Now go through each row, and convert it to a dictionary. We will then 
     59                # add that dictionary to the tmpRows list. When all is done, we will replace  
     60                # the _rows property with that list of dictionaries 
     61                for row in self._rows: 
     62                    dic= {} 
     63                    for i in range(0, fldcount-1): 
     64                        dic[fldNames[i]] = row[i] 
     65                    tmpRows.append(dic) 
     66                self._rows = tuple(tmpRows) 
     67     
     68     
    3669    def requery(self, params=None): 
    37         if params is None: 
    38             sql = self.sql 
    39         else: 
    40             sql = self.sql % params 
     70        self.lastSQL = self.sql 
     71        self.lastParams = params 
    4172        try: 
    42             self.execute(sql
     73            self.execute(self.sql, params
    4374        except: 
    4475            return k.REQUERY_ERROR 
     
    4980     
    5081    def setMemento(self): 
    51         self.addMemento(self.rownumber) 
     82        if self.rowcount > 0: 
     83            if (self.rownumber >= 0) and (self.rownumber < self.rowcount): 
     84                self.addMemento(self.rownumber) 
    5285         
    5386     
     
    5588        """ Returns the value of the requested field """ 
    5689        ret = None 
    57         if self.rowcount == 0: 
     90        if self.rowcount <= 0: 
    5891            self.addToErrorMsg("No records in the data set") 
    5992        else: 
     
    69102        """ Sets the value of the specified field """ 
    70103        ret = 0 
    71         if self.rowcount == 0: 
     104        if self.rowcount <= 0: 
    72105            self.addToErrorMsg("No records in the data set") 
    73106        else: 
     
    79112                self.addToErrorMsg("Field '" + fld + "' does not exist in the data set") 
    80113        return ret 
     114     
     115     
     116    def getRowCount(self): 
     117        ret = -1 
     118        if hasattr(self, "rowcount"): 
     119            ret = self.rowcount 
     120        return ret 
    81121         
    82122     
     
    130170        ret = k.FILE_OK 
    131171        if self.rowcount > 0: 
    132             if self.rownumber < (self.rowcount-1): 
    133                 self.rownumber = self.rowcount-1 
    134             else: 
    135                 ret = k.FILE_EOF 
    136                 self.addToErrorMsg("Already at the end of the data set.") 
     172            self.rownumber = self.rowcount-1 
    137173        else: 
    138174            ret = k.FILE_NORECORDS 
     
    146182         
    147183        # Make sure that there is data to save 
    148         if self.rowcount == 0: 
     184        if self.rowcount <= 0: 
    149185            self.addToErrorMsg("No data to save") 
    150186            return k.FILE_CANCEL 
     
    229265         
    230266        # Make sure that there is data to save 
    231         if not self.rowcount > 0: 
     267        if not self.rowcount >= 0: 
    232268            self.addToErrorMsg("No data to cancel") 
    233269            return k.FILE_CANCEL 
     
    238274            recs = (self._rows[self.rownumber],) 
    239275         
    240         for i in range(self.rowcount, 0, -1): 
     276        for i in range(self.rowcount-1, 0, -1): 
    241277            rec = self._rows[i] 
    242278            newrec =  rec.has_key(k.CURSOR_NEWFLAG) 
     
    245281                ret = self.delete(i) 
    246282            else: 
    247                 ret = cancelrow(i
     283                ret = self.cancelRow(rec
    248284            if ret != k.FILE_OK: 
    249285                break 
    250286        return ret 
    251      
    252      
    253     def delete(self, rownum): 
    254         ret = k.FILE_OK 
     287                     
     288                 
     289    def cancelRow(self, rec): 
     290        mem = rec[k.CURSOR_MEMENTO] 
     291        diff = mem.makeDiff(rec) 
     292        if diff: 
     293            for fld, val in diff.items(): 
     294                rec[fld] = val 
     295        return k.FILE_OK 
     296     
     297     
     298    def delete(self, rownum=None): 
     299        ret = k.FILE_OK 
     300         
     301        if rownum is None: 
     302            # assume that it is the current row that is to be deleted 
     303            rownum = self.rownumber 
     304         
    255305        rec = self._rows[rownum] 
    256306        newrec =  rec.has_key(k.CURSOR_NEWFLAG) 
     
    266316            res = self.execute(sql) 
    267317         
    268         self.restoreProps(restoreRows=0) 
    269         if not res: 
     318        if res: 
     319            # First, delete the row from the held properties 
     320            tmprows = list(self.holdrows) 
     321            del tmprows[rownum] 
     322            self.holdrows = tuple(tmprows) 
     323            # Now restore the properties 
     324            self.restoreProps() 
     325        else: 
    270326            # Nothing was deleted 
    271327            ret = FILE_CANCEL 
    272328        return ret 
    273                      
    274                  
    275     def cancelrow(self, rec): 
    276         mem = rec[k.CURSOR_MEMENTO] 
    277329     
    278330     
     
    303355    def setStructure(self): 
    304356        import re 
    305         pat = re.compile("\s*select\s*.*\s*from\s*.*\s*((?:where\s(.*))+)\s*", re.I | re.M) 
     357        pat = re.compile("(\s*select\s*.*\s*from\s*.*\s*)((?:where\s(.*))+)\s*", re.I | re.M) 
    306358        if pat.search(self.sql): 
    307359            # There is a WHERE clause. Add the NODATA clause 
    308             tmpsql = pat.sub(" where 1=0 ", self.sql) 
     360            tmpsql = pat.sub("\\1 where 1=0 ", self.sql) 
    309361        else: 
    310362            # no WHERE clause. See if it has GROUP BY or ORDER BY clauses 
    311             pat = re.compile("\s*select\s*.*\s*from\s*.*\s*((?:group\s*by\s(.*))+)\s*", re.I | re.M) 
     363            pat = re.compile("(\s*select\s*.*\s*from\s*.*\s*)((?:group\s*by\s(.*))+)\s*", re.I | re.M) 
    312364            if pat.search(self.sql): 
    313                 tmpsql = pat.sub(" where 1=0 ", self.sql) 
     365                tmpsql = pat.sub("\\1 where 1=0 ", self.sql) 
    314366            else:                
    315                 pat = re.compile("\s*select\s*.*\s*from\s*.*\s*((?:order\s*by\s(.*))+)\s*", re.I | re.M) 
     367                pat = re.compile("(\s*select\s*.*\s*from\s*.*\s*)((?:order\s*by\s(.*))+)\s*", re.I | re.M) 
    316368                if pat.search(self.sql): 
    317                     tmpsql = pat.sub(" where 1=0 ", self.sql) 
     369                    tmpsql = pat.sub("\\1 where 1=0 ", self.sql) 
    318370                else:                
    319371                    # Nothing. So just tack it on the end. 
    320372                    tmpsql = sql + " where 1=0 " 
    321373         
     374        # We need to save and restore the cursor properties, since this query will wipe 'em out. 
     375        self.saveProps() 
    322376        self.execute(tmpsql) 
     377        self.restoreProps() 
     378         
    323379        dscrp = self.description 
    324380        for fld in dscrp: 
     
    333389                    # Int 
    334390                    _blank[fld] = 0 
    335          
     391     
     392     
     393    def moveToPK(self, pk): 
     394        """ Find the record in the result set (if any) whose value in the keyField 
     395        field matches the passed value. If found, set the current position to that  
     396        record. If not found, set the position to the first record. """ 
     397        self.rownumber = 0 
     398        for i in range(0, len(self._rows)): 
     399            rec = self._rows[i] 
     400            if rec[self.keyField] == pk: 
     401                self.rownumber = i 
     402                break 
     403 
    336404         
    337405    def checkPK(self): 
     
    382450 
    383451    def saveProps(self, saverows=1): 
    384         self.tmprows = self._rows 
    385         self.tmpcount = self.rowcount 
    386         self.tmppos = self.rownumber 
    387         self.tmpdesc = self.description 
    388          
    389  
    390     def restoreProps(self, restorerows=1): 
    391         if restorerows: 
    392             self._rows = self.tmprows 
     452        self.holdrows = self._rows 
     453        self.holdcount = self.rowcount 
     454        self.holdpos = self.rownumber 
     455        self.holddesc = self.description 
     456         
     457 
     458    def restoreProps(self, restoreRows=1): 
     459        if restoreRows: 
     460            self._rows = self.holdrows 
    393461        self.rowcount = len(self._rows) 
    394         self.rownumber = min(self.tmppos, self.rowcount-1) 
    395         self.description = self.tmpdesc 
     462        self.rownumber = min(self.holdpos, self.rowcount-1) 
     463        self.description = self.holddesc 
    396464     
    397465     
  • trunk/classes/dMemento.py

    r25 r47  
    1717        the passed dictionary of values is identical to the current snapshot.""" 
    1818        return (self._snapshot != newvals) 
     19         
    1920 
    20     def makeDiff(self, newvals, newrec): 
     21    def makeDiff(self, newvals, isNewRecord=0): 
    2122        """ The idea here is to create a dictionary containing just the values  
    2223        that have changed in the newvals dict., as compared to the snapshot.  
     
    3435            # OK, if this is a new record, include all the values. Otherwise, just 
    3536            # include the changed ones. 
    36             if newrec or self._snapshot[kk] != vv: 
     37            if isNewRecord or self._snapshot[kk] != vv: 
    3738                ret[kk] = vv 
    3839        return ret