Changeset 1912

Show
Ignore:
Timestamp:
02/08/06 14:44:41 (3 years ago)
Author:
ed
Message:

Revamped the entire flow for transactions. These changes have been tested on MySQL and SQLite, but still need to be tested with Firebird and PostgreSQL.

Changed the default for bizobjs, cursors, etc., to not autocommit. The AutoCommit? property of the bizobj is simply a pass-through to the cursor's AutoCommit? property.

Also cleaned up some inconsistent spacing and method ordering.

Files:

Legend:

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

    r1876 r1912  
    77 
    88class dBackend(dObject): 
    9     """ Abstract object: inherit from this to define new dabo db interfaces. 
    10     """ 
     9    """ Abstract object: inherit from this to define new dabo db interfaces.""" 
    1110    def __init__(self): 
    1211        self._baseClass = dBackend 
    13         #dBackend.doDefault(self) 
     12        self._autoCommit = False 
     13        # This forces the setting on the connection 
     14        self.AutoCommit = False 
    1415        super(dBackend, self).__init__() 
    1516        self.dbModuleName = None 
    1617        self._connection = None 
    17 #       sysenc = sys.getdefaultencoding() 
    18 #       self._encoding = sysenc == 'ascii' and 'latin-1' or sysenc 
    1918        self._encoding = "utf-8" 
    2019 
     20 
    2121    def isValidModule(self): 
    22         """ Test the dbapi to see if it is supported on this computer.  
    23         """ 
     22        """ Test the dbapi to see if it is supported on this computer.""" 
    2423        try: 
    2524            dbapi = __import__(self.dbModuleName) 
     
    2827            return False 
    2928 
     29 
    3030    def getConnection(self, connectInfo): 
    3131        """ override in subclasses """ 
    3232        return None 
     33         
    3334 
    3435    def getDictCursorClass(self): 
    3536        """ override in subclasses """ 
    3637        return None 
     38         
    3739     
    3840    def getCursor(self, cursorClass): 
    3941        """ override in subclasses if necessary """ 
    4042        return cursorClass(self._connection) 
     43     
    4144     
    4245    def formatDateTime(self, val): 
     
    4851        """ 
    4952        return val 
     53         
    5054 
    5155    def formatNone(self): 
     
    5559        """ 
    5660        return "NULL" 
     61     
    5762     
    5863    def noResultsOnSave(self): 
     
    6267        raise dException.dException, _("No records updated") 
    6368 
     69 
    6470    def noResultsOnDelete(self): 
    6571        """ Most backends will return a non-zero number if there are deletions. 
     
    6874        raise dException.dException, _("No records deleted") 
    6975         
     76         
    7077    def flush(self, cursor): 
    7178        """ Only used in some backends """ 
    7279        return 
     80         
    7381 
    7482    def processFields(self, txt): 
     
    8896        # OVERRIDE IN SUBCLASSES! 
    8997        return val 
     98     
    9099     
    91100    def getLastInsertID(self, cursor): 
     
    96105        This method should be coded in backend-specific subclasses to address 
    97106        that database's approach. 
    98         """ 
    99          
     107        """      
    100108        # Here is some code to fall back on if the specific subclass doesn't  
    101109        # override. 
     
    109117            return None 
    110118 
     119 
    111120    def getTables(self, includeSystemTables=False): 
    112121        """ Return a tuple of the tables in the current database. 
     
    116125        return tuple() 
    117126         
     127         
    118128    def getTableRecordCount(self, tableName): 
    119129        """ Return the number of records in the backend table. 
    120130        """ 
    121131        return -1 
     132     
    122133     
    123134    def getFields(self, tableName): 
     
    146157 
    147158 
     159    def getAutoCommitStatus(self, cursor): 
     160        return self._autoCommit 
     161     
     162     
     163    def setAutoCommitStatus(self, cursor, val): 
     164        if hasattr(self._connection, "autocommit"): 
     165            self._connection.autocommit(val) 
     166            self._autoCommit = val 
     167        else: 
     168            # Without an autocommit method, assume  
     169            # no autocommit. 
     170            self._autoCommit = False 
     171         
     172     
    148173    def beginTransaction(self, cursor): 
    149174        """ Begin a SQL transaction.""" 
    150         try
     175        if not cursor.AutoCommit
    151176            cursor.connection.begin() 
    152         except: 
    153             # Should we raise an error? 
    154             pass 
     177 
    155178         
    156179    def commitTransaction(self, cursor): 
    157180        """ Commit a SQL transaction.""" 
    158         try
     181        if not cursor.AutoCommit
    159182            cursor.connection.commit() 
    160         except: 
    161             # Should we raise an error? 
    162             pass 
     183 
    163184         
    164185    def rollbackTransaction(self, cursor): 
    165186        """ Roll back (revert) a SQL transaction.""" 
    166         try: 
    167             cursor.connection.rollback() 
    168         except: 
    169             # Should we raise an error? 
    170             pass 
     187        cursor.connection.rollback() 
     188 
    171189         
    172190    def addWithSep(self, base, new, sep=",\n\t"): 
     
    181199        return ret 
    182200         
     201         
    183202    def addField(self, clause, exp): 
    184         """ Add a field to the field clause. 
    185         """ 
     203        """ Add a field to the field clause.""" 
    186204        return self.addWithSep(clause, exp) 
    187205 
     206 
    188207    def addFrom(self, clause, exp): 
    189         """ Add a table to the sql statement. 
    190         """ 
     208        """ Add a table to the sql statement.""" 
    191209        return self.addWithSep(clause, exp) 
     210         
    192211 
    193212    def addWhere(self, clause, exp, comp="and"): 
    194         """ Add an expression to the where clause. 
    195         """ 
     213        """ Add an expression to the where clause.""" 
    196214        return self.addWithSep(clause, exp, sep=" %s " % comp) 
     215         
    197216 
    198217    def addGroupBy(self, clause, exp): 
    199         """ Add an expression to the group-by clause. 
    200         """ 
     218        """ Add an expression to the group-by clause.""" 
    201219        return self.addWithSep(clause, exp) 
     220         
    202221 
    203222    def addOrderBy(self, clause, exp): 
    204         """ Add an expression to the order-by clause. 
    205         """ 
     223        """ Add an expression to the order-by clause.""" 
    206224        return self.addWithSep(clause, exp) 
     225         
    207226         
    208227    def getLimitWord(self): 
     
    211230        """ 
    212231        return "limit" 
     232     
    213233     
    214234    def formSQL(self, fieldClause, fromClause,  
     
    223243        return sql 
    224244 
     245 
    225246    def prepareWhere(self, clause): 
    226247        """ Normally, just return the original. Can be overridden as needed 
     
    228249        """ 
    229250        return clause 
     251         
    230252         
    231253    def getWordMatchFormat(self): 
     
    239261        """ 
    240262        return " %(field)s = %(value)s " 
     263 
    241264 
    242265    def getUpdateTablePrefix(self, tbl): 
     
    315338        descFlds = cursor.FieldDescription 
    316339        # Get the raw version of the table 
    317         sql = """select * from %s where 1=0 """ % cursor.Table 
     340        sql = "select * from %s where 1=0 " % cursor.Table 
    318341        auxCrs = cursor._getAuxCursor() 
    319342        auxCrs.execute( sql ) 
     
    409432        """ 
    410433        self._encoding = enc 
     434         
    411435    def _getEncoding(self): 
    412436        """ Get backend encoding.""" 
    413437        return self._encoding 
    414438 
    415     Encoding = property(_getEncoding, _setEncoding, None, "Backend encoding") 
     439    Encoding = property(_getEncoding, _setEncoding, None,  
     440            _("Backend encoding  (str)")) 
  • trunk/dabo/db/dCursorMixin.py

    r1899 r1912  
    137137 
    138138    def execute(self, sql, params=()): 
    139         """ 
    140         The idea here is to let the super class do the actual work in retrieving the data. However,  
    141         many cursor classes can only return row information as a list, not as a dictionary. This 
    142         method will detect that, and convert the results to a dictionary. 
     139        """The idea here is to let the super class do the actual work in  
     140        retrieving the data. However, many cursor classes can only return  
     141        row information as a list, not as a dictionary. This method will  
     142        detect that, and convert the results to a dictionary. 
    143143        """ 
    144144        # Some backends, notably Firebird, require that fields be specially 
     
    265265        # Add mementos to each row of the result set 
    266266        self.addMemento(-1) 
    267  
    268267        # Check for any derived fields that should not be included in  
    269268        # any updates. 
    270269        self.__setNonUpdateFields() 
    271  
    272  
    273270        # Clear the unsorted list, and then apply the current sort 
    274271        self.__unsortedRows = [] 
     
    491488 
    492489    def isChanged(self, allRows=True): 
    493         """    Scan all the records and compare them with their mementos.  
     490        """Scan all the records and compare them with their mementos.  
    494491        Returns True if any differ, False otherwise. 
    495492        """ 
    496493        ret = False 
    497  
    498494        if self.RowCount > 0: 
    499495            if allRows: 
     
    579575        if self.RowCount <= 0: 
    580576            raise dException.NoRecordsException, _("No records in the data set.") 
    581  
    582577        if row is None: 
    583578            row = self.RowNumber 
     
    655650                         
    656651                        if not ignore: 
    657                             msg = "!!! Data Type Mismatch: field=%s. Expecting: %s; got: %s"
     652                            msg = _("!!! Data Type Mismatch: field=%s. Expecting: %s; got: %s")
    658653                                    % (fld, str(fldType), str(type(val))) 
    659654                            dabo.errorLog.write(msg) 
     
    779774 
    780775 
    781     def save(self, allrows=False): 
     776    def save(self, allrows=False, useTransaction=False): 
    782777        """ Save any changes to the data back to the data store.""" 
    783778        # Make sure that there is data to save 
    784779        if self.RowCount <= 0: 
    785780            raise dException.dException, _("No data to save") 
    786  
    787781        # Make sure that there is a PK 
    788782        self.checkPK() 
    789  
    790783        if allrows: 
    791784            recs = self._records 
     
    793786            recs = (self._records[self.RowNumber],) 
    794787 
    795         self.beginTransaction() 
     788        if useTransaction: 
     789            self.beginTransaction() 
    796790 
    797791        for rec in recs: 
     
    802796                    raise dException.ConnectionLostException, e 
    803797                else: 
    804                     # Error was raised. Exit and rollback the changes 
    805                     self.rollbackTransaction() 
     798                    # Error was raised. Exit and rollback the changes if 
     799                    # this object started the transaction. 
     800                    if useTransaction: 
     801                        self.rollbackTransaction() 
    806802                    raise dException.QueryException, e 
    807  
    808         self.commitTransaction() 
     803        if useTransaction: 
     804            self.commitTransaction() 
     805 
    809806 
    810807    def __saverow(self, rec): 
     
    11961193 
    11971194    def checkPK(self): 
    1198         """ Verify that the field(s) specified in the KeyField prop exist. 
    1199         """ 
     1195        """ Verify that the field(s) specified in the KeyField prop exist.""" 
    12001196        # First, make sure that there is *something* in the field 
    12011197        if not self.KeyField: 
     
    12801276        return self.BackendObject.getTables(includeSystemTables) 
    12811277         
     1278         
    12821279    def getTableRecordCount(self, tableName): 
    12831280        """ Get the number of records in the backend table.""" 
    12841281        return self.BackendObject.getTableRecordCount(tableName) 
     1282         
    12851283         
    12861284    def getFields(self, tableName=None): 
     
    13351333        ret = None 
    13361334        if self.BackendObject: 
    1337             ret = self.BackendObject.beginTransaction(self.AuxCursor) 
     1335            if not self.AutoCommit: 
     1336                ret = self.BackendObject.beginTransaction(self.AuxCursor) 
    13381337        return ret 
    13391338 
     
    13431342        ret = None 
    13441343        if self.BackendObject: 
    1345             ret = self.BackendObject.commitTransaction(self.AuxCursor) 
     1344            if not self.AutoCommit: 
     1345                ret = self.BackendObject.commitTransaction(self.AuxCursor) 
    13461346        return ret 
    13471347 
     
    15651565 
    15661566    ## Property getter/setter methods ## 
     1567    def _getAutoCommit(self): 
     1568        return self.BackendObject.getAutoCommitStatus(self) 
     1569         
     1570 
     1571    def _setAutoCommit(self, val): 
     1572        self.BackendObject.setAutoCommitStatus(self, val) 
     1573 
     1574 
    15671575    def _getAutoSQL(self): 
    15681576        return self.getSQL() 
     
    16031611         
    16041612 
     1613    def _getDescrip(self): 
     1614        return self.__backend.getDescription(self) 
     1615         
     1616             
    16051617    def _getEncoding(self): 
    16061618        return self.BackendObject.Encoding 
     
    16101622         
    16111623     
    1612     def _getDescrip(self): 
    1613         return self.__backend.getDescription(self) 
    1614          
    1615              
     1624    def _getIsAdding(self): 
     1625        """ Return True if the current record is a new record.""" 
     1626        return self._records[self.RowNumber].has_key(kons.CURSOR_NEWFLAG) 
     1627         
     1628     
     1629    def _getKeyField(self): 
     1630        try: 
     1631            return self._keyField 
     1632        except AttributeError: 
     1633            return "" 
     1634 
     1635    def _setKeyField(self, kf): 
     1636        self._keyField = str(kf) 
     1637        self.AuxCursor._keyField = str(kf) 
     1638        self._keyFieldSet = True 
     1639 
     1640 
    16161641    def _getLastSQL(self): 
    16171642        try: 
     
    16221647         
    16231648             
    1624     def _getKeyField(self): 
    1625         try: 
    1626             return self._keyField 
    1627         except AttributeError: 
    1628             return "" 
    1629  
    1630     def _setKeyField(self, kf): 
    1631         self._keyField = str(kf) 
    1632         self.AuxCursor._keyField = str(kf) 
    1633         self._keyFieldSet = True 
    1634  
    1635  
    16361649    def _getRowNumber(self): 
    16371650        try: 
     
    16791692 
    16801693 
    1681     def _isAdding(self): 
    1682         """ Return True if the current record is a new record.""" 
    1683         return self._records[self.RowNumber].has_key(kons.CURSOR_NEWFLAG) 
    1684          
     1694    AutoCommit = property(_getAutoCommit, _setAutoCommit, None, 
     1695            _("Do we need explicit begin/commit/rollback commands for transactions?  (bool)")) 
    16851696     
    16861697    AutoSQL = property(_getAutoSQL, None, None, 
     
    17061717            _("Tuple of field names and types, as returned by the backend  (tuple)") ) 
    17071718             
    1708     IsAdding = property(_isAdding, None, None, 
     1719    IsAdding = property(_getIsAdding, None, None, 
    17091720            _("Returns True if the current record is new and unsaved")) 
    17101721             
  • trunk/dabo/db/dbFirebird.py

    r1251 r1912  
    1919        if not port: 
    2020            port = 3050 
    21  
    2221        # kinterbasdb will barf with unicode strings: 
    2322        host = str(connectInfo.Host) 
     
    3029        return self._connection 
    3130         
     31         
    3232    def getDictCursorClass(self): 
    3333        return self.dbapi.Cursor 
     34         
    3435     
    3536    def noResultsOnSave(self): 
     
    4041        return 
    4142     
     43     
    4244    def noResultsOnDelete(self): 
    4345        """ Firebird does not return the number of records deleted, so 
     
    4648        """ 
    4749        return 
     50         
    4851 
    4952    def processFields(self, txt): 
     
    6164        return qt + val.replace(sl, sl+sl).replace(qt, qt+qt) + qt 
    6265     
     66     
    6367    def formatDateTime(self, val): 
    6468        """ We need to wrap the value in quotes. """ 
    6569        sqt = "'"       # single quote 
    6670        return "%s%s%s" % (sqt, str(val), sqt) 
     71 
    6772 
    6873    def getTables(self, includeSystemTables=False): 
     
    9095    def getFields(self, tableName): 
    9196        tempCursor = self._connection.cursor() 
    92          
    9397        # Get the PK 
    9498        sql = """ select inseg.rdb$field_name 
     
    173177        """ Override the default 'limit', since Firebird doesn't use that. """ 
    174178        return "first" 
     179         
    175180 
    176181    def formSQL(self, fieldClause, fromClause,  
  • trunk/dabo/db/dbMySQL.py

    r1693 r1912  
    1111        dBackend.__init__(self) 
    1212        self.dbModuleName = "MySQLdb" 
    13         # Are we using a version of MySQL that supports transactions? 
    14         self.useTransactions = False 
     13 
    1514 
    1615    def getConnection(self, connectInfo): 
     
    4241                db=connectInfo.Database, 
    4342                port=port, **kwargs) 
     43        return self._connection 
    4444 
    45         return self._connection 
    4645 
    4746    def getDictCursorClass(self): 
    4847        import MySQLdb.cursors as cursors 
    4948        return cursors.DictCursor 
     49 
    5050 
    5151    def escQuote(self, val): 
     
    5656        return qt + val.replace(sl, sl+sl).replace(qt, sl+qt) + qt 
    5757     
     58     
    5859    def formatDateTime(self, val): 
    5960        """ We need to wrap the value in quotes. """ 
    6061        sqt = "'"       # single quote 
    6162        return "%s%s%s" % (sqt, str(val), sqt) 
    62          
     63     
     64     
    6365    def getTables(self, includeSystemTables=False): 
    6466        # MySQL doesn't have system tables, in the traditional sense, as  
     
    7274        return tuple(tables) 
    7375         
     76         
    7477    def getTableRecordCount(self, tableName): 
    7578        tempCursor = self._connection.cursor() 
    7679        tempCursor.execute("select count(*) as ncount from %s" % tableName) 
    7780        return tempCursor.fetchall()[0][0] 
     81 
    7882 
    7983    def getFields(self, tableName): 
     
    162166                "VAR_STRING": "C", 
    163167                "YEAR": "?"} 
     168        return daboMapping[typeMapping[backendFieldType]] 
    164169 
    165         return daboMapping[typeMapping[backendFieldType]] 
     170 
     171    def getWordMatchFormat(self): 
     172        """ MySQL's fulltext search expression""" 
     173        return """ match (%(field)s) against ("%(value)s") """ 
    166174 
    167175 
    168176    def beginTransaction(self, cursor): 
    169177        """ Begin a SQL transaction.""" 
    170         if self.useTransactions: 
    171             cursor.execute("BEGIN") 
     178        if not cursor.AutoCommit: 
     179            if hasattr(cursor.connection, "begin"): 
     180                cursor.connection.begin() 
     181            else: 
     182                cursor.execute("BEGIN") 
     183                 
    172184 
    173     def commitTransaction(self, cursor): 
    174         """ Commit a SQL transaction.""" 
    175         if self.useTransactions: 
    176             cursor.execute("COMMIT") 
    177  
    178     def rollbackTransaction(self, cursor): 
    179         """ Roll back (revert) a SQL transaction.""" 
    180         if self.useTransactions: 
    181             cursor.execute("ROLLBACK") 
    182  
    183     def getWordMatchFormat(self): 
    184         """ MySQL's fulltext search expression 
    185         """ 
    186         return """ match (%(field)s) against ("%(value)s") """ 
     185         
  • trunk/dabo/db/dbPostgreSQL.py

    r1186 r1912  
    1414        self.useTransactions = True  # this does not appear to be required 
    1515 
     16 
    1617    def getConnection(self, connectInfo): 
    17         ### TODO: what connector should we use? 
    1818        import psycopg2 as dbapi 
    1919        #from pyPgSQL import PgSQL as dbapi 
     
    2121        #- jfcs 11/01/04 port needs to be a string 
    2222        port = str(connectInfo.Port) 
    23         if not port or port == 'None'
    24             port = '5432' 
     23        if not port or port == "None"
     24            port = "5432" 
    2525                 
    2626        DSN = "host=%s port=%s dbname=%s user=%s password=%s" % (connectInfo.Host, 
     
    3333        return self._connection 
    3434 
     35 
    3536    def getDictCursorClass(self): 
    36         ### TODO: If PostgreSQL doesn't offer specific Dict cursors,  
    37         ###   return a plain one, and Dabo will convert it. 
    3837        # the new psycopg 2.0 supports DictCursor 
    3938        import psycopg2.extras as cursors 
    4039        return cursors.DictCursor  
    4140 
     41 
    4242    def escQuote(self, val): 
    43         ### TODO: This method needs to escape any 'dangerous' characters, 
    44         ###   and properly enclose a string value in quotes. 
    4543        # escape backslashes and single quotes, and 
    4644        # wrap the result in single quotes 
     
    4947        return qt + val.replace(sl, sl+sl).replace(qt, sl+qt) + qt 
    5048     
     49     
    5150    def formatDateTime(self, val): 
    5251        """ We need to wrap the value in quotes. """ 
    53         ### TODO:  How does PostgreSQL handle date-time values? 
    5452        sqt = "'"       # single quote 
    5553        return "%s%s%s" % (sqt, str(val), sqt) 
    56          
     54     
     55     
    5756    def getTables(self, includeSystemTables=False): 
    5857        tempCursor = self._connection.cursor() 
    59         ### TODO: Verify that this is the correct syntax 
    6058        # jfcs 11/01/04 assumed public schema 
    6159        tempCursor.execute("select tablename from pg_tables where schemaname = 'public'") 
     
    6462        for record in rs: 
    6563            tables.append(record[0]) 
     64        return tuple(tables) 
    6665 
    67         return tuple(tables) 
    68          
     66     
    6967    def getTableRecordCount(self, tableName): 
    7068        tempCursor = self._connection.cursor() 
    71         ### TODO: Verify syntax 
    7269        tempCursor.execute("select count(*) as ncount from %s" % tableName) 
    7370        return tempCursor.fetchall()[0][0] 
    7471 
     72 
    7573    def getFields(self, tableName): 
    7674        tempCursor = self._connection.cursor() 
    77         ### TODO: Verify syntax 
    7875        #jfcs 11/01/04 works great from psql (but does not work with the psycopg 
    7976        #module) and only with postgres 7.4.x and later.  Too bad, the statement 
     
    9188        #LEFT JOIN pg_index i ON(cl.oid= i.indrelid) WHERE c.table_name= '%s'" % tableName) 
    9289        #rs=tempCursor.fetchall() 
    93          
    9490         
    9591        # jfcs 11/01/04 Below sucks but works with 7.3.x and 7.4.x (don't know anything 
     
    116112         
    117113        fields = [] 
    118         ### TODO: Verify the field type names returned. 
    119114        for r in rs: 
    120              
    121115            name = r[1] 
    122116            fldType =r[2] 
     
    124118            if thePKFieldName is not None: 
    125119                pk = (name == thePKFieldName) 
    126              
    127120            if 'int' in fldType: 
    128121                fldType = 'I' 
     
    139132            else: 
    140133                fldType = "?" 
    141              
    142              
    143134            fields.append((name.strip(), fldType, pk)) 
    144              
    145135        return tuple(fields) 
    146136         
    147     ### TODO: Customize these for PostgreSQL syntax. 
    148137 
    149     def beginTransaction(self, cursor): 
    150         """ Begin a SQL transaction.""" 
    151         # jfcs 11/01/04 not sure of this 
    152         # Normally Postgres is in the  
    153         # transaction mode always???? 
    154         #if self.useTransactions: 
    155         cursor.execute("BEGIN") 
    156  
    157     def commitTransaction(self, cursor): 
    158         """ Commit a SQL transaction.""" 
    159         #if self.useTransactions: 
    160         cursor.execute("COMMIT") 
    161  
    162     def rollbackTransaction(self, cursor): 
    163         """ Roll back (revert) a SQL transaction.""" 
    164         #if self.useTransactions: 
    165         cursor.execute("ROLLBACK") 
    166          
    167  
    168      
    169138    def getUpdateTablePrefix(self, tbl): 
    170139        """ By default, the update SQL statement will be in the form of 
     
    175144         Postgres needs to return an empty string.""" 
    176145        return "" 
     146         
     147         
    177148    def noResultsOnSave(self): 
    178149        """ Most backends will return a non-zero number if there are updates. 
    179150        Some do not, so this will have to be customized in those cases. 
    180151        """ 
    181         #TODO find out what it should return when it fails.... 
    182152        return  
     153 
    183154 
    184155    def noResultsOnDelete(self): 
     
    187158        """ 
    188159        #raise dException.dException, _("No records deleted") 
    189         #TODO find out what it should return when it fails.... 
    190160        return  
     161 
    191162     
    192163    def flush(self, cursor): 
     
    194165        to the database written to disk. 
    195166        """ 
    196         cursor.execute("COMMIT"
     167        self.commitTransaction(
  • trunk/dabo/db/dbSQLite.py

    r1876 r1912  
    1010        from pysqlite2 import dbapi2 as dbapi 
    1111        self.dbapi = dbapi 
     12         
    1213 
    1314    def getConnection(self, connectInfo): 
     
    1516        self._connection = self.dbapi.connect(pth) 
    1617        return self._connection 
     18         
    1719 
    1820    def getDictCursorClass(self): 
    1921        return self.dbapi.Cursor 
     22         
    2023 
    2124    def escQuote(self, val): 
    2225        if val is None: 
    2326            return self.formatNone() 
    24              
    2527        sl = "\\" 
    2628        qt = "\'" 
     
    2830     
    2931     
     32    def setAutoCommitStatus(self, cursor, val): 
     33        """SQLite doesn't use an 'autocommit()' method. Instead, 
     34        set the isolation_level property of the connection. 
     35        """ 
     36        if val: 
     37            self._connection.isolation_level = None 
     38        else: 
     39            self._connection.isolation_level = "" 
     40        self._autoCommit = val 
     41         
     42     
     43    def beginTransaction(self, cursor): 
     44        """ Begin a SQL transaction. Since pysqlite does an implicit 
     45        'begin' even when not using autocommit, simply do nothing. 
     46        """ 
     47        pass 
     48 
     49         
    3050    def formatDateTime(self, val): 
    3151        """ We need to wrap the value in quotes. """ 
    32         #### TODO: Make sure that the format for DateTime  
    33         ####    values is returned correctly  
    3452        sqt = "'"       # single quote 
    3553        return "%s%s%s" % (sqt, str(val), sqt) 
     
    4967        return tuple(tables) 
    5068         
     69         
    5170    def getTableRecordCount(self, tableName): 
    5271        tempCursor = self._connection.cursor() 
    5372        tempCursor.execute("select count(*) as ncount from %s" % tableName) 
    5473        return tempCursor.fetchall()[0][0] 
     74 
    5575 
    5676    def getFields(self, tableName): 
     
    131151        return "" 
    132152 
     153 
    133154    def noResultsOnSave(self): 
    134155        """ SQLite does not return anything on a successful update""" 
    135156        pass 
     157         
    136158         
    137159    def getStructureDescription(self, cursor): 
     
    184206            else: 
    185207                sql = "CREATE TEMP TABLE " 
    186                  
    187208            sql = sql + tabledef.Name + " (" 
    188209             
     
    225246                if idx.Name.lower() != "primary": 
    226247                    sql = "CREATE INDEX " + idx.Name + " ON " + tabledef.Name + "(" 
    227                      
    228248                    for fld in idx.Fields: 
    229249                        sql = sql + fld + "," 
    230                  
    231250                    if sql[-1:] == ",": 
    232251                        sql = sql[:-1]