1 # $Id: back_sqlite.py,v 1.13 2004-02-11 23:55:09 richard Exp $
2 '''Implements a backend for SQLite.
4 See https://pysqlite.sourceforge.net/ for pysqlite info
5 '''
6 __docformat__ = 'restructuredtext'
8 import os, base64, marshal
10 from roundup import hyperdb
11 from roundup.backends import rdbms_common
12 from roundup.backends import locking
13 import sqlite
15 class Database(rdbms_common.Database):
16 # char to use for positional arguments
17 arg = '%s'
19 def sql_open_connection(self):
20 # ensure files are group readable and writable
21 os.umask(0002)
22 db = os.path.join(self.config.DATABASE, 'db')
24 # lock it
25 lockfilenm = db[:-3] + 'lck'
26 self.lockfile = locking.acquire_lock(lockfilenm)
27 self.lockfile.write(str(os.getpid()))
28 self.lockfile.flush()
30 self.conn = sqlite.connect(db=db)
31 self.cursor = self.conn.cursor()
32 try:
33 self.database_schema = self.load_dbschema()
34 except sqlite.DatabaseError, error:
35 if str(error) != 'no such table: schema':
36 raise
37 self.database_schema = {}
38 self.cursor.execute('create table schema (schema varchar)')
39 self.cursor.execute('create table ids (name varchar, num integer)')
40 self.cursor.execute('create index ids_name_idx on ids(name)')
42 def sql_close(self):
43 ''' Squash any error caused by us already having closed the
44 connection.
45 '''
46 try:
47 self.conn.close()
48 except sqlite.ProgrammingError, value:
49 if str(value) != 'close failed - Connection is closed.':
50 raise
52 def sql_rollback(self):
53 ''' Squash any error caused by us having closed the connection (and
54 therefore not having anything to roll back)
55 '''
56 try:
57 self.conn.rollback()
58 except sqlite.ProgrammingError, value:
59 if str(value) != 'rollback failed - Connection is closed.':
60 raise
62 def __repr__(self):
63 return '<roundlite 0x%x>'%id(self)
65 def sql_commit(self):
66 ''' Actually commit to the database.
68 Ignore errors if there's nothing to commit.
69 '''
70 try:
71 self.conn.commit()
72 except sqlite.DatabaseError, error:
73 if str(error) != 'cannot commit - no transaction is active':
74 raise
76 def sql_index_exists(self, table_name, index_name):
77 self.cursor.execute('pragma index_list(%s)'%table_name)
78 for entry in self.cursor.fetchall():
79 if entry[1] == index_name:
80 return 1
81 return 0
83 class sqliteClass:
84 def filter(self, search_matches, filterspec, sort=(None,None),
85 group=(None,None)):
86 ''' If there's NO matches to a fetch, sqlite returns NULL
87 instead of nothing
88 '''
89 return filter(None, rdbms_common.Class.filter(self, search_matches,
90 filterspec, sort=sort, group=group))
92 class Class(sqliteClass, rdbms_common.Class):
93 pass
95 class IssueClass(sqliteClass, rdbms_common.IssueClass):
96 pass
98 class FileClass(sqliteClass, rdbms_common.FileClass):
99 pass