These are the beginnings of a new manual. 1. Connecting to the datatabase =============================== 1.1 Basic usage --------------- Connecting to a datatabase file "db":: import sqlite cx = sqlite.connect("db") 1.2 Parameters explained ------------------------ In the most basic usage, we only used the database parameter, which is the database file we want SQLite to use, or ":memory:" if we want to use an in-RAM database. Of course there are more parameters:: def connect(database, mode=0755, converters={}, autocommit=0, encoding=None, timeout=None, command_logfile=None) mode: This parameter is passed through to SQLite and means the mode in which to open the file. The idea is to be able to open the database file in read-only mode. But it's currently ignored by SQLite so just forget about it. converters: The converters are a mapping from SQL type names to Python conversion callables. You'll only need to define any of these if you want to make PySQLite handle a user-defined type of you transparently. => examples/converters.py autocommit: see => Transaction management encoding: This is an important parameter if you use unicode strings. It can either be a simple encoding name, like "utf-8", or it can be a tuple of encoding name and error policy, like ("utf-8", "ignore"), or ("utf-16", "replace"). Cf. the documentation about the unicode builtin for possible error policies. What it means is in which encoding to save unicode strings in the SQLite database, and from which encoding to construct Unicode strings. timeout: A timeout value in seconds, i. e. timeout=1.5. An SQLite database can be locked by a different connection being in an transaction. The timeout value means how long to wait for the lock to be released. If after /timeout/ seconds the lock is still not released, a DatabaseError will be thrown. command_logfile: A file-like object (anything that has a write method) where all statements sent to the SQLite library will be logged into. 2. Transaction management ========================= 2.1 The standard, DB-API way ---------------------------- Transactions are opened "when necessary". PySQLite is optimized quite a bit at opening transactions as late as possible. I. e. when you have a sequence:: cu = cx.cursor() # (1) cu.execute("select foo from bar") # (2) cu.execute("update foo set bar=5 where blarg=3") # (3) cx.commit() # (4) only line number 3 triggers the sending of a BEGIN statement to the SQLIte library. That's because under SQLite, it is safe to use even multiple SELECT statements outside transactions. The reason is that a BEGIN will lock the whole database, so outside transactions, you will always get consistent data using SELECT statements. Ok, so the .execute() in line #3 sees that it has got a DML (data modification language) statement as SQL string and will transparently send a BEGIN before that to the SQLite engine. .commit() will send the corresponding COMMIT statement, of course. To roll back transactions intead, you'd use .rollback() on the connection object. see => examples/dbapi_transactions.py 2.2 The manual way ------------------ If you used the parameter autocommit=1 in the sqlite.connect() call, PySQLite will not get in your way with respect to transactions. You can send BEGIN/COMMIT/ROLLBACK statements with the .execute() method of the cursor object as you like. see => examples/manual_transactions.py I don't recommend you actually use this option, unless you're implementing a transaction management system different from the DB-API one. 3. Conversions Python => SQLite =============================== This section only matters if you want to create your own types and use them transparently with SQLite. Just provide them with a _quote() method that will return a string ready to be inserted directly into a SQL statement. You'll then also want to register a suitable converter callable with the converters parameter of the connect() function. 4. Conversions SQLITE => Python =============================== SQLite itself is typeless, it only knows about strings, and to some degree about numbers. So PySQLite has to work around this limitation. The conversion from string to the Python type we want works with a hidden dictionary called converters, which consists of the converters you registered in the .connect() call yourself, plus a few standard ones from PySQLite, listed below. +-------------------------+-------------------+--------------------------------+ | column types | converter name | converter callable | +=========================+===================+================================+ | \*CHAR\*, \*TEXT\* | str | str() | +-------------------------+-------------------+--------------------------------+ | \*INT\* | int | int() | +-------------------------+-------------------+--------------------------------+ | | long | long() | +-------------------------+-------------------+--------------------------------+ | \*FLOAT\*, \*NUMERIC\*, | float | float() | | \*NUMBER\*, \*DECIMAL\*,| | | | \*REAL\*, \*DOUBLE\* | | | +-------------------------+-------------------+--------------------------------+ | \*UNICODE\* | unicode | UnicodeConverter(self.encoding)| +-------------------------+-------------------+--------------------------------+ | \*BINARY\*, \*BLOB\* | binary | sqlite.decode() | +-------------------------+-------------------+--------------------------------+ | \*DATE\* | date | DateTime.DateFrom() | +-------------------------+-------------------+--------------------------------+ | \*TIME\* | time | DateTime.TimeFrom() | +-------------------------+-------------------+--------------------------------+ | \*TIMESTAMP\* | timestamp | DateTime.DateTimeFrom() | +-------------------------+-------------------+--------------------------------+ | \*INTERVAL\* | interval | DateTime.DateTimeDeltaFrom() | +-------------------------+-------------------+--------------------------------+ Now there are two ways to determine which converter to use for a given column in the resultset. If the column came directly from a table, and wasn't created by an expression, or by a function or aggregate, then SQLite delivers column type to PySQLite, and PySQLite will then use a certain converter, depending on the column type. Let's use an example to make this more clear:: CREATE TABLE TEST (V VARCHAR, I INTEGER); INSERT INTO TEST(V, I) VALUES ('foo', 25); >>> cu = cx.cursor() >>> cu.execute("select v, i from test") >>> row = cu.fetchone() >>> row, map(type, row) (('foo', 25), [, ]) Now, with the statement "select v, i from test" you directly accessed the columns 'v' and 'i' in the table 'test'. SQLite is thus able to deliver the types of the columns to PySQLite. PySQLite thus knows that the first column is of type VARCHAR, and the second column is of type INTEGER. Now VARCHAR matches *CHAR* and INTEGER matches *INT*, so PySQLite finds the converter name 'str' for the first column in the resultset, and the converter name 'int' for the second column. Now 'str' maps to str() and 'int' maps to int(), so these two callables are called for the raw string data PySQLite gets from the SQLite engine. For you, this means you transparently got back an integer for the second column, even though SQLite basically only knows about strings. Now let's try something else: >>> cu.execute("select i*2.3 from test") >>> row = cu.fetchone() >>> row, map(type, row) ((57.5,), []) There's a little magic going on here. SQLite infers that the result is numeric, so it sets "NUMERIC" as the type of the result column, which in turn by PySQLite is mapped to the converter name 'float', and then to the callable float. Now of course there are areas where there is no magic left and you have to tell PySQLite yourself to which type to convert back. Basically always when result columns don't come directly from tables, but from expressions. One example would be where you'd want to concatenate two columns of a UNICODE type: >>> cx = sqlite.connect("db", encoding="utf-8") >>> cu = cx.cursor() >>> cu.execute("create table test(u1 unicode, u2 unicode)") >>> cu.execute("insert into test(u1, u2) values (%s, %s)", (u"\x99sterreich", u"Ungarn")) >>> cu.execute("select u1 || '-' || u2 from test") >>> print cu.fetchone() ('\xc2\x99sterreich-Ungarn',) We didn't specify what type to convert to, so we just got a normal Python string back, with the result in UTF-8 encoding. So let's specifiy the converter name with the magical "-- types type1[, type2 ...]" SQL command that PySQLite intercepts and interprets itself and try again: >>> cu.execute("-- types unicode") >>> cu.execute("select u1 || '-' || u2 from test") >>> row = cu.fetchone() >>> row, map(type, row) ((u'\x99sterreich-Ungarn',), [])