diff --git a/sqlite3/sqlite3.py b/sqlite3/sqlite3.py index bc883dfc..970f130f 100644 --- a/sqlite3/sqlite3.py +++ b/sqlite3/sqlite3.py @@ -4,6 +4,8 @@ import ffi sq3 = ffi.open("libsqlite3.so.0") sqlite3_open = sq3.func("i", "sqlite3_open", "sp") +#int sqlite3_close(sqlite3*); +sqlite3_close = sq3.func("i", "sqlite3_close", "p") #int sqlite3_prepare( # sqlite3 *db, /* Database handle */ # const char *zSql, /* SQL statement, UTF-8 encoded */ @@ -12,6 +14,8 @@ sqlite3_open = sq3.func("i", "sqlite3_open", "sp") # const char **pzTail /* OUT: Pointer to unused portion of zSql */ #); sqlite3_prepare = sq3.func("i", "sqlite3_prepare", "psipp") +#int sqlite3_finalize(sqlite3_stmt *pStmt); +sqlite3_finalize = sq3.func("i", "sqlite3_finalize", "p") #int sqlite3_step(sqlite3_stmt*); sqlite3_step = sq3.func("i", "sqlite3_step", "p") #int sqlite3_column_count(sqlite3_stmt *pStmt); @@ -22,8 +26,15 @@ sqlite3_column_int = sq3.func("i", "sqlite3_column_int", "pi") # using "d" return type gives wrong results sqlite3_column_double = sq3.func("f", "sqlite3_column_double", "pi") sqlite3_column_text = sq3.func("s", "sqlite3_column_text", "pi") +#const char *sqlite3_errmsg(sqlite3*); +sqlite3_errmsg = sq3.func("s", "sqlite3_errmsg", "p") + +# Too recent +##const char *sqlite3_errstr(int); +#sqlite3_errstr = sq3.func("s", "sqlite3_errstr", "i") +SQLITE_OK = 0 SQLITE_ERROR = 1 SQLITE_BUSY = 5 SQLITE_MISUSE = 21 @@ -37,6 +48,15 @@ SQLITE_BLOB = 4 SQLITE_NULL = 5 +class Error(Exception): + pass + + +def check_error(db, s): + if s != SQLITE_OK: + raise Error(s, sqlite3_errmsg(db)) + + class Connections: def __init__(self, h): @@ -45,43 +65,53 @@ class Connections: def cursor(self): return Cursor(self.h) + def close(self): + s = sqlite3_close(self.h) + check_error(self.h, s) + class Cursor: def __init__(self, h): self.h = h - self.s = None + self.stmnt = None def execute(self, sql): b = bytearray(4) - sqlite3_prepare(self.h, sql, -1, b, None) - self.s = int.from_bytes(b) - self.num_cols = sqlite3_column_count(self.s) - #print("num_cols", self.num_cols) + s = sqlite3_prepare(self.h, sql, -1, b, None) + check_error(self.h, s) + self.stmnt = int.from_bytes(b) + print("stmnt", self.stmnt) + self.num_cols = sqlite3_column_count(self.stmnt) + print("num_cols", self.num_cols) + + def close(self): + s = sqlite3_finalize(self.stmnt) + check_error(self.h, s) def make_row(self): res = [] for i in range(self.num_cols): - t = sqlite3_column_type(self.s, i) + t = sqlite3_column_type(self.stmnt, i) #print("type", t) if t == SQLITE_INTEGER: - res.append(sqlite3_column_int(self.s, i)) + res.append(sqlite3_column_int(self.stmnt, i)) elif t == SQLITE_FLOAT: - res.append(sqlite3_column_double(self.s, i)) + res.append(sqlite3_column_double(self.stmnt, i)) elif t == SQLITE_TEXT: - res.append(sqlite3_column_text(self.s, i)) + res.append(sqlite3_column_text(self.stmnt, i)) else: raise NotImplementedError return tuple(res) def fetchone(self): - res = sqlite3_step(self.s) + res = sqlite3_step(self.stmnt) #print("step:", res) if res == SQLITE_DONE: return None if res == SQLITE_ROW: return self.make_row() - assert False, res + check_error(self.h, res) def connect(fname):