sqlite3 in Python 2.5b1: my out-of-the-box experience

John Machin sjmachin at lexicon.net
Mon Jul 3 22:51:58 EDT 2006


Apologies in advance if this is a bit bloggy, but I'd like to get 
comments on whether I've lost the plot (or, more likely, failed to 
acquire it) before I start reporting bugs etc.

 From "What's new ...":
"""
# Create table
c.execute('''create table stocks
(date timestamp, trans varchar, symbol varchar,
  qty decimal, price decimal)''')

# Insert a row of data
c.execute("""insert into stocks
           values ('2006-01-05','BUY','RHAT',100,35.14)""")
"""

Point 1: Maybe that "timestamp" type for the first column should be 
"date". More on this later.

Point 2: Maybe naming a column "date" wouldn't survive a real code 
review :-)

Query results:
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)

Point 3: Column 1 neither looks nor quacks like a datetime.datetime 
instance.

Point 4: Column 5 is quacking like a float, not a 'decimal'.

Point 5: There are no docs for sqlite3 in the Windows docs gadget that's 
included in the 2.5b1 msi file [or the install didn't blow away the 
2.5a2 docs gadget]. There are docs however at 
http://docs.python.org/dev/lib/module-sqlite3.html

Looking for a way to get dates back instead of strings ... found 
12.13.4.4 Default adapters and converters

Point 6: The example works (produces instances of datetime.* instead of 
Unicode strings) but doesn't explain why *both* varieties of type 
detection are specified in the connect() call.

Wrote a script to check out points 1 and 6:

8<--- start of script ---
import sqlite3, datetime

CREATE = """
     create table stocks (
         trans_date %s,
         trans varchar,
         symbol varchar,
         qty decimal,
         price decimal
         )
     """

INSERT = """
     insert into stocks
         values ('2006-01-05','BUY','RHAT',100,35.14)
     """

def test(col1type, detect_types):
     conn = sqlite3.connect(":memory:", detect_types=detect_types)
     c = conn.cursor()
     c.execute(CREATE % col1type)
     c.execute(INSERT)
     c.execute('select * from stocks')
     for row in c:
         print row
     conn.close()

if __name__ == "__main__":
     for ty in ['timestamp', 'date']:
         for detective in [
             0,
             sqlite3.PARSE_COLNAMES,
             sqlite3.PARSE_DECLTYPES,
             sqlite3.PARSE_COLNAMES | sqlite3.PARSE_DECLTYPES,
             ]:
             print "\ntest(%r, %d):" % (ty, detective)
             test(ty, detective)
8<--- end of script ---

Results of running script:

test('timestamp', 0):
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)

test('timestamp', 2):
(None, u'BUY', u'RHAT', 100, 35.140000000000001)

test('timestamp', 1):
(None, u'BUY', u'RHAT', 100, 35.140000000000001)

test('timestamp', 3):
(None, u'BUY', u'RHAT', 100, 35.140000000000001)

test('date', 0):
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)

test('date', 2):
(datetime.date(2006, 1, 5), u'BUY', u'RHAT', 100, 35.140000000000001)

test('date', 1):
(datetime.date(2006, 1, 5), u'BUY', u'RHAT', 100, 35.140000000000001)

test('date', 3):
(datetime.date(2006, 1, 5), u'BUY', u'RHAT', 100, 35.140000000000001)

Point 7: Type detection on a "timestamp" column causes None to be 
retrieved after a date-only (yyyy-mm-dd) string is inserted. An 
exception (or maybe defaulting the time part to 00:00:00) would be much 
less astonishing.

Point 8: The test definitely doesn't use "... as [... date]" anywhere, 
but PARSE_COLNAMES used in isolation appears to cause retrieval as a 
datetime.date.

Point 9: IMHO the default should be to do both forms of type detection.

Comments on any of the above would be appreciated.

Cheers,
John



More information about the Python-list mailing list