Skip to content

Commit 83598cd

Browse files
rhermanklinkdpgeorge
authored andcommitted
unix-ffi/sqlite3: Change to use close and prepare v2 versions, clean-up.
The sqlite3_prepare and sqlite3_close have been changed to use the v2 version. For the prepare this was done as the v1 version is "legacy", and for close the documentation describes the v2 version to be used for "host languages that are garbage collected, and where the order in which destructors are called is arbitrary", which fits here. Some clean-up to comments has also be done, and the tests now also close the Cursor and Connections. Signed-off-by: Robert Klink <rhermanklink@ripe.net>
1 parent ab9c5a0 commit 83598cd

File tree

3 files changed

+27
-19
lines changed

3 files changed

+27
-19
lines changed

unix-ffi/sqlite3/sqlite3.py

+21-19
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,23 @@
55

66
sq3 = ffilib.open("libsqlite3")
77

8+
# int sqlite3_open(
9+
# const char *filename, /* Database filename (UTF-8) */
10+
# sqlite3 **ppDb /* OUT: SQLite db handle */
11+
# );
812
sqlite3_open = sq3.func("i", "sqlite3_open", "sp")
913
# int sqlite3_config(int, ...);
1014
sqlite3_config = sq3.func("i", "sqlite3_config", "ii")
11-
# int sqlite3_close(sqlite3*);
12-
sqlite3_close = sq3.func("i", "sqlite3_close", "p")
15+
# int sqlite3_close_v2(sqlite3*);
16+
sqlite3_close = sq3.func("i", "sqlite3_close_v2", "p")
1317
# int sqlite3_prepare(
1418
# sqlite3 *db, /* Database handle */
1519
# const char *zSql, /* SQL statement, UTF-8 encoded */
1620
# int nByte, /* Maximum length of zSql in bytes. */
1721
# sqlite3_stmt **ppStmt, /* OUT: Statement handle */
1822
# const char **pzTail /* OUT: Pointer to unused portion of zSql */
1923
# );
20-
sqlite3_prepare = sq3.func("i", "sqlite3_prepare", "psipp")
24+
sqlite3_prepare = sq3.func("i", "sqlite3_prepare_v2", "psipp")
2125
# int sqlite3_finalize(sqlite3_stmt *pStmt);
2226
sqlite3_finalize = sq3.func("i", "sqlite3_finalize", "p")
2327
# int sqlite3_step(sqlite3_stmt*);
@@ -26,20 +30,17 @@
2630
sqlite3_column_count = sq3.func("i", "sqlite3_column_count", "p")
2731
# int sqlite3_column_type(sqlite3_stmt*, int iCol);
2832
sqlite3_column_type = sq3.func("i", "sqlite3_column_type", "pi")
33+
# int sqlite3_column_int(sqlite3_stmt*, int iCol);
2934
sqlite3_column_int = sq3.func("i", "sqlite3_column_int", "pi")
30-
# using "d" return type gives wrong results
35+
# double sqlite3_column_double(sqlite3_stmt*, int iCol);
3136
sqlite3_column_double = sq3.func("d", "sqlite3_column_double", "pi")
37+
# const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
3238
sqlite3_column_text = sq3.func("s", "sqlite3_column_text", "pi")
3339
# sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
34-
# TODO: should return long int
35-
sqlite3_last_insert_rowid = sq3.func("i", "sqlite3_last_insert_rowid", "p")
40+
sqlite3_last_insert_rowid = sq3.func("l", "sqlite3_last_insert_rowid", "p")
3641
# const char *sqlite3_errmsg(sqlite3*);
3742
sqlite3_errmsg = sq3.func("s", "sqlite3_errmsg", "p")
3843

39-
# Too recent
40-
##const char *sqlite3_errstr(int);
41-
# sqlite3_errstr = sq3.func("s", "sqlite3_errstr", "i")
42-
4344

4445
SQLITE_OK = 0
4546
SQLITE_ERROR = 1
@@ -78,8 +79,10 @@ def cursor(self):
7879
return Cursor(self.h)
7980

8081
def close(self):
81-
s = sqlite3_close(self.h)
82-
check_error(self.h, s)
82+
if self.h:
83+
s = sqlite3_close(self.h)
84+
check_error(self.h, s)
85+
self.h = None
8386

8487

8588
class Cursor:
@@ -96,30 +99,30 @@ def execute(self, sql, params=None):
9699
if params:
97100
params = [quote(v) for v in params]
98101
sql = sql % tuple(params)
99-
print(sql)
100102

101103
stmnt_ptr = bytes(get_ptr_size())
102104
res = sqlite3_prepare(self.h, sql, -1, stmnt_ptr, None)
103105
check_error(self.h, res)
104106
self.stmnt = int.from_bytes(stmnt_ptr, sys.byteorder)
105107
self.num_cols = sqlite3_column_count(self.stmnt)
106108

107-
# If it's not select, actually execute it here
108-
# num_cols == 0 for statements which don't return data (=> modify it)
109109
if not self.num_cols:
110110
v = self.fetchone()
111+
# If it's not select, actually execute it here
112+
# num_cols == 0 for statements which don't return data (=> modify it)
111113
assert v is None
112114
self.lastrowid = sqlite3_last_insert_rowid(self.h)
113115

114116
def close(self):
115-
s = sqlite3_finalize(self.stmnt)
116-
check_error(self.h, s)
117+
if self.stmnt:
118+
s = sqlite3_finalize(self.stmnt)
119+
check_error(self.h, s)
120+
self.stmnt = None
117121

118122
def make_row(self):
119123
res = []
120124
for i in range(self.num_cols):
121125
t = sqlite3_column_type(self.stmnt, i)
122-
# print("type", t)
123126
if t == SQLITE_INTEGER:
124127
res.append(sqlite3_column_int(self.stmnt, i))
125128
elif t == SQLITE_FLOAT:
@@ -132,7 +135,6 @@ def make_row(self):
132135

133136
def fetchone(self):
134137
res = sqlite3_step(self.stmnt)
135-
# print("step:", res)
136138
if res == SQLITE_DONE:
137139
return None
138140
if res == SQLITE_ROW:

unix-ffi/sqlite3/test_sqlite3.py

+3
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,6 @@
1717
assert row == e
1818

1919
assert expected == []
20+
21+
cur.close()
22+
conn.close()

unix-ffi/sqlite3/test_sqlite3_2.py

+3
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@
1010
cur.execute("SELECT * FROM foo")
1111
assert cur.fetchone() == (42,)
1212
assert cur.fetchone() is None
13+
14+
cur.close()
15+
conn.close()

0 commit comments

Comments
 (0)