5 from sqlite3 import IntegrityError
9 class DBError(Exception):
13 def get_db(dbfile, stderr=sys.stderr,
14 create_version=(None, None), updaters={}, just_create=False, dbname="db",
15 journal_mode=None, synchronous=None):
16 """Open or create the given db file. The parent directory must exist.
17 create_version=(SCHEMA, VERNUM), and SCHEMA must have a 'version' table.
18 Updaters is a {newver: commands} mapping, where e.g. updaters[2] is used
19 to get from ver=1 to ver=2. Returns a (sqlite3,db) tuple, or raises
22 must_create = not os.path.exists(dbfile)
24 db = sqlite3.connect(dbfile)
25 except (EnvironmentError, sqlite3.OperationalError), e:
26 raise DBError("Unable to create/open %s file %s: %s" % (dbname, dbfile, e))
28 schema, target_version = create_version
31 # Enabling foreign keys allows stricter integrity checking.
32 # The default is unspecified according to <http://www.sqlite.org/foreignkeys.html#fk_enable>.
33 c.execute("PRAGMA foreign_keys = ON;")
35 if journal_mode is not None:
36 c.execute("PRAGMA journal_mode = %s;" % (journal_mode,))
38 if synchronous is not None:
39 c.execute("PRAGMA synchronous = %s;" % (synchronous,))
42 c.executescript(schema)
43 c.execute("INSERT INTO version (version) VALUES (?)", (target_version,))
47 c.execute("SELECT version FROM version")
48 version = c.fetchone()[0]
49 except sqlite3.DatabaseError, e:
50 # this indicates that the file is not a compatible database format.
51 # Perhaps it was created with an old version, or it might be junk.
52 raise DBError("%s file is unusable: %s" % (dbname, e))
54 if just_create: # for tests
57 while version < target_version and version+1 in updaters:
58 c.executescript(updaters[version+1])
61 if version != target_version:
62 raise DBError("Unable to handle %s version %s" % (dbname, version))