Skip to content

Commit 6250842

Browse files
committed
sqlite3: Start with FFI bindings for SQLite3.
1 parent 966b6c1 commit 6250842

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

sqlite3/sqlite3.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import ffi
2+
3+
4+
sq3 = ffi.open("libsqlite3.so.0")
5+
6+
sqlite3_open = sq3.func("i", "sqlite3_open", "sp")
7+
#int sqlite3_prepare(
8+
# sqlite3 *db, /* Database handle */
9+
# const char *zSql, /* SQL statement, UTF-8 encoded */
10+
# int nByte, /* Maximum length of zSql in bytes. */
11+
# sqlite3_stmt **ppStmt, /* OUT: Statement handle */
12+
# const char **pzTail /* OUT: Pointer to unused portion of zSql */
13+
#);
14+
sqlite3_prepare = sq3.func("i", "sqlite3_prepare", "psipp")
15+
#int sqlite3_step(sqlite3_stmt*);
16+
sqlite3_step = sq3.func("i", "sqlite3_step", "p")
17+
#int sqlite3_column_count(sqlite3_stmt *pStmt);
18+
sqlite3_column_count = sq3.func("i", "sqlite3_column_count", "p")
19+
#int sqlite3_column_type(sqlite3_stmt*, int iCol);
20+
sqlite3_column_type = sq3.func("i", "sqlite3_column_type", "pi")
21+
sqlite3_column_int = sq3.func("i", "sqlite3_column_int", "pi")
22+
# using "d" return type gives wrong results
23+
sqlite3_column_double = sq3.func("f", "sqlite3_column_double", "pi")
24+
sqlite3_column_text = sq3.func("s", "sqlite3_column_text", "pi")
25+
26+
27+
SQLITE_ERROR = 1
28+
SQLITE_BUSY = 5
29+
SQLITE_MISUSE = 21
30+
SQLITE_ROW = 100
31+
SQLITE_DONE = 101
32+
33+
SQLITE_INTEGER = 1
34+
SQLITE_FLOAT = 2
35+
SQLITE_TEXT = 3
36+
SQLITE_BLOB = 4
37+
SQLITE_NULL = 5
38+
39+
40+
class Connections:
41+
42+
def __init__(self, h):
43+
self.h = h
44+
45+
def cursor(self):
46+
return Cursor(self.h)
47+
48+
49+
class Cursor:
50+
51+
def __init__(self, h):
52+
self.h = h
53+
self.s = None
54+
55+
def execute(self, sql):
56+
b = bytearray(4)
57+
sqlite3_prepare(self.h, sql, -1, b, None)
58+
self.s = int.from_bytes(b)
59+
self.num_cols = sqlite3_column_count(self.s)
60+
#print("num_cols", self.num_cols)
61+
62+
def make_row(self):
63+
res = []
64+
for i in range(self.num_cols):
65+
t = sqlite3_column_type(self.s, i)
66+
#print("type", t)
67+
if t == SQLITE_INTEGER:
68+
res.append(sqlite3_column_int(self.s, i))
69+
elif t == SQLITE_FLOAT:
70+
res.append(sqlite3_column_double(self.s, i))
71+
elif t == SQLITE_TEXT:
72+
res.append(sqlite3_column_text(self.s, i))
73+
else:
74+
raise NotImplementedError
75+
return tuple(res)
76+
77+
def fetchone(self):
78+
res = sqlite3_step(self.s)
79+
#print("step:", res)
80+
if res == SQLITE_DONE:
81+
return None
82+
if res == SQLITE_ROW:
83+
return self.make_row()
84+
assert False, res
85+
86+
87+
def connect(fname):
88+
b = bytearray(4)
89+
sqlite3_open(fname, b)
90+
h = int.from_bytes(b)
91+
return Connections(h)

0 commit comments

Comments
 (0)