Changeset 3212

Show
Ignore:
Timestamp:
06/26/2007 09:33:27 AM (1 year ago)
Author:
ed
Message:

Added the _syncAuxProperties() method to ensure that the AuxCursor? has the same property settings as its main cursor.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/dabo/db/dCursorMixin.py

    r3199 r3212  
    4242        ##      which we are mixed-in will take the __init__. 
    4343        dObject.__init__(self, *args, **kwargs) 
    44          
     44 
    4545        # Just in case this is used outside of the context of a bizobj 
    4646        if not hasattr(self, "superCursor") or self.superCursor is None: 
     
    7676        # Flag that is set when the user explicitly sets the Key Field 
    7777        self._keyFieldSet = False 
    78         # Cursor that manages this cursor's SQL. Default to self;  
    79         # in some cases, such as a single bizobj managing several cursors,  
     78        # Cursor that manages this cursor's SQL. Default to self; 
     79        # in some cases, such as a single bizobj managing several cursors, 
    8080        # it will be a separate object. 
    8181        self.sqlManager = self 
     
    9494        # Holds the data types for each field 
    9595        self._types = {} 
    96          
     96 
    9797        # Holds reference to auxiliary cursor that handles queries that 
    9898        # are not supposed to affect the record set. 
    9999        self.__auxCursor = None 
     100        # Marks the cursor as an auxiliary cursor 
     101        self._isAuxiliary = False 
    100102 
    101103        # Reference to the object with backend-specific behaviors 
    102104        self.__backend = None 
    103          
     105 
    104106        # Reference to the bizobj that 'owns' this cursor, if any, 
    105107        self._bizobj = None 
    106          
     108 
    107109        # set properties for the SQL Builder functions 
    108110        self.clearSQL() 
    109111        self.hasSqlBuilder = True 
    110          
     112 
    111113        # props for building the auxiliary cursor 
    112114        self._cursorFactoryFunc = None 
     
    116118        self._mementos = {} 
    117119        self._newRecords = {} 
    118          
     120 
    119121        # Flag preference cursors so that they don't fill up the logs 
    120122        self._isPrefCursor = False 
     
    126128        self._cursorFactoryFunc = func 
    127129        self._cursorFactoryClass = cls 
    128          
    129      
     130 
     131 
    130132    def clearSQL(self): 
    131133        self._fieldClause = "" 
     
    139141        self._defaultLimit = 1000 
    140142 
    141          
     143 
    142144    def getSortColumn(self): 
    143145        return self.sortColumn 
     
    150152    def getSortCase(self): 
    151153        return self.sortCase 
    152      
    153      
     154 
     155 
    154156    def pkExpression(self, rec=None): 
    155157        """Returns the PK expression for the passed record.""" 
     
    161163            pk = rec[self.KeyField] 
    162164        return pk 
    163          
     165 
    164166 
    165167    def _correctFieldType(self, field_val, field_name, _fromRequery=False): 
    166168        """Correct the type of the passed field_val, based on self.DataStructure. 
    167169 
    168         This is called by self.execute(), and contains code to convert all strings  
    169         to unicode, as well as to correct any datatypes that don't match what  
     170        This is called by self.execute(), and contains code to convert all strings 
     171        to unicode, as well as to correct any datatypes that don't match what 
    170172        self.DataStructure reports. The latter can happen with SQLite, for example, 
    171173        which only knows about a quite limited number of types. 
     
    248250#           ret = field_val.tostring() 
    249251 
    250             dabo.errorLog.write(_("%s couldn't be converted to %s (field %s)")  
     252            dabo.errorLog.write(_("%s couldn't be converted to %s (field %s)") 
    251253                    % (repr(field_val), pythonType, field_name)) 
    252254        return ret 
     
    255257    def execute(self, sql, params=(), _fromRequery=False): 
    256258        """ Execute the sql, and populate the DataSet if it is a select statement.""" 
    257         # The idea here is to let the super class do the actual work in  
    258         # retrieving the data. However, many cursor classes can only return  
    259         # row information as a list, not as a dictionary. This method will  
     259        # The idea here is to let the super class do the actual work in 
     260        # retrieving the data. However, many cursor classes can only return 
     261        # row information as a list, not as a dictionary. This method will 
    260262        # detect that, and convert the results to a dictionary. 
    261263 
     
    266268            sql = unicode(sql, self.Encoding) 
    267269        sql = self.processFields(sql) 
    268          
     270 
    269271        try: 
    270272            if params is None or len(params) == 0: 
     
    314316                    dic = {} 
    315317                    for idx, fldName in enumerate(fldNames): 
    316                         dic[fldName] = self._correctFieldType(field_val=row[idx],  
     318                        dic[fldName] = self._correctFieldType(field_val=row[idx], 
    317319                                field_name=fldName, _fromRequery=_fromRequery) 
    318320                    tmpRows.append(dic) 
     
    337339    def executeSafe(self, sql): 
    338340        """Execute the passed SQL using an auxiliary cursor. 
    339  
    340         This is considered 'safe', because it won't harm the contents of the 
    341         main cursor. 
    342         """ 
    343         return self.AuxCursor.execute(sql) 
    344  
    345      
     341        This is considered 'safe', because it won't harm the contents 
     342        of the main cursor. 
     343        """ 
     344        ac = self.AuxCursor 
     345        self._syncAuxProperties() 
     346        return ac.execute(sql) 
     347 
     348 
     349    def _syncAuxProperties(self): 
     350        """Make sure that the auxiliary cursor has the same property 
     351        settings as the main cursor. 
     352        """ 
     353        if self._isAuxiliary: 
     354            # Redundant! 
     355            return 
     356        ac = self.AuxCursor 
     357        ac.AutoCommit = self.AutoCommit 
     358        ac.AutoPopulatePK = self.AutoPopulatePK 
     359        ac.AutoQuoteNames = self.AutoQuoteNames 
     360        ac.DataStructure = self.DataStructure 
     361        ac.Encoding = self.Encoding 
     362        ac.IsPrefCursor = self.IsPrefCursor 
     363        ac.KeyField = self.KeyField 
     364        ac.Table = self.Table 
     365        ac.UserSQL = self.UserSQL 
     366        ac.VirtualFields = self.VirtualFields 
     367 
     368 
    346369    def requery(self, params=None): 
    347370        self._lastSQL = self.CurrentSQL 
     
    350373 
    351374        self.execute(self.CurrentSQL, params, _fromRequery=True) 
    352          
     375 
    353376        # clear mementos and new record flags: 
    354377        self._mementos = {} 
    355378        self._newRecords = {} 
    356379 
    357         # Check for any derived fields that should not be included in  
     380        # Check for any derived fields that should not be included in 
    358381        # any updates. 
    359382        self.__setNonUpdateFields() 
     
    379402            target._types[field_alias] = dabo.db.getPythonType(field_type) 
    380403 
    381      
     404 
    382405    def sort(self, col, dir=None, caseSensitive=True): 
    383406        """ Sort the result set on the specified column in the specified order. 
    384407 
    385         If the sort direction is not specified, sort() cycles among Ascending,  
     408        If the sort direction is not specified, sort() cycles among Ascending, 
    386409        Descending and no sort order. 
    387410        """ 
     
    400423        newCol = col 
    401424        if col == currCol: 
    402             # Not changing the column; most likely they are flipping  
     425            # Not changing the column; most likely they are flipping 
    403426            # the sort order. 
    404427            if (dir is None) or not dir: 
     
    426449                else: 
    427450                    raise dException.dException, _("Invalid Sort direction specified: ") + dir 
    428          
     451 
    429452        self.__sortRows(newCol, newOrd, caseSensitive) 
    430453        # Save the current sort values 
     
    437460        """ Sort the rows of the cursor. 
    438461 
    439         At this point, we know we have a valid column and order. We need to  
     462        At this point, we know we have a valid column and order. We need to 
    440463        preserve the unsorted order if we haven't done that yet; then we sort 
    441464        the data according to the request. 
     
    444467        if not kf: 
    445468            return 
    446              
     469 
    447470        if not self.__unsortedRows: 
    448471            # Record the PK values 
     
    509532            sortfunc = caseInsensitiveSort 
    510533        else: 
    511             sortfunc = noneSort     
     534            sortfunc = noneSort 
    512535        sortList.sort(sortfunc) 
    513              
     536 
    514537        # Unless DESC was specified as the sort order, we're done sorting 
    515538        if ord == "DESC": 
     
    535558        else: 
    536559            self.RowNumber = 0 
    537      
    538      
     560 
     561 
    539562    def cursorToXML(self): 
    540         """ Returns an XML string containing the information necessary to  
     563        """ Returns an XML string containing the information necessary to 
    541564        re-create this cursor. 
    542565        """ 
     
    555578        </row> 
    556579""" 
    557          
     580 
    558581        colTemplate = """           <column name="%s" type="%s">%s</column>""" 
    559582 
    560583        rowXML = "" 
    561584        for rec in self._records: 
    562             recInfo = [ colTemplate % (k, self.getType(v), self.escape(v))  
     585            recInfo = [ colTemplate % (k, self.getType(v), self.escape(v)) 
    563586                    for k,v in rec.items() ] 
    564587            rowXML += rowTemplate % "\n".join(recInfo) 
    565         return base % (self.Encoding, self.AutoPopulatePK, self.KeyField,  
     588        return base % (self.Encoding, self.AutoPopulatePK, self.KeyField, 
    566589                self.Table, rowXML) 
    567590 
    568      
     591 
    569592    def getType(self, val): 
    570593        try: 
     
    573596            ret = "-unknown-" 
    574597        return ret 
    575      
    576      
     598 
     599 
    577600    def escape(self, val): 
    578601        """ Provides the proper escaping of values in XML output """ 
     
    583606        return ret 
    584607 
     608 
    585609    def setNonUpdateFields(self, fldList=None): 
    586610        if fldList is None: 
    587611            fldList = [] 
    588612        self.nonUpdateFields = fldList 
    589      
    590      
     613 
     614 
    591615    def getNonUpdateFields(self): 
    592616        return list(set(self.nonUpdateFields + self.__nonUpdateFields)) 
    593          
    594          
     617 
     618 
    595619    def __setNonUpdateFields(self): 
    596620        """Automatically set the non-update fields.""" 
     
    608632            # Delegate to the backend object to figure it out. 
    609633            self.BackendObject.setNonUpdateFields(self) 
    610      
     634 
    611635 
    612636    def isChanged(self, allRows=True, includeNewUnchanged=False): 
    613637        """Return True if there are any changes to the local field values. 
    614638 
    615         If allRows is True (the default), all records in the recordset will be  
     639        If allRows is True (the default), all records in the recordset will be 
    616640        considered. Otherwise, only the current record will be checked. 
    617          
     641 
    618642        If includeNewUnchanged is True, new records that have not been 
    619         modified from their default values, which normally are not  
     643        modified from their default values, which normally are not 
    620644        considered 'changed', will be counted as 'changed'. 
    621645        """ 
     
    644668 
    645669        dBizobj will automatically call this method as appropriate, but if you are 
    646         using dCursor without a proxy dBizobj, you'll need to manually call this  
     670        using dCursor without a proxy dBizobj, you'll need to manually call this 
    647671        method after cursor.new(), and (if applicable) after cursor.genTempAutoPK(). 
    648672        For example: 
     
    650674            cursor.genTempAutoPK() 
    651675            cursor.setNewFlag() 
    652         """     
     676        """ 
    653677        if self.KeyField: 
    654678            rec = self._records[self.RowNumber] 
     
    672696            # No records; default to string 
    673697            pkVal = "" 
    674          
     698 
    675699        tmpPK = self._genTempPKVal(pkVal) 
    676700        if isinstance(kf, tuple): 
     
    681705        rec[kons.CURSOR_TMPKEY_FIELD] = tmpPK 
    682706        return tmpPK 
    683          
    684      
     707 
     708 
    685709    def _genTempPKVal(self, pkValue): 
    686         """ Return the next available temp PK value. It will be a string, and  
     710        """ Return the next available temp PK value. It will be a string, and 
    687711        postfixed with '-dabotmp' to avoid potential conflicts with actual PKs 
    688712        """ 
     
    693717            ret = "%s-dabotmp" % ret 
    694718        return ret 
    695      
    696      
     719 
     720 
    697721    def getPK(self): 
    698722        """ Returns the value of the PK field in the current record. If that record 
    699         is new an unsaved record, return the temp PK value. If this is a compound  
     723        is new an unsaved record, return the temp PK value. If this is a compound 
    700724        PK, return a tuple containing each field's values. 
    701725        """ 
     
    715739                ret = rec[kf] 
    716740        return ret 
    717          
     741 
    718742 
    719743    def getFieldVal(self, fld, row=None): 
     
    756780            typ = [ff[1] for ff in flds if ff[0] == fld][0] 
    757781        except IndexError: 
    758             # This 'fld' value is not a native field, so no way to  
     782            # This 'fld' value is not a native field, so no way to 
    759783            # determine its type 
    760784            typ = None 
     
    766790                ret = None 
    767791        return ret 
    768          
     792 
    769793 
    770794    def _hasValidKeyField(self): 
     
    799823        else: 
    800824            fldType = self._fldTypeFromDB(fld) 
     825        nonUpdateFields = self.getNonUpdateFields() 
    801826        if fldType is not None: 
    802827            if fldType != type(val): 
     
    809834                elif isinstance(rec[fld], int) and isinstance(val, bool): 
    810835                    # convert bool to int (original field val was bool, but UI 
    811                     # changed to int.  
     836                    # changed to int. 
    812837                    val = int(val) 
    813838                elif isinstance(rec[fld], int) and isinstance(val, long): 
    814839                    # convert long to int (original field val was int, but UI 
    815                     # changed to long.  
     840                    # changed to long. 
    816841                    val = int(val) 
    817842                elif isinstance(rec[fld], long) and isinstance(val, int): 
    818843                    # convert int to long (original field val was long, but UI 
    819                     # changed to int.  
     844                    # changed to int. 
    820845                    val = long(val) 
    821846 
    822847            if fldType != type(val): 
    823848                ignore = False 
    824                 # Date and DateTime types are handled as character, even if the  
    825                 # native field type is not. Ignore these. NOTE: we have to deal with the  
     849                # Date and DateTime types are handled as character, even if the 
     850                # native field type is not. Ignore these. NOTE: we have to deal with the 
    826851                # string representation of these classes, as there is no primitive for either 
    827852                # 'DateTime' or 'Date'. 
     
    835860                    # Sometimes you want to set it to a sql function, equation, ect. 
    836861                    ignore = True 
    837                 elif fld in self.getNonUpdateFields()
     862                elif fld in nonUpdateFields
    838863                    # don't worry so much if this is just a calculated field. 
    839864                    ignore = True 
     
    842867                    # fields full of empty strings. 
    843868                    ignore = self._newRecords.has_key(rec[keyField]) 
    844                          
     869 
    845870                if not ignore: 
    846871                    msg = _("!!! Data Type Mismatch: field=%s. Expecting: %s; got: %s") \ 
     
    851876        # update the mementos if necessary. 
    852877        old_val = rec[fld] 
    853         nonUpdateFields = self.getNonUpdateFields() 
    854878        if old_val != val: 
    855879            if valid_pk: 
     
    890914 
    891915    def getRecordStatus(self, row=None): 
    892         """ Returns a dictionary containing an element for each changed  
     916        """ Returns a dictionary containing an element for each changed 
    893917        field in the specified record (or the current record if none is specified). 
    894918        The field name is the key for each element; the value is a 2-element 
    895         tuple, with the first element being the original value, and the second  
     919        tuple, with the first element being the original value, and the second 
    896920        being the current value. 
    897921        """ 
     
    903927        recKey = self.pkExpression(rec) 
    904928        mem = self._mementos.get(recKey, {}) 
    905      
     929 
    906930        for k, v in mem.items(): 
    907931            ret[k] = (v, rec[k]) 
     
    910934 
    911935    def _getNewRecordDiff(self, row=None): 
    912         """ Returns a dictionary containing an element for each field  
     936        """ Returns a dictionary containing an element for each field 
    913937        in the specified record (or the current record if none is specified). 
    914938        The field name is the key for each element; the value is a 2-element 
    915         tuple, with the first element being the original value, and the second  
     939        tuple, with the first element being the original value, and the second 
    916940        being the current value. 
    917941 
     
    938962            ret = None 
    939963        return ret 
    940          
    941          
     964 
     965 
    942966    def getDataSet(self, flds=(), rowStart=0, rows=None, returnInternals=False): 
    943         """ Get the entire data set encapsulated in a dDataSet object.  
    944  
    945         If the optional 'flds' parameter is given, the result set will be filtered  
     967        """ Get the entire data set encapsulated in a dDataSet object. 
     968 
     969        If the optional 'flds' parameter is given, the result set will be filtered 
    946970        to only include the specified fields. rowStart specifies the starting row 
    947         to include, and rows is the number of rows to return.  
     971        to include, and rows is the number of rows to return. 
    948972        """ 
    949973        ds = [] 
     
    970994        return dDataSet(ds) 
    971995 
    972      
     996 
    973997    def replace(self, field, valOrExpr, scope=None): 
    974998        """Replaces the value of the specified field with the given value 
    975999        or expression. All records matching the scope are affected; if 
    9761000        no scope is specified, all records are affected. 
    977          
     1001 
    9781002        'valOrExpr' will be treated as a literal value, unless it is prefixed 
    979         with an equals sign. All expressions will therefore be a string  
    980         beginning with '='. Literals can be of any type.  
     1003        with an equals sign. All expressions will therefore be a string 
     1004        beginning with '='. Literals can be of any type. 
    9811005        """ 
    9821006        if isinstance(self._records, dDataSet): 
    9831007            # Make sure that the data set object has any necessary references 
    9841008            self._records.Cursor = self 
    985             self._records.Bizobj = self._bizobj             
     1009            self._records.Bizobj = self._bizobj 
    9861010            self._records.replace(field, valOrExpr, scope=scope) 
    987              
     1011 
    9881012 
    9891013    def first(self): 
     
    10511075                        self.rollbackTransaction() 
    10521076                    raise 
    1053      
     1077 
     1078        self._syncAuxProperties() 
    10541079        if useTransaction: 
    10551080            self.beginTransaction() 
     
    10651090            if pk in self._mementos.keys(): 
    10661091                saverow(self.RowNumber) 
    1067          
     1092 
    10681093        if useTransaction: 
    10691094            self.commitTransaction() 
     
    11001125                    # add value to expression 
    11011126                    vals += ", %s" % (self.formatForQuery(vv[1]),) 
    1102                      
     1127 
    11031128                # Trim leading comma-space from the strings 
    11041129                flds = flds[2:] 
     
    11161141                pkWhere = self.makePkWhere(row) 
    11171142                updClause = self.makeUpdClause(diff) 
    1118                 sql = "update %s set %s where %s" % (self.BackendObject.encloseNames(self.Table, aq),  
     1143                sql = "update %s set %s where %s" % (self.BackendObject.encloseNames(self.Table, aq), 
    11191144                        updClause, pkWhere) 
    11201145            oldPKVal = self.pkExpression(rec) 
    11211146            newPKVal = None 
    11221147            if newrec and self.AutoPopulatePK: 
    1123                 # Some backends do not provide a means to retrieve  
    1124                 # auto-generated PKs; for those, we need to create the  
     1148                # Some backends do not provide a means to retrieve 
     1149                # auto-generated PKs; for those, we need to create the 
    11251150                # PK before inserting the record so that we can pass it on 
    1126                 # to any linked child records. NOTE: if you are using  
     1151                # to any linked child records. NOTE: if you are using 
    11271152                # compound PKs, this cannot be done. 
    11281153                newPKVal = self.pregenPK() 
    11291154                if newPKVal and not self._compoundKey: 
    11301155                    self.setFieldVal(self.KeyField, newPKVal, row) 
    1131              
     1156 
    11321157            #run the update 
    11331158            aux = self.AuxCursor 
     
    11731198                if row is None: 
    11741199                    # We deleted based on pk, don't delete flag for the current row. 
    1175                     return              
     1200                    return 
    11761201            except: 
    11771202                pass 
     
    11891214 
    11901215    def pregenPK(self): 
    1191         """Various backend databases require that you manually  
     1216        """Various backend databases require that you manually 
    11921217        generate new PKs if you need to refer to their values afterward. 
    1193         This method will call the backend to generate and  
    1194         retrieve a new PK if the backend supports this. We use the  
     1218        This method will call the backend to generate and 
     1219        retrieve a new PK if the backend supports this. We use the 
    11951220        auxiliary cursor so as not to alter the current data. 
    11961221        """ 
    11971222        return self.BackendObject.pregenPK(self.AuxCursor) 
    1198          
    1199          
     1223 
     1224 
    12001225    def new(self): 
    12011226        """Add a new record to the data set.""" 
     
    12181243            else: 
    12191244                raise dException.NoRecordsException, _("No data to cancel.") 
    1220          
     1245 
    12211246        # Faster to deal with 2 specific cases: all rows or just current row 
    12221247        if allRows: 
     
    12281253                delrecs_idx = [] 
    12291254                for rec_id in delrecs_ids: 
    1230                     # Remove any memento associated with the canceled new record, and  
     1255                    # Remove any memento associated with the canceled new record, and 
    12311256                    # append to the list of indexes to delete. 
    12321257                    row, rec = self._getRecordByPk(rec_id) 
     
    12461271                    self._records[row][fld] = val 
    12471272            self._mementos = {} 
    1248          
     1273 
    12491274        else: 
    12501275            row = self.RowNumber 
     
    12611286                    self.RowNumber = self.RowCount - 1 
    12621287                return 
    1263              
     1288 
    12641289            # Not a new record: need to manually replace the old values: 
    12651290            for fld, val in self._mementos.get(recKey, {}).items(): 
    12661291                self._records[row][fld] = val 
    12671292            self._clearMemento(row) 
    1268              
    1269      
     1293 
     1294 
    12701295    def delete(self, delRowNum=None): 
    12711296        """Delete the specified row, or the currently active row.""" 
     
    13031328            # Delete the record from the current dataset 
    13041329            self._removeRow(delRowNum) 
    1305      
    1306      
     1330 
     1331 
    13071332    def _removeRow(self, row): 
    1308         ## Since record sets are tuples and thus immutable, we need to do this  
     1333        ## Since record sets are tuples and thus immutable, we need to do this 
    13091334        ## little dance to remove a row. 
    13101335        lRec = list(self._records) 
     
    13121337        self._records = dDataSet(lRec) 
    13131338        self.RowNumber = min(self.RowNumber, self.RowCount-1) 
    1314      
    1315      
     1339 
     1340 
    13161341    def flush(self): 
    13171342        """ Some backends need to be prompted to flush changes 
     
    13501375            setDefault(keyField, vals[keyField]) 
    13511376            keyFieldSet = True 
    1352              
     1377 
    13531378        for field, val in vals.items(): 
    13541379            if field == keyField and keyFieldSet: 
     
    14051430            chKeys = dict.fromkeys(chKeys + self._newRecords.keys()).keys() 
    14061431        return sorted(map(self._getRowByPk, chKeys), reverse=True) 
    1407          
     1432 
    14081433 
    14091434    def _getRecordByPk(self, pk): 
     
    14281453        """ Find the record with the passed primary key, and make it active. 
    14291454 
    1430         If the record is not found, the position is set to the first record.  
     1455        If the record is not found, the position is set to the first record. 
    14311456        """ 
    14321457        row, rec = self._getRecordByPk(pk) 
     
    14391464        """ Move the record pointer to the specified row number. 
    14401465 
    1441         If the specified row does not exist, the pointer remains where it is,  
     1466        If the specified row does not exist, the pointer remains where it is, 
    14421467        and an exception is raised. 
    14431468        """ 
     
    14691494            raise dException.FieldNotFoundException, _("Non-existent field '%s'" % fld) 
    14701495 
    1471         # Copy the specified field vals and their row numbers to a list, and  
     1496        # Copy the specified field vals and their row numbers to a list, and 
    14721497        # add those lists to the sort list 
    14731498        sortList = [] 
     
    15041529            sortList.sort() 
    15051530 
    1506         # Now iterate through the list to find the matching value. I know that  
     1531        # Now iterate through the list to find the matching value. I know that 
    15071532        # there are more efficient search algorithms, but for this purpose, we'll 
    15081533        # just use brute force 
     
    15221547                # If we are doing a near search, see if the row is less than the 
    15231548                # requested matching value. If so, update the value of 'ret'. If not, 
    1524                 # we have passed the matching value, so there's no point in  
     1549                # we have passed the matching value, so there's no point in 
    15251550                # continuing the search. 
    15261551                if compString and not caseSensitive: 
     
    15541579 
    15551580    def makePkWhere(self, row=None): 
    1556         """ Create the WHERE clause used for updates, based on the pk field.  
     1581        """ Create the WHERE clause used for updates, based on the pk field. 
    15571582 
    15581583        Optionally pass in a row number, otherwise use the current record. 
    15591584        """ 
    15601585        bo = self.BackendObject 
    1561         tblPrefix = bo.getWhereTablePrefix(self.Table,  
     1586        tblPrefix = bo.getWhereTablePrefix(self.Table, 
    15621587                    autoQuote=self.AutoQuoteNames) 
    15631588        if not row: 
    15641589            row = self.RowNumber 
    15651590        rec = self._records[row] 
    1566          
     1591 
    15671592        if self._compoundKey: 
    15681593            keyFields = [fld for fld in self.KeyField] 
     
    15771602            else: 
    15781603                return rec[fld] 
    1579              
     1604 
    15801605        ret = "" 
    15811606        for fld in keyFields: 
     
    16121637    def processFields(self, txt): 
    16131638        return self.BackendObject.processFields(txt) 
    1614          
    1615      
     1639 
     1640 
    16161641    def escQuote(self, val): 
    16171642        """ Escape special characters in SQL strings. """ 
     
    16191644        if isinstance(val, basestring): 
    16201645            ret = self.BackendObject.escQuote(val) 
    1621         return ret           
     1646        return ret 
    16221647 
    16231648 
     
    16251650        """ Return a tuple of tables in the current database.""" 
    16261651        return self.BackendObject.getTables(includeSystemTables) 
    1627          
    1628          
     1652 
     1653 
    16291654    def getTableRecordCount(self, tableName): 
    16301655        """ Get the number of records in the backend table.""" 
    16311656        return self.BackendObject.getTableRecordCount(tableName) 
    1632          
    1633          
     1657 
     1658 
    16341659    def getFields(self, tableName=None): 
    16351660        """ Get field information about the backend table. 
    1636          
     1661 
    16371662        Returns a list of 3-tuples, where the 3-tuple's elements are: 
    16381663            0: the field name (string) 
     
    16441669            tableName = self.Table 
    16451670        return self.BackendObject.getFields(tableName) 
    1646      
     1671 
    16471672 
    16481673    def getFieldInfoFromDescription(self): 
     
    16641689        return ret 
    16651690 
    1666      
     1691 
    16671692    def formatForQuery(self, val): 
    16681693        """ Format any value for the backend """ 
     
    16721697        return ret 
    16731698 
    1674      
     1699 
    16751700    def formatDateTime(self, val): 
    16761701        """ Format DateTime values for the backend """ 
     
    17111736            ret = self.BackendObject.rollbackTransaction(self.AuxCursor) 
    17121737        return ret 
    1713      
     1738 
    17141739 
    17151740    def createTable(self, tabledef): 
    17161741        """Create a table based on the table definition.""" 
    17171742        self.BackendObject.createJustTable(tabledef, self) 
    1718          
    1719          
     1743 
     1744 
    17201745    def createIndexes(self, tabledef): 
    17211746        """Create indexes based on the table definition.""" 
    17221747        self.BackendObject.createJustIndexes(tabledef, self) 
    1723          
    1724          
     1748 
     1749 
    17251750    def createTableAndIndexes(self, tabledef): 
    17261751        """Create a table and its indexes based on the table definition.""" 
     
    17441769        beo = sm.BackendObject 
    17451770        if beo: 
    1746             sm._fieldClause = beo.addField(sm._fieldClause, exp, alias,  
     1771            sm._fieldClause = beo.addField(sm._fieldClause, exp, alias, 
    17471772                    autoQuote=self.AutoQuoteNames) 
    17481773        return sm._fieldClause 
     
    17561781    def setFromClause(self, clause): 
    17571782        """ Set the from clause of the sql statement.""" 
    1758         self.sqlManager._fromClause = self.sqlManager.BackendObject.setFromClause(clause,  
     1783        self.sqlManager._fromClause = self.sqlManager.BackendObject.setFromClause(clause, 
    17591784                    autoQuote=self.AutoQuoteNames) 
    17601785 
    17611786 
    17621787    def addFrom(self, exp): 
    1763         """ Add a table to the sql statement. For joins, use  
     1788        """ Add a table to the sql statement. For joins, use 
    17641789        the addJoin() method. 
    17651790        """ 
    17661791        if self.sqlManager.BackendObject: 
    1767             self.sqlManager._fromClause = self.sqlManager.BackendObject.addFrom(self.sqlManager._fromClause, exp,  
     1792            self.sqlManager._fromClause = self.sqlManager.BackendObject.addFrom(self.sqlManager._fromClause, exp, 
    17681793                    autoQuote=self.AutoQuoteNames) 
    17691794        return self.sqlManager._fromClause 
     
    17771802    def setJoinClause(self, clause): 
    17781803        """ Set the join clause of the sql statement.""" 
    1779         self.sqlManager._joinClause = self.sqlManager.BackendObject.setJoinClause(clause,  
     1804        self.sqlManager._joinClause = self.sqlManager.BackendObject.setJoinClause(clause, 
    17801805                    autoQuote=self.AutoQuoteNames) 
    17811806 
     
    17841809        """ Add a joined table to the sql statement.""" 
    17851810        if self.sqlManager.BackendObject: 
    1786             self.sqlManager._joinClause = self.sqlManager.BackendObject.addJoin(tbl,  
    1787                     joinCondition, self.sqlManager._joinClause, joinType,  
     1811            self.sqlManager._joinClause = self.sqlManager.BackendObject.addJoin(tbl, 
     1812                    joinCondition, self.sqlManager._joinClause, joinType, 
    17881813                    autoQuote=self.AutoQuoteNames) 
    17891814        return self.sqlManager._joinClause 
    1790          
     1815 
    17911816 
    17921817 
     
    17981823    def setWhereClause(self, clause): 
    17991824        """ Set the where clause of the sql statement.""" 
    1800         self.sqlManager._whereClause = self.sqlManager.BackendObject.setWhereClause(clause,  
     1825        self.sqlManager._whereClause = self.sqlManager.BackendObject.setWhereClause(clause, 
    18011826                    autoQuote=self.AutoQuoteNames) 
    18021827 
     
    18051830        """ Add an expression to the where clause.""" 
    18061831        if self.sqlManager.BackendObject: 
    1807             self.sqlManager._whereClause = self.sqlManager.BackendObject.addWhere(self.sqlManager._whereClause, exp, comp,  
     1832            self.sqlManager._whereClause = self.sqlManager.BackendObject.addWhere(self.sqlManager._whereClause, exp, comp, 
    18081833                    autoQuote=self.AutoQuoteNames) 
    18091834        return self.sqlManager._whereClause 
     
    18121837    def prepareWhere(self, clause): 
    18131838        """ Modifies WHERE clauses as needed for each backend. """ 
    1814         return self.sqlManager.BackendObject.prepareWhere(clause,  
     1839        return self.sqlManager.BackendObject.prepareWhere(clause, 
    18151840                    autoQuote=self.AutoQuoteNames) 
    1816          
    1817          
     1841 
     1842 
    18181843    def getChildFilterClause(self): 
    18191844        """ Get the child filter part of the sql statement.""" 
     
    18471872        """ Get the order-by clause of the sql statement.""" 
    18481873        return self.sqlManager._orderByClause 
    1849          
     1874 
    18501875 
    18511876    def setOrderByClause(self, clause): 
     
    18571882        """ Add an expression to the order-by clause.""" 
    18581883        if self.sqlManager.BackendObject: 
    1859             self.sqlManager._orderByClause = self.sqlManager.BackendObject.addOrderBy(self.sqlManager._orderByClause,  
     1884            self.sqlManager._orderByClause = self.sqlManager.BackendObject.addOrderBy(self.sqlManager._orderByClause, 
    18601885                    exp, autoQuote=self.AutoQuoteNames) 
    18611886        return self.sqlManager._orderByClause 
     
    18651890        """ Get the limit clause of the sql statement.""" 
    18661891        return self.sqlManager._limitClause 
    1867          
     1892 
    18681893 
    18691894    def setLimitClause(self, clause): 
    18701895        """ Set the limit clause of the sql statement.""" 
    18711896        self.sqlManager._limitClause = clause 
    1872      
     1897 
    18731898    # For simplicity's sake, create aliases 
    18741899    setLimit, getLimit = setLimitClause, getLimitClause 
     
    18821907            ret = self.sqlManager.BackendObject.getLimitWord() 
    18831908        return ret 
    1884          
    1885              
     1909 
     1910 
    18861911    def getLimitPosition(self): 
    18871912        """ Return the position to place the limit clause. 
    1888          
     1913 
    18891914        For currently-supported dbapi's, the return values of 'top' or 'bottom' 
    18901915        are sufficient. 
     
    18941919            ret = self.sqlManager.BackendObject.getLimitPosition() 
    18951920        return ret 
    1896          
    1897              
     1921 
     1922 
    18981923    def getSQL(self): 
    18991924        """ Get the complete SQL statement from all the parts.""" 
     
    19091934        if not fieldClause: 
    19101935            fieldClause = "*" 
    1911          
     1936 
    19121937        if not fromClause: 
    19131938            fromClause = self.Table 
    1914          
     1939 
    19151940        if childFilterClause: 
    19161941            # Prepend it to the where clause 
     
    19191944            whereClause = childFilterClause + " " + whereClause 
    19201945 
    1921         if fromClause:  
     1946        if fromClause: 
    19221947            fromClause = "  from " + fromClause 
    19231948        else: 
     
    19391964            limitClause = " %s %s" % (self.sqlManager.getLimitWord(), self.sqlManager._defaultLimit) 
    19401965