Skip to content

Commit a5e4968

Browse files
author
gerhard.haering
committed
Merged changes from standalone version 2.3.3. This should probably all be
merged into the 2.5 maintenance branch: - self->statement was not checked while fetching data, which could lead to crashes if you used the pysqlite API in unusual ways. Closing the cursor and continuing to fetch data was enough. - Converters are stored in a converters dictionary. The converter name is uppercased first. The old upper-casing algorithm was wrong and was replaced by a simple call to the Python string's upper() method instead. -Applied patch by Glyph Lefkowitz that fixes the problem with subsequent SQLITE_SCHEMA errors. - Improvement to the row type: rows can now be iterated over and have a keys() method. This improves compatibility with both tuple and dict a lot. - A bugfix for the subsecond resolution in timestamps. - Corrected the way the flags PARSE_DECLTYPES and PARSE_COLNAMES are checked for. Now they work as documented. - gcc on Linux sucks. It exports all symbols by default in shared libraries, so if symbols are not unique it can lead to problems with symbol lookup. pysqlite used to crash under Apache when mod_cache was enabled because both modules had the symbol cache_init. I fixed this by applying the prefix pysqlite_ almost everywhere. Sigh. git-svn-id: http://svn.python.org/projects/python/trunk@53420 6015fed2-1504-0410-9fe1-9d1591cc4771
1 parent 3ce3114 commit a5e4968

22 files changed

Lines changed: 574 additions & 490 deletions

Lib/sqlite3/dbapi2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def convert_timestamp(val):
6868
timepart_full = timepart.split(".")
6969
hours, minutes, seconds = map(int, timepart_full[0].split(":"))
7070
if len(timepart_full) == 2:
71-
microseconds = int(float("0." + timepart_full[1]) * 1000000)
71+
microseconds = int(timepart_full[1])
7272
else:
7373
microseconds = 0
7474

Lib/sqlite3/test/factory.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def CheckCustomFactory(self):
9191
list),
9292
"row is not instance of list")
9393

94-
def CheckSqliteRow(self):
94+
def CheckSqliteRowIndex(self):
9595
self.con.row_factory = sqlite.Row
9696
row = self.con.execute("select 1 as a, 2 as b").fetchone()
9797
self.failUnless(isinstance(row,
@@ -110,6 +110,27 @@ def CheckSqliteRow(self):
110110
self.failUnless(col1 == 1, "by index: wrong result for column 0")
111111
self.failUnless(col2 == 2, "by index: wrong result for column 1")
112112

113+
def CheckSqliteRowIter(self):
114+
"""Checks if the row object is iterable"""
115+
self.con.row_factory = sqlite.Row
116+
row = self.con.execute("select 1 as a, 2 as b").fetchone()
117+
for col in row:
118+
pass
119+
120+
def CheckSqliteRowAsTuple(self):
121+
"""Checks if the row object can be converted to a tuple"""
122+
self.con.row_factory = sqlite.Row
123+
row = self.con.execute("select 1 as a, 2 as b").fetchone()
124+
t = tuple(row)
125+
126+
def CheckSqliteRowAsDict(self):
127+
"""Checks if the row object can be correctly converted to a dictionary"""
128+
self.con.row_factory = sqlite.Row
129+
row = self.con.execute("select 1 as a, 2 as b").fetchone()
130+
d = dict(row)
131+
self.failUnlessEqual(d["a"], row["a"])
132+
self.failUnlessEqual(d["b"], row["b"])
133+
113134
def tearDown(self):
114135
self.con.close()
115136

Lib/sqlite3/test/regression.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ def CheckColumnNameWithSpaces(self):
6969
cur.execute('select 1 as "foo baz"')
7070
self.failUnlessEqual(cur.description[0][0], "foo baz")
7171

72+
def CheckStatementAvailable(self):
73+
# pysqlite up to 2.3.2 crashed on this, because the active statement handle was not checked
74+
# before trying to fetch data from it. close() destroys the active statement ...
75+
con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_DECLTYPES)
76+
cur = con.cursor()
77+
cur.execute("select 4 union select 5")
78+
cur.close()
79+
cur.fetchone()
80+
cur.fetchone()
81+
7282
def suite():
7383
regression_suite = unittest.makeSuite(RegressionTests, "Check")
7484
return unittest.TestSuite((regression_suite,))

Lib/sqlite3/test/types.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ def setUp(self):
106106
# and implement two custom ones
107107
sqlite.converters["BOOL"] = lambda x: bool(int(x))
108108
sqlite.converters["FOO"] = DeclTypesTests.Foo
109+
sqlite.converters["WRONG"] = lambda x: "WRONG"
109110

110111
def tearDown(self):
111112
del sqlite.converters["FLOAT"]
@@ -117,7 +118,7 @@ def tearDown(self):
117118
def CheckString(self):
118119
# default
119120
self.cur.execute("insert into test(s) values (?)", ("foo",))
120-
self.cur.execute("select s from test")
121+
self.cur.execute('select s as "s [WRONG]" from test')
121122
row = self.cur.fetchone()
122123
self.failUnlessEqual(row[0], "foo")
123124

@@ -204,26 +205,32 @@ def CheckBlob(self):
204205

205206
class ColNamesTests(unittest.TestCase):
206207
def setUp(self):
207-
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES|sqlite.PARSE_DECLTYPES)
208+
self.con = sqlite.connect(":memory:", detect_types=sqlite.PARSE_COLNAMES)
208209
self.cur = self.con.cursor()
209210
self.cur.execute("create table test(x foo)")
210211

211212
sqlite.converters["FOO"] = lambda x: "[%s]" % x
212213
sqlite.converters["BAR"] = lambda x: "<%s>" % x
213214
sqlite.converters["EXC"] = lambda x: 5/0
215+
sqlite.converters["B1B1"] = lambda x: "MARKER"
214216

215217
def tearDown(self):
216218
del sqlite.converters["FOO"]
217219
del sqlite.converters["BAR"]
218220
del sqlite.converters["EXC"]
221+
del sqlite.converters["B1B1"]
219222
self.cur.close()
220223
self.con.close()
221224

222-
def CheckDeclType(self):
225+
def CheckDeclTypeNotUsed(self):
226+
"""
227+
Assures that the declared type is not used when PARSE_DECLTYPES
228+
is not set.
229+
"""
223230
self.cur.execute("insert into test(x) values (?)", ("xxx",))
224231
self.cur.execute("select x from test")
225232
val = self.cur.fetchone()[0]
226-
self.failUnlessEqual(val, "[xxx]")
233+
self.failUnlessEqual(val, "xxx")
227234

228235
def CheckNone(self):
229236
self.cur.execute("insert into test(x) values (?)", (None,))
@@ -241,6 +248,11 @@ def CheckColName(self):
241248
# whitespace should be stripped.
242249
self.failUnlessEqual(self.cur.description[0][0], "x")
243250

251+
def CheckCaseInConverterName(self):
252+
self.cur.execute("""select 'other' as "x [b1b1]\"""")
253+
val = self.cur.fetchone()[0]
254+
self.failUnlessEqual(val, "MARKER")
255+
244256
def CheckCursorDescriptionNoRow(self):
245257
"""
246258
cursor.description should at least provide the column name(s), even if
@@ -334,6 +346,13 @@ def CheckDateTimeSubSeconds(self):
334346
ts2 = self.cur.fetchone()[0]
335347
self.failUnlessEqual(ts, ts2)
336348

349+
def CheckDateTimeSubSecondsFloatingPoint(self):
350+
ts = sqlite.Timestamp(2004, 2, 14, 7, 15, 0, 510241)
351+
self.cur.execute("insert into test(ts) values (?)", (ts,))
352+
self.cur.execute("select ts from test")
353+
ts2 = self.cur.fetchone()[0]
354+
self.failUnlessEqual(ts, ts2)
355+
337356
def suite():
338357
sqlite_type_suite = unittest.makeSuite(SqliteTypeTests, "Check")
339358
decltypes_type_suite = unittest.makeSuite(DeclTypesTests, "Check")

Modules/_sqlite/cache.c

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@
2525
#include <limits.h>
2626

2727
/* only used internally */
28-
Node* new_node(PyObject* key, PyObject* data)
28+
pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data)
2929
{
30-
Node* node;
30+
pysqlite_Node* node;
3131

32-
node = (Node*) (NodeType.tp_alloc(&NodeType, 0));
32+
node = (pysqlite_Node*) (pysqlite_NodeType.tp_alloc(&pysqlite_NodeType, 0));
3333
if (!node) {
3434
return NULL;
3535
}
@@ -46,15 +46,15 @@ Node* new_node(PyObject* key, PyObject* data)
4646
return node;
4747
}
4848

49-
void node_dealloc(Node* self)
49+
void pysqlite_node_dealloc(pysqlite_Node* self)
5050
{
5151
Py_DECREF(self->key);
5252
Py_DECREF(self->data);
5353

5454
self->ob_type->tp_free((PyObject*)self);
5555
}
5656

57-
int cache_init(Cache* self, PyObject* args, PyObject* kwargs)
57+
int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs)
5858
{
5959
PyObject* factory;
6060
int size = 10;
@@ -86,10 +86,10 @@ int cache_init(Cache* self, PyObject* args, PyObject* kwargs)
8686
return 0;
8787
}
8888

89-
void cache_dealloc(Cache* self)
89+
void pysqlite_cache_dealloc(pysqlite_Cache* self)
9090
{
91-
Node* node;
92-
Node* delete_node;
91+
pysqlite_Node* node;
92+
pysqlite_Node* delete_node;
9393

9494
if (!self->factory) {
9595
/* constructor failed, just get out of here */
@@ -112,14 +112,14 @@ void cache_dealloc(Cache* self)
112112
self->ob_type->tp_free((PyObject*)self);
113113
}
114114

115-
PyObject* cache_get(Cache* self, PyObject* args)
115+
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args)
116116
{
117117
PyObject* key = args;
118-
Node* node;
119-
Node* ptr;
118+
pysqlite_Node* node;
119+
pysqlite_Node* ptr;
120120
PyObject* data;
121121

122-
node = (Node*)PyDict_GetItem(self->mapping, key);
122+
node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key);
123123
if (node) {
124124
/* an entry for this key already exists in the cache */
125125

@@ -186,7 +186,7 @@ PyObject* cache_get(Cache* self, PyObject* args)
186186
return NULL;
187187
}
188188

189-
node = new_node(key, data);
189+
node = pysqlite_new_node(key, data);
190190
if (!node) {
191191
return NULL;
192192
}
@@ -211,9 +211,9 @@ PyObject* cache_get(Cache* self, PyObject* args)
211211
return node->data;
212212
}
213213

214-
PyObject* cache_display(Cache* self, PyObject* args)
214+
PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args)
215215
{
216-
Node* ptr;
216+
pysqlite_Node* ptr;
217217
PyObject* prevkey;
218218
PyObject* nextkey;
219219
PyObject* fmt_args;
@@ -265,20 +265,20 @@ PyObject* cache_display(Cache* self, PyObject* args)
265265
}
266266

267267
static PyMethodDef cache_methods[] = {
268-
{"get", (PyCFunction)cache_get, METH_O,
268+
{"get", (PyCFunction)pysqlite_cache_get, METH_O,
269269
PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")},
270-
{"display", (PyCFunction)cache_display, METH_NOARGS,
270+
{"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS,
271271
PyDoc_STR("For debugging only.")},
272272
{NULL, NULL}
273273
};
274274

275-
PyTypeObject NodeType = {
275+
PyTypeObject pysqlite_NodeType = {
276276
PyObject_HEAD_INIT(NULL)
277277
0, /* ob_size */
278278
MODULE_NAME "Node", /* tp_name */
279-
sizeof(Node), /* tp_basicsize */
279+
sizeof(pysqlite_Node), /* tp_basicsize */
280280
0, /* tp_itemsize */
281-
(destructor)node_dealloc, /* tp_dealloc */
281+
(destructor)pysqlite_node_dealloc, /* tp_dealloc */
282282
0, /* tp_print */
283283
0, /* tp_getattr */
284284
0, /* tp_setattr */
@@ -315,13 +315,13 @@ PyTypeObject NodeType = {
315315
0 /* tp_free */
316316
};
317317

318-
PyTypeObject CacheType = {
318+
PyTypeObject pysqlite_CacheType = {
319319
PyObject_HEAD_INIT(NULL)
320320
0, /* ob_size */
321321
MODULE_NAME ".Cache", /* tp_name */
322-
sizeof(Cache), /* tp_basicsize */
322+
sizeof(pysqlite_Cache), /* tp_basicsize */
323323
0, /* tp_itemsize */
324-
(destructor)cache_dealloc, /* tp_dealloc */
324+
(destructor)pysqlite_cache_dealloc, /* tp_dealloc */
325325
0, /* tp_print */
326326
0, /* tp_getattr */
327327
0, /* tp_setattr */
@@ -352,24 +352,24 @@ PyTypeObject CacheType = {
352352
0, /* tp_descr_get */
353353
0, /* tp_descr_set */
354354
0, /* tp_dictoffset */
355-
(initproc)cache_init, /* tp_init */
355+
(initproc)pysqlite_cache_init, /* tp_init */
356356
0, /* tp_alloc */
357357
0, /* tp_new */
358358
0 /* tp_free */
359359
};
360360

361-
extern int cache_setup_types(void)
361+
extern int pysqlite_cache_setup_types(void)
362362
{
363363
int rc;
364364

365-
NodeType.tp_new = PyType_GenericNew;
366-
CacheType.tp_new = PyType_GenericNew;
365+
pysqlite_NodeType.tp_new = PyType_GenericNew;
366+
pysqlite_CacheType.tp_new = PyType_GenericNew;
367367

368-
rc = PyType_Ready(&NodeType);
368+
rc = PyType_Ready(&pysqlite_NodeType);
369369
if (rc < 0) {
370370
return rc;
371371
}
372372

373-
rc = PyType_Ready(&CacheType);
373+
rc = PyType_Ready(&pysqlite_CacheType);
374374
return rc;
375375
}

Modules/_sqlite/cache.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@
2929
* dictionary. The list items are of type 'Node' and the dictionary has the
3030
* nodes as values. */
3131

32-
typedef struct _Node
32+
typedef struct _pysqlite_Node
3333
{
3434
PyObject_HEAD
3535
PyObject* key;
3636
PyObject* data;
3737
long count;
38-
struct _Node* prev;
39-
struct _Node* next;
40-
} Node;
38+
struct _pysqlite_Node* prev;
39+
struct _pysqlite_Node* next;
40+
} pysqlite_Node;
4141

4242
typedef struct
4343
{
@@ -50,24 +50,24 @@ typedef struct
5050
/* the factory callable */
5151
PyObject* factory;
5252

53-
Node* first;
54-
Node* last;
53+
pysqlite_Node* first;
54+
pysqlite_Node* last;
5555

5656
/* if set, decrement the factory function when the Cache is deallocated.
5757
* this is almost always desirable, but not in the pysqlite context */
5858
int decref_factory;
59-
} Cache;
59+
} pysqlite_Cache;
6060

61-
extern PyTypeObject NodeType;
62-
extern PyTypeObject CacheType;
61+
extern PyTypeObject pysqlite_NodeType;
62+
extern PyTypeObject pysqlite_CacheType;
6363

64-
int node_init(Node* self, PyObject* args, PyObject* kwargs);
65-
void node_dealloc(Node* self);
64+
int pysqlite_node_init(pysqlite_Node* self, PyObject* args, PyObject* kwargs);
65+
void pysqlite_node_dealloc(pysqlite_Node* self);
6666

67-
int cache_init(Cache* self, PyObject* args, PyObject* kwargs);
68-
void cache_dealloc(Cache* self);
69-
PyObject* cache_get(Cache* self, PyObject* args);
67+
int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs);
68+
void pysqlite_cache_dealloc(pysqlite_Cache* self);
69+
PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args);
7070

71-
int cache_setup_types(void);
71+
int pysqlite_cache_setup_types(void);
7272

7373
#endif

0 commit comments

Comments
 (0)