:func:`connect` function.
Setting it makes the :mod:`sqlite3` module parse the declared type for each
- column it returns. It will parse out the first word of the declared type, i. e.
- for "integer primary key", it will parse out "integer". Then for that column, it
- will look into the converters dictionary and use the converter function
- registered for that type there. Converter names are case-sensitive!
+ column it returns. It will parse out the first word of the declared type,
+ i. e. for "integer primary key", it will parse out "integer", or for
+ "number(10)" it will parse out "number". Then for that column, it will look
+ into the converters dictionary and use the converter function registered for
+ that type there.
.. data:: PARSE_COLNAMES
Converter functions **always** get called with a string, no matter under which
data type you sent the value to SQLite.
-.. note::
-
- Converter names are looked up in a case-sensitive manner.
-
::
def convert_point(s):
def setUp(self):
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
self.cur = self.con.cursor()
- self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob)")
+ self.cur.execute("create table test(i int, s str, f float, b bool, u unicode, foo foo, bin blob, n1 number, n2 number(5))")
# override float, make them always return the same number
sqlite.converters["FLOAT"] = lambda x: 47.2
sqlite.converters["BOOL"] = lambda x: bool(int(x))
sqlite.converters["FOO"] = DeclTypesTests.Foo
sqlite.converters["WRONG"] = lambda x: "WRONG"
+ sqlite.converters["NUMBER"] = float
def tearDown(self):
del sqlite.converters["FLOAT"]
del sqlite.converters["BOOL"]
del sqlite.converters["FOO"]
+ del sqlite.converters["NUMBER"]
self.cur.close()
self.con.close()
row = self.cur.fetchone()
self.failUnlessEqual(row[0], val)
+ def CheckNumber1(self):
+ self.cur.execute("insert into test(n1) values (5)")
+ value = self.cur.execute("select n1 from test").fetchone()[0]
+ # if the converter is not used, it's an int instead of a float
+ self.failUnlessEqual(type(value), float)
+
+ def CheckNumber2(self):
+ """Checks wether converter names are cut off at '(' characters"""
+ self.cur.execute("insert into test(n2) values (5)")
+ value = self.cur.execute("select n2 from test").fetchone()[0]
+ # if the converter is not used, it's an int instead of a float
+ self.failUnlessEqual(type(value), float)
+
class ColNamesTests(unittest.TestCase):
def setUp(self):
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
decltype = sqlite3_column_decltype(self->statement->st, i);
if (decltype) {
for (pos = decltype;;pos++) {
- if (*pos == ' ' || *pos == 0) {
+ /* Converter names are split at '(' and blanks.
+ * This allows 'INTEGER NOT NULL' to be treated as 'INTEGER' and
+ * 'NUMBER(10)' to be treated as 'NUMBER', for example.
+ * In other words, it will work as people expect it to work.*/
+ if (*pos == ' ' || *pos == '(' || *pos == 0) {
py_decltype = PyString_FromStringAndSize(decltype, pos - decltype);
if (!py_decltype) {
return -1;