Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing bools in SQLite database

Tags:

python

sqlite

In my table schema:

... disabled BOOLEAN, ...

When connecting to db:

db = sqlite3.connect(f, detect_types=sqlite3.PARSE_DECLTYPES)
sqlite3.register_converter("BOOLEAN", myfunc)

I insert a record like so:

INSERT INTO mytable (disabled, ...) VALUES (:disabled, ...)

Along with a parameter dict containing disabled: False.

When I read that record back, myfunc is called to convert the BOOLEAN type:

def myfunc(x):
    print x, type(x)

Result: 0, <type 'str'> (which of course evaluates as True when I want False)

I want bools stored as 1 byte INTEGER, I simply want to convert them to Python bool when reading records (other parts of code expect bools not ints). Is SQLite storing them as strings, or converting them to strings before calling myfunc? Why?

P.S. - I tried using sqlite3.register_adapter(bool, int), to no avail.

like image 962
peu ping Avatar asked Jun 05 '13 09:06

peu ping


People also ask

Does SQLite support a BLOB type?

(10) Does SQLite support a BLOB type? SQLite allows you to store BLOB data in any column, even columns that are declared to hold some other type. BLOBs can even be used as PRIMARY KEYs.

Does an SQLite database support Date Time objects?

SQLite does not support built-in date and/or time storage class. Instead, it leverages some built-in date and time functions to use other storage classes such as TEXT , REAL , or INTEGER for storing the date and time values.

How do I add a Boolean in SQLite?

Basically, SQLite does not support the Boolean data type, so instead of Boolean type SQLite uses the integer data type to execute the Boolean expression in the form of true or false here 0 is used for false and 1 for true that we already discussed.

What is BLOB data type in SQLite?

BLOB stands for a binary large object that is a collection of binary data stored as a value in the database. By using the BLOB, you can store the documents, images, and other multimedia files in the database. We will create a new table named documents for the sake of demonstration.


1 Answers

You want to use a combination of register_adapter and register_converter for the two directions:

sqlite3.register_adapter(bool, int)
sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))

SQLite uses a dynamic type system but for custom types it has no way of knowing for certain if 0 is a string or an integer, so you get a string back here.

Alternatively, use:

sqlite3.register_converter("BOOLEAN", lambda v: v != '0')

which is a lot more flexible and robust when it comes to legacy data, but perhaps you want an exception to be raised.

Demo:

>>> import sqlite3
>>> db = sqlite3.connect(':memory:', detect_types=sqlite3.PARSE_DECLTYPES)
>>> sqlite3.register_adapter(bool, int)
>>> sqlite3.register_converter("BOOLEAN", lambda v: bool(int(v)))
>>> db.execute('CREATE TABLE foo (bar BOOLEAN)')
<sqlite3.Cursor object at 0x10a17a340>
>>> db.execute('INSERT INTO foo VALUES (?)', (True,))
<sqlite3.Cursor object at 0x10a17a3b0>
>>> db.execute('INSERT INTO foo VALUES (?)', (False,))
<sqlite3.Cursor object at 0x10a17a340>
>>> for row in db.execute('SELECT * FROM foo'):
...     print row
... 
(True,)
(False,)
like image 65
Martijn Pieters Avatar answered Sep 28 '22 09:09

Martijn Pieters