comparison roundup/backends/back_sqlite.py @ 7921:e3975f679bf1

issue2551302 - Remove support for sqlite version 1 from back_sqlite.py Remove sqlite v1 support and document.
author John Rouillard <rouilj@ieee.org>
date Tue, 30 Apr 2024 22:16:22 -0400
parents e10d0b262abd
children 95f91b6f0386
comparison
equal deleted inserted replaced
7920:6aa0525187cd 7921:e3975f679bf1
36 if sqlite.version_info < (2, 1, 0): 36 if sqlite.version_info < (2, 1, 0):
37 raise ValueError('pysqlite2 minimum version is 2.1.0+ ' 37 raise ValueError('pysqlite2 minimum version is 2.1.0+ '
38 '- %s found' % sqlite.version) 38 '- %s found' % sqlite.version)
39 sqlite_version = 2 39 sqlite_version = 2
40 except ImportError: 40 except ImportError:
41 import sqlite 41 raise ValueError("Unable to import sqlite3 or sqlite 2.")
42 sqlite_version = 1
43 42
44 43
45 def db_exists(config): 44 def db_exists(config):
46 return os.path.exists(os.path.join(config.DATABASE, 'db')) 45 return os.path.exists(os.path.join(config.DATABASE, 'db'))
47 46
59 identify the database type so it can import the correct indexer 58 identify the database type so it can import the correct indexer
60 module when using native text search mode. 59 module when using native text search mode.
61 """ 60 """
62 61
63 # char to use for positional arguments 62 # char to use for positional arguments
64 if sqlite_version in (2, 3): 63 arg = '?'
65 arg = '?'
66 else:
67 arg = '%s'
68 64
69 dbtype = "sqlite" 65 dbtype = "sqlite"
70 66
71 # used by some code to switch styles of query 67 # used by some code to switch styles of query
72 implements_intersect = 1 68 implements_intersect = 1
142 self.Otk = sessions_dbm.OneTimeKeys(self) 138 self.Otk = sessions_dbm.OneTimeKeys(self)
143 else: 139 else:
144 self.Otk = sessions_sqlite.OneTimeKeys(self) 140 self.Otk = sessions_sqlite.OneTimeKeys(self)
145 return self.Otk 141 return self.Otk
146 142
147 def sqlite_busy_handler(self, data, table, count):
148 """invoked whenever SQLite tries to access a database that is locked"""
149 now = time.time()
150 if count == 1:
151 # Timeout for handling locked database (default 30s)
152 self._busy_handler_endtime = now + self.config.RDBMS_SQLITE_TIMEOUT
153 elif now > self._busy_handler_endtime:
154 # timeout expired - no more retries
155 return 0
156 # sleep adaptively as retry count grows,
157 # starting from about half a second
158 time_to_sleep = 0.01 * (2 << min(5, count))
159 time.sleep(time_to_sleep)
160 return 1
161
162 def sql_open_connection(self, dbname=None): 143 def sql_open_connection(self, dbname=None):
163 """Open a standard, non-autocommitting connection. 144 """Open a standard, non-autocommitting connection.
164 145
165 pysqlite will automatically BEGIN TRANSACTION for us. 146 pysqlite will automatically BEGIN TRANSACTION for us.
166 """ 147 """
172 if dbname: 153 if dbname:
173 db = os.path.join(self.config.DATABASE, 'db-' + dbname) 154 db = os.path.join(self.config.DATABASE, 'db-' + dbname)
174 else: 155 else:
175 db = os.path.join(self.config.DATABASE, 'db') 156 db = os.path.join(self.config.DATABASE, 'db')
176 logging.getLogger('roundup.hyperdb').info('open database %r' % db) 157 logging.getLogger('roundup.hyperdb').info('open database %r' % db)
177 # set timeout (30 second default is extraordinarily generous) 158 conn = sqlite.connect(db, timeout=self.config.RDBMS_SQLITE_TIMEOUT)
178 # for handling locked database 159 conn.row_factory = sqlite.Row
179 if sqlite_version == 1:
180 conn = sqlite.connect(db=db)
181 conn.db.sqlite_busy_handler(self.sqlite_busy_handler)
182 else:
183 conn = sqlite.connect(db, timeout=self.config.RDBMS_SQLITE_TIMEOUT)
184 conn.row_factory = sqlite.Row
185 160
186 # pysqlite2 / sqlite3 want us to store Unicode in the db but 161 # pysqlite2 / sqlite3 want us to store Unicode in the db but
187 # that's not what's been done historically and it's definitely 162 # that's not what's been done historically and it's definitely
188 # not what the other backends do, so we'll stick with UTF-8 163 # not what the other backends do, so we'll stick with UTF-8
189 if sqlite_version in (2, 3): 164 if sqlite_version in (2, 3):
396 elif sqlite_version in (2, 3): 371 elif sqlite_version in (2, 3):
397 try: 372 try:
398 v = entry[name] 373 v = entry[name]
399 except IndexError: 374 except IndexError:
400 v = None 375 v = None
401 elif (sqlite_version == 1 and name in entry):
402 v = entry[name]
403 else: 376 else:
404 v = None 377 v = None
405 if name == 'id': 378 if name == 'id':
406 retired_id = v 379 retired_id = v
407 elif (name == '__retired__' and retired_id and 380 elif (name == '__retired__' and retired_id and
541 sql = 'insert into ids (name, num) values (%s, %s)' % ( 514 sql = 'insert into ids (name, num) values (%s, %s)' % (
542 self.arg, self.arg) 515 self.arg, self.arg)
543 vals = (spec.classname, 1) 516 vals = (spec.classname, 1)
544 self.sql(sql, vals) 517 self.sql(sql, vals)
545 518
546 if sqlite_version in (2, 3): 519 def load_journal(self, classname, cols, nodeid):
547 def load_journal(self, classname, cols, nodeid): 520 """We need to turn the sqlite3.Row into a tuple so it can be
548 """We need to turn the sqlite3.Row into a tuple so it can be
549 unpacked""" 521 unpacked"""
550 l = rdbms_common.Database.load_journal(self, 522 l = rdbms_common.Database.load_journal(self,
551 classname, cols, nodeid) 523 classname, cols, nodeid)
552 cols = range(5) 524 cols = range(5)
553 return [[row[col] for col in cols] for row in l] 525 return [[row[col] for col in cols] for row in l]
554 526
555 527
556 class sqliteClass: 528 class sqliteClass:
557 def filter(self, *args, **kw): 529 def filter(self, *args, **kw):
558 """ If there's NO matches to a fetch, sqlite returns NULL 530 """ If there's NO matches to a fetch, sqlite returns NULL

Roundup Issue Tracker: http://roundup-tracker.org/