Changeset 3212
- Timestamp:
- 06/26/2007 09:33:27 AM (1 year ago)
- Files:
-
- trunk/dabo/db/dCursorMixin.py (modified) (107 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/dabo/db/dCursorMixin.py
r3199 r3212 42 42 ## which we are mixed-in will take the __init__. 43 43 dObject.__init__(self, *args, **kwargs) 44 44 45 45 # Just in case this is used outside of the context of a bizobj 46 46 if not hasattr(self, "superCursor") or self.superCursor is None: … … 76 76 # Flag that is set when the user explicitly sets the Key Field 77 77 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, 80 80 # it will be a separate object. 81 81 self.sqlManager = self … … 94 94 # Holds the data types for each field 95 95 self._types = {} 96 96 97 97 # Holds reference to auxiliary cursor that handles queries that 98 98 # are not supposed to affect the record set. 99 99 self.__auxCursor = None 100 # Marks the cursor as an auxiliary cursor 101 self._isAuxiliary = False 100 102 101 103 # Reference to the object with backend-specific behaviors 102 104 self.__backend = None 103 105 104 106 # Reference to the bizobj that 'owns' this cursor, if any, 105 107 self._bizobj = None 106 108 107 109 # set properties for the SQL Builder functions 108 110 self.clearSQL() 109 111 self.hasSqlBuilder = True 110 112 111 113 # props for building the auxiliary cursor 112 114 self._cursorFactoryFunc = None … … 116 118 self._mementos = {} 117 119 self._newRecords = {} 118 120 119 121 # Flag preference cursors so that they don't fill up the logs 120 122 self._isPrefCursor = False … … 126 128 self._cursorFactoryFunc = func 127 129 self._cursorFactoryClass = cls 128 129 130 131 130 132 def clearSQL(self): 131 133 self._fieldClause = "" … … 139 141 self._defaultLimit = 1000 140 142 141 143 142 144 def getSortColumn(self): 143 145 return self.sortColumn … … 150 152 def getSortCase(self): 151 153 return self.sortCase 152 153 154 155 154 156 def pkExpression(self, rec=None): 155 157 """Returns the PK expression for the passed record.""" … … 161 163 pk = rec[self.KeyField] 162 164 return pk 163 165 164 166 165 167 def _correctFieldType(self, field_val, field_name, _fromRequery=False): 166 168 """Correct the type of the passed field_val, based on self.DataStructure. 167 169 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 170 172 self.DataStructure reports. The latter can happen with SQLite, for example, 171 173 which only knows about a quite limited number of types. … … 248 250 # ret = field_val.tostring() 249 251 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)") 251 253 % (repr(field_val), pythonType, field_name)) 252 254 return ret … … 255 257 def execute(self, sql, params=(), _fromRequery=False): 256 258 """ 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 260 262 # detect that, and convert the results to a dictionary. 261 263 … … 266 268 sql = unicode(sql, self.Encoding) 267 269 sql = self.processFields(sql) 268 270 269 271 try: 270 272 if params is None or len(params) == 0: … … 314 316 dic = {} 315 317 for idx, fldName in enumerate(fldNames): 316 dic[fldName] = self._correctFieldType(field_val=row[idx], 318 dic[fldName] = self._correctFieldType(field_val=row[idx], 317 319 field_name=fldName, _fromRequery=_fromRequery) 318 320 tmpRows.append(dic) … … 337 339 def executeSafe(self, sql): 338 340 """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 346 369 def requery(self, params=None): 347 370 self._lastSQL = self.CurrentSQL … … 350 373 351 374 self.execute(self.CurrentSQL, params, _fromRequery=True) 352 375 353 376 # clear mementos and new record flags: 354 377 self._mementos = {} 355 378 self._newRecords = {} 356 379 357 # Check for any derived fields that should not be included in 380 # Check for any derived fields that should not be included in 358 381 # any updates. 359 382 self.__setNonUpdateFields() … … 379 402 target._types[field_alias] = dabo.db.getPythonType(field_type) 380 403 381 404 382 405 def sort(self, col, dir=None, caseSensitive=True): 383 406 """ Sort the result set on the specified column in the specified order. 384 407 385 If the sort direction is not specified, sort() cycles among Ascending, 408 If the sort direction is not specified, sort() cycles among Ascending, 386 409 Descending and no sort order. 387 410 """ … … 400 423 newCol = col 401 424 if col == currCol: 402 # Not changing the column; most likely they are flipping 425 # Not changing the column; most likely they are flipping 403 426 # the sort order. 404 427 if (dir is None) or not dir: … … 426 449 else: 427 450 raise dException.dException, _("Invalid Sort direction specified: ") + dir 428 451 429 452 self.__sortRows(newCol, newOrd, caseSensitive) 430 453 # Save the current sort values … … 437 460 """ Sort the rows of the cursor. 438 461 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 440 463 preserve the unsorted order if we haven't done that yet; then we sort 441 464 the data according to the request. … … 444 467 if not kf: 445 468 return 446 469 447 470 if not self.__unsortedRows: 448 471 # Record the PK values … … 509 532 sortfunc = caseInsensitiveSort 510 533 else: 511 sortfunc = noneSort 534 sortfunc = noneSort 512 535 sortList.sort(sortfunc) 513 536 514 537 # Unless DESC was specified as the sort order, we're done sorting 515 538 if ord == "DESC": … … 535 558 else: 536 559 self.RowNumber = 0 537 538 560 561 539 562 def cursorToXML(self): 540 """ Returns an XML string containing the information necessary to 563 """ Returns an XML string containing the information necessary to 541 564 re-create this cursor. 542 565 """ … … 555 578 </row> 556 579 """ 557 580 558 581 colTemplate = """ <column name="%s" type="%s">%s</column>""" 559 582 560 583 rowXML = "" 561 584 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)) 563 586 for k,v in rec.items() ] 564 587 rowXML += rowTemplate % "\n".join(recInfo) 565 return base % (self.Encoding, self.AutoPopulatePK, self.KeyField, 588 return base % (self.Encoding, self.AutoPopulatePK, self.KeyField, 566 589 self.Table, rowXML) 567 590 568 591 569 592 def getType(self, val): 570 593 try: … … 573 596 ret = "-unknown-" 574 597 return ret 575 576 598 599 577 600 def escape(self, val): 578 601 """ Provides the proper escaping of values in XML output """ … … 583 606 return ret 584 607 608 585 609 def setNonUpdateFields(self, fldList=None): 586 610 if fldList is None: 587 611 fldList = [] 588 612 self.nonUpdateFields = fldList 589 590 613 614 591 615 def getNonUpdateFields(self): 592 616 return list(set(self.nonUpdateFields + self.__nonUpdateFields)) 593 594 617 618 595 619 def __setNonUpdateFields(self): 596 620 """Automatically set the non-update fields.""" … … 608 632 # Delegate to the backend object to figure it out. 609 633 self.BackendObject.setNonUpdateFields(self) 610 634 611 635 612 636 def isChanged(self, allRows=True, includeNewUnchanged=False): 613 637 """Return True if there are any changes to the local field values. 614 638 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 616 640 considered. Otherwise, only the current record will be checked. 617 641 618 642 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 620 644 considered 'changed', will be counted as 'changed'. 621 645 """ … … 644 668 645 669 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 647 671 method after cursor.new(), and (if applicable) after cursor.genTempAutoPK(). 648 672 For example: … … 650 674 cursor.genTempAutoPK() 651 675 cursor.setNewFlag() 652 """ 676 """ 653 677 if self.KeyField: 654 678 rec = self._records[self.RowNumber] … … 672 696 # No records; default to string 673 697 pkVal = "" 674 698 675 699 tmpPK = self._genTempPKVal(pkVal) 676 700 if isinstance(kf, tuple): … … 681 705 rec[kons.CURSOR_TMPKEY_FIELD] = tmpPK 682 706 return tmpPK 683 684 707 708 685 709 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 687 711 postfixed with '-dabotmp' to avoid potential conflicts with actual PKs 688 712 """ … … 693 717 ret = "%s-dabotmp" % ret 694 718 return ret 695 696 719 720 697 721 def getPK(self): 698 722 """ 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 700 724 PK, return a tuple containing each field's values. 701 725 """ … … 715 739 ret = rec[kf] 716 740 return ret 717 741 718 742 719 743 def getFieldVal(self, fld, row=None): … … 756 780 typ = [ff[1] for ff in flds if ff[0] == fld][0] 757 781 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 759 783 # determine its type 760 784 typ = None … … 766 790 ret = None 767 791 return ret 768 792 769 793 770 794 def _hasValidKeyField(self): … … 799 823 else: 800 824 fldType = self._fldTypeFromDB(fld) 825 nonUpdateFields = self.getNonUpdateFields() 801 826 if fldType is not None: 802 827 if fldType != type(val): … … 809 834 elif isinstance(rec[fld], int) and isinstance(val, bool): 810 835 # convert bool to int (original field val was bool, but UI 811 # changed to int. 836 # changed to int. 812 837 val = int(val) 813 838 elif isinstance(rec[fld], int) and isinstance(val, long): 814 839 # convert long to int (original field val was int, but UI 815 # changed to long. 840 # changed to long. 816 841 val = int(val) 817 842 elif isinstance(rec[fld], long) and isinstance(val, int): 818 843 # convert int to long (original field val was long, but UI 819 # changed to int. 844 # changed to int. 820 845 val = long(val) 821 846 822 847 if fldType != type(val): 823 848 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 826 851 # string representation of these classes, as there is no primitive for either 827 852 # 'DateTime' or 'Date'. … … 835 860 # Sometimes you want to set it to a sql function, equation, ect. 836 861 ignore = True 837 elif fld in self.getNonUpdateFields():862 elif fld in nonUpdateFields: 838 863 # don't worry so much if this is just a calculated field. 839 864 ignore = True … … 842 867 # fields full of empty strings. 843 868 ignore = self._newRecords.has_key(rec[keyField]) 844 869 845 870 if not ignore: 846 871 msg = _("!!! Data Type Mismatch: field=%s. Expecting: %s; got: %s") \ … … 851 876 # update the mementos if necessary. 852 877 old_val = rec[fld] 853 nonUpdateFields = self.getNonUpdateFields()854 878 if old_val != val: 855 879 if valid_pk: … … 890 914 891 915 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 893 917 field in the specified record (or the current record if none is specified). 894 918 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 896 920 being the current value. 897 921 """ … … 903 927 recKey = self.pkExpression(rec) 904 928 mem = self._mementos.get(recKey, {}) 905 929 906 930 for k, v in mem.items(): 907 931 ret[k] = (v, rec[k]) … … 910 934 911 935 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 913 937 in the specified record (or the current record if none is specified). 914 938 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 916 940 being the current value. 917 941 … … 938 962 ret = None 939 963 return ret 940 941 964 965 942 966 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 946 970 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. 948 972 """ 949 973 ds = [] … … 970 994 return dDataSet(ds) 971 995 972 996 973 997 def replace(self, field, valOrExpr, scope=None): 974 998 """Replaces the value of the specified field with the given value 975 999 or expression. All records matching the scope are affected; if 976 1000 no scope is specified, all records are affected. 977 1001 978 1002 '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. 981 1005 """ 982 1006 if isinstance(self._records, dDataSet): 983 1007 # Make sure that the data set object has any necessary references 984 1008 self._records.Cursor = self 985 self._records.Bizobj = self._bizobj 1009 self._records.Bizobj = self._bizobj 986 1010 self._records.replace(field, valOrExpr, scope=scope) 987 1011 988 1012 989 1013 def first(self): … … 1051 1075 self.rollbackTransaction() 1052 1076 raise 1053 1077 1078 self._syncAuxProperties() 1054 1079 if useTransaction: 1055 1080 self.beginTransaction() … … 1065 1090 if pk in self._mementos.keys(): 1066 1091 saverow(self.RowNumber) 1067 1092 1068 1093 if useTransaction: 1069 1094 self.commitTransaction() … … 1100 1125 # add value to expression 1101 1126 vals += ", %s" % (self.formatForQuery(vv[1]),) 1102 1127 1103 1128 # Trim leading comma-space from the strings 1104 1129 flds = flds[2:] … … 1116 1141 pkWhere = self.makePkWhere(row) 1117 1142 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), 1119 1144 updClause, pkWhere) 1120 1145 oldPKVal = self.pkExpression(rec) 1121 1146 newPKVal = None 1122 1147 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 1125 1150 # 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 1127 1152 # compound PKs, this cannot be done. 1128 1153 newPKVal = self.pregenPK() 1129 1154 if newPKVal and not self._compoundKey: 1130 1155 self.setFieldVal(self.KeyField, newPKVal, row) 1131 1156 1132 1157 #run the update 1133 1158 aux = self.AuxCursor … … 1173 1198 if row is None: 1174 1199 # We deleted based on pk, don't delete flag for the current row. 1175 return 1200 return 1176 1201 except: 1177 1202 pass … … 1189 1214 1190 1215 def pregenPK(self): 1191 """Various backend databases require that you manually 1216 """Various backend databases require that you manually 1192 1217 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 1195 1220 auxiliary cursor so as not to alter the current data. 1196 1221 """ 1197 1222 return self.BackendObject.pregenPK(self.AuxCursor) 1198 1199 1223 1224 1200 1225 def new(self): 1201 1226 """Add a new record to the data set.""" … … 1218 1243 else: 1219 1244 raise dException.NoRecordsException, _("No data to cancel.") 1220 1245 1221 1246 # Faster to deal with 2 specific cases: all rows or just current row 1222 1247 if allRows: … … 1228 1253 delrecs_idx = [] 1229 1254 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 1231 1256 # append to the list of indexes to delete. 1232 1257 row, rec = self._getRecordByPk(rec_id) … … 1246 1271 self._records[row][fld] = val 1247 1272 self._mementos = {} 1248 1273 1249 1274 else: 1250 1275 row = self.RowNumber … … 1261 1286 self.RowNumber = self.RowCount - 1 1262 1287 return 1263 1288 1264 1289 # Not a new record: need to manually replace the old values: 1265 1290 for fld, val in self._mementos.get(recKey, {}).items(): 1266 1291 self._records[row][fld] = val 1267 1292 self._clearMemento(row) 1268 1269 1293 1294 1270 1295 def delete(self, delRowNum=None): 1271 1296 """Delete the specified row, or the currently active row.""" … … 1303 1328 # Delete the record from the current dataset 1304 1329 self._removeRow(delRowNum) 1305 1306 1330 1331 1307 1332 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 1309 1334 ## little dance to remove a row. 1310 1335 lRec = list(self._records) … … 1312 1337 self._records = dDataSet(lRec) 1313 1338 self.RowNumber = min(self.RowNumber, self.RowCount-1) 1314 1315 1339 1340 1316 1341 def flush(self): 1317 1342 """ Some backends need to be prompted to flush changes … … 1350 1375 setDefault(keyField, vals[keyField]) 1351 1376 keyFieldSet = True 1352 1377 1353 1378 for field, val in vals.items(): 1354 1379 if field == keyField and keyFieldSet: … … 1405 1430 chKeys = dict.fromkeys(chKeys + self._newRecords.keys()).keys() 1406 1431 return sorted(map(self._getRowByPk, chKeys), reverse=True) 1407 1432 1408 1433 1409 1434 def _getRecordByPk(self, pk): … … 1428 1453 """ Find the record with the passed primary key, and make it active. 1429 1454 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. 1431 1456 """ 1432 1457 row, rec = self._getRecordByPk(pk) … … 1439 1464 """ Move the record pointer to the specified row number. 1440 1465 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, 1442 1467 and an exception is raised. 1443 1468 """ … … 1469 1494 raise dException.FieldNotFoundException, _("Non-existent field '%s'" % fld) 1470 1495 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 1472 1497 # add those lists to the sort list 1473 1498 sortList = [] … … 1504 1529 sortList.sort() 1505 1530 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 1507 1532 # there are more efficient search algorithms, but for this purpose, we'll 1508 1533 # just use brute force … … 1522 1547 # If we are doing a near search, see if the row is less than the 1523 1548 # 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 1525 1550 # continuing the search. 1526 1551 if compString and not caseSensitive: … … 1554 1579 1555 1580 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. 1557 1582 1558 1583 Optionally pass in a row number, otherwise use the current record. 1559 1584 """ 1560 1585 bo = self.BackendObject 1561 tblPrefix = bo.getWhereTablePrefix(self.Table, 1586 tblPrefix = bo.getWhereTablePrefix(self.Table, 1562 1587 autoQuote=self.AutoQuoteNames) 1563 1588 if not row: 1564 1589 row = self.RowNumber 1565 1590 rec = self._records[row] 1566 1591 1567 1592 if self._compoundKey: 1568 1593 keyFields = [fld for fld in self.KeyField] … … 1577 1602 else: 1578 1603 return rec[fld] 1579 1604 1580 1605 ret = "" 1581 1606 for fld in keyFields: … … 1612 1637 def processFields(self, txt): 1613 1638 return self.BackendObject.processFields(txt) 1614 1615 1639 1640 1616 1641 def escQuote(self, val): 1617 1642 """ Escape special characters in SQL strings. """ … … 1619 1644 if isinstance(val, basestring): 1620 1645 ret = self.BackendObject.escQuote(val) 1621 return ret 1646 return ret 1622 1647 1623 1648 … … 1625 1650 """ Return a tuple of tables in the current database.""" 1626 1651 return self.BackendObject.getTables(includeSystemTables) 1627 1628 1652 1653 1629 1654 def getTableRecordCount(self, tableName): 1630 1655 """ Get the number of records in the backend table.""" 1631 1656 return self.BackendObject.getTableRecordCount(tableName) 1632 1633 1657 1658 1634 1659 def getFields(self, tableName=None): 1635 1660 """ Get field information about the backend table. 1636 1661 1637 1662 Returns a list of 3-tuples, where the 3-tuple's elements are: 1638 1663 0: the field name (string) … … 1644 1669 tableName = self.Table 1645 1670 return self.BackendObject.getFields(tableName) 1646 1671 1647 1672 1648 1673 def getFieldInfoFromDescription(self): … … 1664 1689 return ret 1665 1690 1666 1691 1667 1692 def formatForQuery(self, val): 1668 1693 """ Format any value for the backend """ … … 1672 1697 return ret 1673 1698 1674 1699 1675 1700 def formatDateTime(self, val): 1676 1701 """ Format DateTime values for the backend """ … … 1711 1736 ret = self.BackendObject.rollbackTransaction(self.AuxCursor) 1712 1737 return ret 1713 1738 1714 1739 1715 1740 def createTable(self, tabledef): 1716 1741 """Create a table based on the table definition.""" 1717 1742 self.BackendObject.createJustTable(tabledef, self) 1718 1719 1743 1744 1720 1745 def createIndexes(self, tabledef): 1721 1746 """Create indexes based on the table definition.""" 1722 1747 self.BackendObject.createJustIndexes(tabledef, self) 1723 1724 1748 1749 1725 1750 def createTableAndIndexes(self, tabledef): 1726 1751 """Create a table and its indexes based on the table definition.""" … … 1744 1769 beo = sm.BackendObject 1745 1770 if beo: 1746 sm._fieldClause = beo.addField(sm._fieldClause, exp, alias, 1771 sm._fieldClause = beo.addField(sm._fieldClause, exp, alias, 1747 1772 autoQuote=self.AutoQuoteNames) 1748 1773 return sm._fieldClause … … 1756 1781 def setFromClause(self, clause): 1757 1782 """ 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, 1759 1784 autoQuote=self.AutoQuoteNames) 1760 1785 1761 1786 1762 1787 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 1764 1789 the addJoin() method. 1765 1790 """ 1766 1791 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, 1768 1793 autoQuote=self.AutoQuoteNames) 1769 1794 return self.sqlManager._fromClause … … 1777 1802 def setJoinClause(self, clause): 1778 1803 """ 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, 1780 1805 autoQuote=self.AutoQuoteNames) 1781 1806 … … 1784 1809 """ Add a joined table to the sql statement.""" 1785 1810 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, 1788 1813 autoQuote=self.AutoQuoteNames) 1789 1814 return self.sqlManager._joinClause 1790 1815 1791 1816 1792 1817 … … 1798 1823 def setWhereClause(self, clause): 1799 1824 """ 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, 1801 1826 autoQuote=self.AutoQuoteNames) 1802 1827 … … 1805 1830 """ Add an expression to the where clause.""" 1806 1831 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, 1808 1833 autoQuote=self.AutoQuoteNames) 1809 1834 return self.sqlManager._whereClause … … 1812 1837 def prepareWhere(self, clause): 1813 1838 """ Modifies WHERE clauses as needed for each backend. """ 1814 return self.sqlManager.BackendObject.prepareWhere(clause, 1839 return self.sqlManager.BackendObject.prepareWhere(clause, 1815 1840 autoQuote=self.AutoQuoteNames) 1816 1817 1841 1842 1818 1843 def getChildFilterClause(self): 1819 1844 """ Get the child filter part of the sql statement.""" … … 1847 1872 """ Get the order-by clause of the sql statement.""" 1848 1873 return self.sqlManager._orderByClause 1849 1874 1850 1875 1851 1876 def setOrderByClause(self, clause): … … 1857 1882 """ Add an expression to the order-by clause.""" 1858 1883 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, 1860 1885 exp, autoQuote=self.AutoQuoteNames) 1861 1886 return self.sqlManager._orderByClause … … 1865 1890 """ Get the limit clause of the sql statement.""" 1866 1891 return self.sqlManager._limitClause 1867 1892 1868 1893 1869 1894 def setLimitClause(self, clause): 1870 1895 """ Set the limit clause of the sql statement.""" 1871 1896 self.sqlManager._limitClause = clause 1872 1897 1873 1898 # For simplicity's sake, create aliases 1874 1899 setLimit, getLimit = setLimitClause, getLimitClause … … 1882 1907 ret = self.sqlManager.BackendObject.getLimitWord() 1883 1908 return ret 1884 1885 1909 1910 1886 1911 def getLimitPosition(self): 1887 1912 """ Return the position to place the limit clause. 1888 1913 1889 1914 For currently-supported dbapi's, the return values of 'top' or 'bottom' 1890 1915 are sufficient. … … 1894 1919 ret = self.sqlManager.BackendObject.getLimitPosition() 1895 1920 return ret 1896 1897 1921 1922 1898 1923 def getSQL(self): 1899 1924 """ Get the complete SQL statement from all the parts.""" … … 1909 1934 if not fieldClause: 1910 1935 fieldClause = "*" 1911 1936 1912 1937 if not fromClause: 1913 1938 fromClause = self.Table 1914 1939 1915 1940 if childFilterClause: 1916 1941 # Prepend it to the where clause … … 1919 1944 whereClause = childFilterClause + " " + whereClause 1920 1945 1921 if fromClause: 1946 if fromClause: 1922 1947 fromClause = " from " + fromClause 1923 1948 else: … … 1939 1964 limitClause = " %s %s" % (self.sqlManager.getLimitWord(), self.sqlManager._defaultLimit) 1940 1965
