Mercurial > p > roundup > code
comparison roundup/backends/back_sqlite.py @ 3718:0d561b24ceff
support sqlite3
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Wed, 04 Oct 2006 01:12:00 +0000 |
| parents | a775afeeee8b |
| children | b476fef16ccc |
comparison
equal
deleted
inserted
replaced
| 3717:5770f1802cd0 | 3718:0d561b24ceff |
|---|---|
| 1 # $Id: back_sqlite.py,v 1.46 2006-08-30 09:05:30 schlatterbeck Exp $ | 1 # $Id: back_sqlite.py,v 1.47 2006-10-04 01:12:00 richard Exp $ |
| 2 '''Implements a backend for SQLite. | 2 '''Implements a backend for SQLite. |
| 3 | 3 |
| 4 See https://pysqlite.sourceforge.net/ for pysqlite info | 4 See https://pysqlite.sourceforge.net/ for pysqlite info |
| 5 | 5 |
| 6 | 6 |
| 11 | 11 |
| 12 import os, base64, marshal, shutil, time, logging | 12 import os, base64, marshal, shutil, time, logging |
| 13 | 13 |
| 14 from roundup import hyperdb, date, password | 14 from roundup import hyperdb, date, password |
| 15 from roundup.backends import rdbms_common | 15 from roundup.backends import rdbms_common |
| 16 is_sqlite3 = False | |
| 16 try: | 17 try: |
| 17 import sqlite | 18 import sqlite |
| 18 except ImportError: | 19 except ImportError: |
| 19 from pysqlite2 import dbapi2 as sqlite | 20 try: |
| 21 from pysqlite2 import dbapi2 as sqlite | |
| 22 except ImportError: | |
| 23 import sqlite3 as sqlite | |
| 24 is_sqlite3 = True | |
| 20 | 25 |
| 21 def db_exists(config): | 26 def db_exists(config): |
| 22 return os.path.exists(os.path.join(config.DATABASE, 'db')) | 27 return os.path.exists(os.path.join(config.DATABASE, 'db')) |
| 23 | 28 |
| 24 def db_nuke(config): | 29 def db_nuke(config): |
| 25 shutil.rmtree(config.DATABASE) | 30 shutil.rmtree(config.DATABASE) |
| 26 | 31 |
| 27 class Database(rdbms_common.Database): | 32 class Database(rdbms_common.Database): |
| 28 # char to use for positional arguments | 33 # char to use for positional arguments |
| 29 arg = '%s' | 34 if is_sqlite3: |
| 35 arg = '?' | |
| 36 else: | |
| 37 arg = '%s' | |
| 30 | 38 |
| 31 # used by some code to switch styles of query | 39 # used by some code to switch styles of query |
| 32 implements_intersect = 1 | 40 implements_intersect = 1 |
| 33 | 41 |
| 34 hyperdb_to_sql_datatypes = { | 42 hyperdb_to_sql_datatypes = { |
| 86 if not os.path.isdir(self.config.DATABASE): | 94 if not os.path.isdir(self.config.DATABASE): |
| 87 os.makedirs(self.config.DATABASE) | 95 os.makedirs(self.config.DATABASE) |
| 88 | 96 |
| 89 db = os.path.join(self.config.DATABASE, 'db') | 97 db = os.path.join(self.config.DATABASE, 'db') |
| 90 logging.getLogger('hyperdb').info('open database %r'%db) | 98 logging.getLogger('hyperdb').info('open database %r'%db) |
| 91 conn = sqlite.connect(db=db) | |
| 92 # set a 30 second timeout (extraordinarily generous) for handling | 99 # set a 30 second timeout (extraordinarily generous) for handling |
| 93 # locked database | 100 # locked database |
| 94 conn.db.sqlite_busy_handler(self.sqlite_busy_handler) | 101 if is_sqlite3: |
| 102 conn = sqlite.connect(db, 30) | |
| 103 conn.row_factory = sqlite.Row | |
| 104 else: | |
| 105 conn = sqlite.connect(db=db) | |
| 106 conn.db.sqlite_busy_handler(self.sqlite_busy_handler) | |
| 95 cursor = conn.cursor() | 107 cursor = conn.cursor() |
| 96 return (conn, cursor) | 108 return (conn, cursor) |
| 97 | 109 |
| 98 def open_connection(self): | 110 def open_connection(self): |
| 99 # ensure files are group readable and writable | 111 # ensure files are group readable and writable |
| 250 d = [] | 262 d = [] |
| 251 for name in inscols: | 263 for name in inscols: |
| 252 # generate the new value for the Interval int column | 264 # generate the new value for the Interval int column |
| 253 if name.endswith('_int__'): | 265 if name.endswith('_int__'): |
| 254 name = name[2:-6] | 266 name = name[2:-6] |
| 255 if entry.has_key(name): | 267 if is_sqlite3: |
| 268 try: | |
| 269 v = hyperdb.Interval(entry[name]).as_seconds() | |
| 270 except IndexError: | |
| 271 v = None | |
| 272 elif entry.has_key(name): | |
| 256 v = hyperdb.Interval(entry[name]).as_seconds() | 273 v = hyperdb.Interval(entry[name]).as_seconds() |
| 257 else: | 274 else: |
| 258 v = None | 275 v = None |
| 259 elif entry.has_key(name): | 276 elif is_sqlite3: |
| 277 try: | |
| 278 v = entry[name] | |
| 279 except IndexError: | |
| 280 v = None | |
| 281 elif (not is_sqlite3 and entry.has_key(name)): | |
| 260 v = entry[name] | 282 v = entry[name] |
| 261 else: | 283 else: |
| 262 v = None | 284 v = None |
| 263 d.append(v) | 285 d.append(v) |
| 264 self.sql(sql, tuple(d)) | 286 self.sql(sql, tuple(d)) |
| 340 for cn in self.classes.keys(): | 362 for cn in self.classes.keys(): |
| 341 self.setid(cn, 0) | 363 self.setid(cn, 0) |
| 342 | 364 |
| 343 def create_class(self, spec): | 365 def create_class(self, spec): |
| 344 rdbms_common.Database.create_class(self, spec) | 366 rdbms_common.Database.create_class(self, spec) |
| 345 sql = 'insert into ids (name, num) values (%s, %s)' | 367 sql = 'insert into ids (name, num) values (%s, %s)'%(self.arg, self.arg) |
| 346 vals = (spec.classname, 1) | 368 vals = (spec.classname, 1) |
| 347 self.sql(sql, vals) | 369 self.sql(sql, vals) |
| 370 | |
| 371 if is_sqlite3: | |
| 372 def load_journal(self, classname, cols, nodeid): | |
| 373 '''We need to turn the sqlite3.Row into a tuple so it can be | |
| 374 unpacked''' | |
| 375 l = rdbms_common.Database.load_journal(self, | |
| 376 classname, cols, nodeid) | |
| 377 cols = range(5) | |
| 378 return [[row[col] for col in cols] for row in l] | |
| 348 | 379 |
| 349 class sqliteClass: | 380 class sqliteClass: |
| 350 def filter(self, search_matches, filterspec, sort=(None,None), | 381 def filter(self, search_matches, filterspec, sort=(None,None), |
| 351 group=(None,None)): | 382 group=(None,None)): |
| 352 ''' If there's NO matches to a fetch, sqlite returns NULL | 383 ''' If there's NO matches to a fetch, sqlite returns NULL |
