diff options
-rw-r--r-- | Doc/library/sqlite3.rst | 13 | ||||
-rw-r--r-- | Lib/sqlite3/test/types.py | 17 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.c | 6 |
3 files changed, 26 insertions, 10 deletions
diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst index 85925f4..5408630 100644 --- a/Doc/library/sqlite3.rst +++ b/Doc/library/sqlite3.rst @@ -114,10 +114,11 @@ Module functions and constants :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 @@ -666,10 +667,6 @@ and constructs a :class:`Point` object from it. 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): diff --git a/Lib/sqlite3/test/types.py b/Lib/sqlite3/test/types.py index 1970401..471425d 100644 --- a/Lib/sqlite3/test/types.py +++ b/Lib/sqlite3/test/types.py @@ -98,7 +98,7 @@ class DeclTypesTests(unittest.TestCase): 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 @@ -107,11 +107,13 @@ class DeclTypesTests(unittest.TestCase): 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() @@ -203,6 +205,19 @@ class DeclTypesTests(unittest.TestCase): 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) diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index 2681fc7..308823c 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -202,7 +202,11 @@ int pysqlite_build_row_cast_map(pysqlite_Cursor* self) 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; |