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

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