[pypy-commit] pypy default: backout the sqlite-cffi merge, will redo it differently
fijal
noreply at buildbot.pypy.org
Wed Apr 3 19:37:52 CEST 2013
Author: Maciej Fijalkowski <fijall at gmail.com>
Branch:
Changeset: r62978:084972330ddd
Date: 2013-04-03 19:37 +0200
http://bitbucket.org/pypy/pypy/changeset/084972330ddd/
Log: backout the sqlite-cffi merge, will redo it differently
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -23,6 +23,9 @@
#
# Note: This software has been modified for use in PyPy.
+from ctypes import c_void_p, c_int, c_double, c_int64, c_char_p, c_char, cdll
+from ctypes import POINTER, byref, string_at, CFUNCTYPE, cast
+from ctypes import sizeof, c_ssize_t
from collections import OrderedDict
from functools import wraps
import datetime
@@ -41,266 +44,210 @@
else:
_BLOB_TYPE = buffer
-from cffi import FFI
-ffi = FFI()
+def load_library(names):
+ for name in names:
+ try:
+ return cdll.LoadLibrary(name)
+ except OSError:
+ pass
+ else:
+ raise ImportError("Could not load C-library, tried: %s" % (names,))
-ffi.cdef("""
-#define SQLITE_OK ...
-#define SQLITE_ERROR ...
-#define SQLITE_INTERNAL ...
-#define SQLITE_PERM ...
-#define SQLITE_ABORT ...
-#define SQLITE_BUSY ...
-#define SQLITE_LOCKED ...
-#define SQLITE_NOMEM ...
-#define SQLITE_READONLY ...
-#define SQLITE_INTERRUPT ...
-#define SQLITE_IOERR ...
-#define SQLITE_CORRUPT ...
-#define SQLITE_NOTFOUND ...
-#define SQLITE_FULL ...
-#define SQLITE_CANTOPEN ...
-#define SQLITE_PROTOCOL ...
-#define SQLITE_EMPTY ...
-#define SQLITE_SCHEMA ...
-#define SQLITE_TOOBIG ...
-#define SQLITE_CONSTRAINT ...
-#define SQLITE_MISMATCH ...
-#define SQLITE_MISUSE ...
-#define SQLITE_NOLFS ...
-#define SQLITE_AUTH ...
-#define SQLITE_FORMAT ...
-#define SQLITE_RANGE ...
-#define SQLITE_NOTADB ...
-#define SQLITE_ROW ...
-#define SQLITE_DONE ...
-#define SQLITE_INTEGER ...
-#define SQLITE_FLOAT ...
-#define SQLITE_BLOB ...
-#define SQLITE_NULL ...
-#define SQLITE_TEXT ...
-#define SQLITE3_TEXT ...
+_lib = load_library(
+ "sqlite3.dll libsqlite3.so.0 libsqlite3.so libsqlite3.dylib".split())
+del load_library
-#define SQLITE_TRANSIENT ...
-#define SQLITE_UTF8 ...
+##########################################
+# BEGIN Wrapped SQLite C API and constants
+##########################################
-#define SQLITE_DENY ...
-#define SQLITE_IGNORE ...
+_lib.SQLITE_OK = 0
+_lib.SQLITE_ERROR = 1
+_lib.SQLITE_INTERNAL = 2
+_lib.SQLITE_PERM = 3
+_lib.SQLITE_ABORT = 4
+_lib.SQLITE_BUSY = 5
+_lib.SQLITE_LOCKED = 6
+_lib.SQLITE_NOMEM = 7
+_lib.SQLITE_READONLY = 8
+_lib.SQLITE_INTERRUPT = 9
+_lib.SQLITE_IOERR = 10
+_lib.SQLITE_CORRUPT = 11
+_lib.SQLITE_NOTFOUND = 12
+_lib.SQLITE_FULL = 13
+_lib.SQLITE_CANTOPEN = 14
+_lib.SQLITE_PROTOCOL = 15
+_lib.SQLITE_EMPTY = 16
+_lib.SQLITE_SCHEMA = 17
+_lib.SQLITE_TOOBIG = 18
+_lib.SQLITE_CONSTRAINT = 19
+_lib.SQLITE_MISMATCH = 20
+_lib.SQLITE_MISUSE = 21
+_lib.SQLITE_NOLFS = 22
+_lib.SQLITE_AUTH = 23
+_lib.SQLITE_FORMAT = 24
+_lib.SQLITE_RANGE = 25
+_lib.SQLITE_NOTADB = 26
+_lib.SQLITE_ROW = 100
+_lib.SQLITE_DONE = 101
-#define SQLITE_CREATE_INDEX ...
-#define SQLITE_CREATE_TABLE ...
-#define SQLITE_CREATE_TEMP_INDEX ...
-#define SQLITE_CREATE_TEMP_TABLE ...
-#define SQLITE_CREATE_TEMP_TRIGGER ...
-#define SQLITE_CREATE_TEMP_VIEW ...
-#define SQLITE_CREATE_TRIGGER ...
-#define SQLITE_CREATE_VIEW ...
-#define SQLITE_DELETE ...
-#define SQLITE_DROP_INDEX ...
-#define SQLITE_DROP_TABLE ...
-#define SQLITE_DROP_TEMP_INDEX ...
-#define SQLITE_DROP_TEMP_TABLE ...
-#define SQLITE_DROP_TEMP_TRIGGER ...
-#define SQLITE_DROP_TEMP_VIEW ...
-#define SQLITE_DROP_TRIGGER ...
-#define SQLITE_DROP_VIEW ...
-#define SQLITE_INSERT ...
-#define SQLITE_PRAGMA ...
-#define SQLITE_READ ...
-#define SQLITE_SELECT ...
-#define SQLITE_TRANSACTION ...
-#define SQLITE_UPDATE ...
-#define SQLITE_ATTACH ...
-#define SQLITE_DETACH ...
-#define SQLITE_ALTER_TABLE ...
-#define SQLITE_REINDEX ...
-#define SQLITE_ANALYZE ...
-#define SQLITE_CREATE_VTABLE ...
-#define SQLITE_DROP_VTABLE ...
-#define SQLITE_FUNCTION ...
+_lib.SQLITE_INTEGER = 1
+_lib.SQLITE_FLOAT = 2
+_lib.SQLITE_TEXT = 3
+_lib.SQLITE_BLOB = 4
+_lib.SQLITE_NULL = 5
-const char *sqlite3_libversion(void);
+_lib.SQLITE_UTF8 = 1
-typedef ... sqlite3;
-typedef ... sqlite3_stmt;
-typedef ... sqlite3_context;
-typedef ... sqlite3_value;
-typedef int64_t sqlite3_int64;
-typedef uint64_t sqlite3_uint64;
+_lib.SQLITE_TRANSIENT = cast(-1, c_void_p)
-int sqlite3_open(
- const char *filename, /* Database filename (UTF-8) */
- sqlite3 **ppDb /* OUT: SQLite db handle */
-);
+SQLITE_OK = _lib.SQLITE_OK
-int sqlite3_close(sqlite3 *);
+SQLITE_DENY = 1
+SQLITE_IGNORE = 2
-int sqlite3_busy_timeout(sqlite3*, int ms);
-int sqlite3_prepare_v2(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
-);
-int sqlite3_finalize(sqlite3_stmt *pStmt);
-int sqlite3_column_count(sqlite3_stmt *pStmt);
-const char *sqlite3_column_name(sqlite3_stmt*, int N);
-int sqlite3_get_autocommit(sqlite3*);
-int sqlite3_reset(sqlite3_stmt *pStmt);
-int sqlite3_step(sqlite3_stmt*);
-int sqlite3_errcode(sqlite3 *db);
-const char *sqlite3_errmsg(sqlite3*);
-int sqlite3_changes(sqlite3*);
+SQLITE_CREATE_INDEX = 1
+SQLITE_CREATE_TABLE = 2
+SQLITE_CREATE_TEMP_INDEX = 3
+SQLITE_CREATE_TEMP_TABLE = 4
+SQLITE_CREATE_TEMP_TRIGGER = 5
+SQLITE_CREATE_TEMP_VIEW = 6
+SQLITE_CREATE_TRIGGER = 7
+SQLITE_CREATE_VIEW = 8
+SQLITE_DELETE = 9
+SQLITE_DROP_INDEX = 10
+SQLITE_DROP_TABLE = 11
+SQLITE_DROP_TEMP_INDEX = 12
+SQLITE_DROP_TEMP_TABLE = 13
+SQLITE_DROP_TEMP_TRIGGER = 14
+SQLITE_DROP_TEMP_VIEW = 15
+SQLITE_DROP_TRIGGER = 16
+SQLITE_DROP_VIEW = 17
+SQLITE_INSERT = 18
+SQLITE_PRAGMA = 19
+SQLITE_READ = 20
+SQLITE_SELECT = 21
+SQLITE_TRANSACTION = 22
+SQLITE_UPDATE = 23
+SQLITE_ATTACH = 24
+SQLITE_DETACH = 25
+SQLITE_ALTER_TABLE = 26
+SQLITE_REINDEX = 27
+SQLITE_ANALYZE = 28
-int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-int sqlite3_bind_double(sqlite3_stmt*, int, double);
-int sqlite3_bind_int(sqlite3_stmt*, int, int);
-int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-int sqlite3_bind_null(sqlite3_stmt*, int);
-int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
-int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
-int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
-int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+# SQLite C API
-const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-double sqlite3_column_double(sqlite3_stmt*, int iCol);
-int sqlite3_column_int(sqlite3_stmt*, int iCol);
-sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-int sqlite3_column_type(sqlite3_stmt*, int iCol);
-const char *sqlite3_column_decltype(sqlite3_stmt*,int);
+_lib.sqlite3_value_int.argtypes = [c_void_p]
+_lib.sqlite3_value_int.restype = c_int
-void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
-int sqlite3_create_collation(
- sqlite3*,
- const char *zName,
- int eTextRep,
- void*,
- int(*xCompare)(void*,int,const void*,int,const void*)
-);
-int sqlite3_set_authorizer(
- sqlite3*,
- int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
- void *pUserData
-);
-int sqlite3_create_function(
- sqlite3 *db,
- const char *zFunctionName,
- int nArg,
- int eTextRep,
- void *pApp,
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
- void (*xStep)(sqlite3_context*,int,sqlite3_value**),
- void (*xFinal)(sqlite3_context*)
-);
-void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+_lib.sqlite3_value_int64.argtypes = [c_void_p]
+_lib.sqlite3_value_int64.restype = c_int64
-sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
-int sqlite3_bind_parameter_count(sqlite3_stmt*);
-const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
-int sqlite3_total_changes(sqlite3*);
+_lib.sqlite3_value_blob.argtypes = [c_void_p]
+_lib.sqlite3_value_blob.restype = c_void_p
-int sqlite3_prepare(
- sqlite3 *db, /* Database handle */
- const char *zSql, /* SQL statement, UTF-8 encoded */
- int nByte, /* Maximum length of zSql in bytes. */
- sqlite3_stmt **ppStmt, /* OUT: Statement handle */
- const char **pzTail /* OUT: Pointer to unused portion of zSql */
-);
+_lib.sqlite3_value_bytes.argtypes = [c_void_p]
+_lib.sqlite3_value_bytes.restype = c_int
-void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
-void sqlite3_result_double(sqlite3_context*, double);
-void sqlite3_result_error(sqlite3_context*, const char*, int);
-void sqlite3_result_error16(sqlite3_context*, const void*, int);
-void sqlite3_result_error_toobig(sqlite3_context*);
-void sqlite3_result_error_nomem(sqlite3_context*);
-void sqlite3_result_error_code(sqlite3_context*, int);
-void sqlite3_result_int(sqlite3_context*, int);
-void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
-void sqlite3_result_null(sqlite3_context*);
-void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
-void sqlite3_result_text16le(sqlite3_context*,const void*, int,void(*)(void*));
-void sqlite3_result_text16be(sqlite3_context*,const void*, int,void(*)(void*));
-void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-void sqlite3_result_zeroblob(sqlite3_context*, int n);
+_lib.sqlite3_value_double.argtypes = [c_void_p]
+_lib.sqlite3_value_double.restype = c_double
-const void *sqlite3_value_blob(sqlite3_value*);
-int sqlite3_value_bytes(sqlite3_value*);
-int sqlite3_value_bytes16(sqlite3_value*);
-double sqlite3_value_double(sqlite3_value*);
-int sqlite3_value_int(sqlite3_value*);
-sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
-const unsigned char *sqlite3_value_text(sqlite3_value*);
-const void *sqlite3_value_text16(sqlite3_value*);
-const void *sqlite3_value_text16le(sqlite3_value*);
-const void *sqlite3_value_text16be(sqlite3_value*);
-int sqlite3_value_type(sqlite3_value*);
-int sqlite3_value_numeric_type(sqlite3_value*);
-""")
+_lib.sqlite3_value_text.argtypes = [c_void_p]
+_lib.sqlite3_value_text.restype = c_char_p
+_lib.sqlite3_value_type.argtypes = [c_void_p]
+_lib.sqlite3_value_type.restype = c_int
-def _has_load_extension():
- """Only available since 3.3.6"""
- unverified_ffi = FFI()
- unverified_ffi.cdef("""
- typedef ... sqlite3;
- int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
- """)
- unverified_lib = unverified_ffi.dlopen('sqlite3')
- return hasattr(unverified_lib, 'sqlite3_enable_load_extension')
+_lib.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int, c_void_p]
+_lib.sqlite3_bind_blob.restype = c_int
+_lib.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double]
+_lib.sqlite3_bind_double.restype = c_int
+_lib.sqlite3_bind_int.argtypes = [c_void_p, c_int, c_int]
+_lib.sqlite3_bind_int.restype = c_int
+_lib.sqlite3_bind_int64.argtypes = [c_void_p, c_int, c_int64]
+_lib.sqlite3_bind_int64.restype = c_int
+_lib.sqlite3_bind_null.argtypes = [c_void_p, c_int]
+_lib.sqlite3_bind_null.restype = c_int
+_lib.sqlite3_bind_parameter_count.argtypes = [c_void_p]
+_lib.sqlite3_bind_parameter_count.restype = c_int
+_lib.sqlite3_bind_parameter_index.argtypes = [c_void_p, c_char_p]
+_lib.sqlite3_bind_parameter_index.restype = c_int
+_lib.sqlite3_bind_parameter_name.argtypes = [c_void_p, c_int]
+_lib.sqlite3_bind_parameter_name.restype = c_char_p
+_lib.sqlite3_bind_text.argtypes = [c_void_p, c_int, c_char_p, c_int, c_void_p]
+_lib.sqlite3_bind_text.restype = c_int
+_lib.sqlite3_busy_timeout.argtypes = [c_void_p, c_int]
+_lib.sqlite3_busy_timeout.restype = c_int
+_lib.sqlite3_changes.argtypes = [c_void_p]
+_lib.sqlite3_changes.restype = c_int
+_lib.sqlite3_close.argtypes = [c_void_p]
+_lib.sqlite3_close.restype = c_int
+_lib.sqlite3_column_blob.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_blob.restype = c_void_p
+_lib.sqlite3_column_bytes.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_bytes.restype = c_int
+_lib.sqlite3_column_count.argtypes = [c_void_p]
+_lib.sqlite3_column_count.restype = c_int
+_lib.sqlite3_column_decltype.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_decltype.restype = c_char_p
+_lib.sqlite3_column_double.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_double.restype = c_double
+_lib.sqlite3_column_int64.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_int64.restype = c_int64
+_lib.sqlite3_column_name.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_name.restype = c_char_p
+_lib.sqlite3_column_text.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_text.restype = POINTER(c_char)
+_lib.sqlite3_column_type.argtypes = [c_void_p, c_int]
+_lib.sqlite3_column_type.restype = c_int
+_lib.sqlite3_complete.argtypes = [c_char_p]
+_lib.sqlite3_complete.restype = c_int
+_lib.sqlite3_errcode.restype = c_int
+_lib.sqlite3_errmsg.argtypes = [c_void_p]
+_lib.sqlite3_errmsg.restype = c_char_p
+_lib.sqlite3_finalize.argtypes = [c_void_p]
+_lib.sqlite3_finalize.restype = c_int
+_lib.sqlite3_get_autocommit.argtypes = [c_void_p]
+_lib.sqlite3_get_autocommit.restype = c_int
+_lib.sqlite3_last_insert_rowid.argtypes = [c_void_p]
+_lib.sqlite3_last_insert_rowid.restype = c_int64
+_lib.sqlite3_libversion.argtypes = []
+_lib.sqlite3_libversion.restype = c_char_p
+_lib.sqlite3_open.argtypes = [c_char_p, c_void_p]
+_lib.sqlite3_open.restype = c_int
+_lib.sqlite3_prepare.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)]
+_lib.sqlite3_prepare.restype = c_int
+_lib.sqlite3_prepare_v2.argtypes = [c_void_p, c_char_p, c_int, c_void_p, POINTER(c_char_p)]
+_lib.sqlite3_prepare_v2.restype = c_int
+_lib.sqlite3_step.argtypes = [c_void_p]
+_lib.sqlite3_step.restype = c_int
+_lib.sqlite3_reset.argtypes = [c_void_p]
+_lib.sqlite3_reset.restype = c_int
+_lib.sqlite3_total_changes.argtypes = [c_void_p]
+_lib.sqlite3_total_changes.restype = c_int
+_lib.sqlite3_result_blob.argtypes = [c_void_p, c_void_p, c_int, c_void_p]
+_lib.sqlite3_result_blob.restype = None
+_lib.sqlite3_result_int64.argtypes = [c_void_p, c_int64]
+_lib.sqlite3_result_int64.restype = None
+_lib.sqlite3_result_null.argtypes = [c_void_p]
+_lib.sqlite3_result_null.restype = None
+_lib.sqlite3_result_double.argtypes = [c_void_p, c_double]
+_lib.sqlite3_result_double.restype = None
+_lib.sqlite3_result_error.argtypes = [c_void_p, c_char_p, c_int]
+_lib.sqlite3_result_error.restype = None
+_lib.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p]
+_lib.sqlite3_result_text.restype = None
-if _has_load_extension():
- ffi.cdef("int sqlite3_enable_load_extension(sqlite3 *db, int onoff);")
+_HAS_LOAD_EXTENSION = hasattr(_lib, "sqlite3_enable_load_extension")
+if _HAS_LOAD_EXTENSION:
+ _lib.sqlite3_enable_load_extension.argtypes = [c_void_p, c_int]
+ _lib.sqlite3_enable_load_extension.restype = c_int
-lib = ffi.verify("""
-#include <sqlite3.h>
-""", libraries=['sqlite3'])
-
-exported_sqlite_symbols = [
- 'SQLITE_ALTER_TABLE',
- 'SQLITE_ANALYZE',
- 'SQLITE_ATTACH',
- 'SQLITE_CREATE_INDEX',
- 'SQLITE_CREATE_TABLE',
- 'SQLITE_CREATE_TEMP_INDEX',
- 'SQLITE_CREATE_TEMP_TABLE',
- 'SQLITE_CREATE_TEMP_TRIGGER',
- 'SQLITE_CREATE_TEMP_VIEW',
- 'SQLITE_CREATE_TRIGGER',
- 'SQLITE_CREATE_VIEW',
- 'SQLITE_DELETE',
- 'SQLITE_DENY',
- 'SQLITE_DETACH',
- 'SQLITE_DROP_INDEX',
- 'SQLITE_DROP_TABLE',
- 'SQLITE_DROP_TEMP_INDEX',
- 'SQLITE_DROP_TEMP_TABLE',
- 'SQLITE_DROP_TEMP_TRIGGER',
- 'SQLITE_DROP_TEMP_VIEW',
- 'SQLITE_DROP_TRIGGER',
- 'SQLITE_DROP_VIEW',
- 'SQLITE_IGNORE',
- 'SQLITE_INSERT',
- 'SQLITE_OK',
- 'SQLITE_PRAGMA',
- 'SQLITE_READ',
- 'SQLITE_REINDEX',
- 'SQLITE_SELECT',
- 'SQLITE_TRANSACTION',
- 'SQLITE_UPDATE',
-]
-
-for symbol in exported_sqlite_symbols:
- globals()[symbol] = getattr(lib, symbol)
-
-_SQLITE_TRANSIENT = ffi.cast('void *', lib.SQLITE_TRANSIENT)
-
+##########################################
+# END Wrapped SQLite C API and constants
+##########################################
# pysqlite version information
version = "2.6.0"
@@ -310,7 +257,7 @@
PARSE_DECLTYPES = 2
# SQLite version information
-sqlite_version = ffi.string(lib.sqlite3_libversion())
+sqlite_version = str(_lib.sqlite3_libversion().decode('ascii'))
class Error(StandardError):
@@ -387,36 +334,48 @@
if len(self.cache) > self.maxcount:
self.cache.popitem(0)
- if stat.in_use:
+ if stat._in_use:
stat = Statement(self.connection, sql)
- stat.set_row_factory(row_factory)
+ stat._row_factory = row_factory
return stat
class Connection(object):
- def __init__(self, database, timeout=5.0, detect_types=0,
- isolation_level="", check_same_thread=True, factory=None,
- cached_statements=100):
- db_star = ffi.new('sqlite3 **')
+ __initialized = False
+ _db = None
+
+ def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="",
+ check_same_thread=True, factory=None, cached_statements=100):
+ self.__initialized = True
+ self._db = c_void_p()
+
if isinstance(database, unicode):
database = database.encode('utf-8')
- if lib.sqlite3_open(database, db_star) != lib.SQLITE_OK:
+ if _lib.sqlite3_open(database, byref(self._db)) != _lib.SQLITE_OK:
raise OperationalError("Could not open database")
- self.db = db_star[0]
if timeout is not None:
timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds
- lib.sqlite3_busy_timeout(self.db, timeout)
+ _lib.sqlite3_busy_timeout(self._db, timeout)
+ self.row_factory = None
self.text_factory = _unicode_text_factory
- self.closed = False
- self.statements = []
- self.statement_counter = 0
- self.row_factory = None
- self._isolation_level = isolation_level
- self.detect_types = detect_types
- self.statement_cache = _StatementCache(self, cached_statements)
- self.cursors = []
+ self._detect_types = detect_types
+ self._in_transaction = False
+ self.isolation_level = isolation_level
+
+ self.__cursors = []
+ self.__cursors_counter = 0
+ self.__statements = []
+ self.__statements_counter = 0
+ self._statement_cache = _StatementCache(self, cached_statements)
+
+ self.__func_cache = {}
+ self.__aggregates = {}
+ self.__aggregate_instances = {}
+ self.__collations = {}
+ if check_same_thread:
+ self.__thread_ident = _thread_get_ident()
self.Error = Error
self.Warning = Warning
@@ -429,30 +388,25 @@
self.DataError = DataError
self.NotSupportedError = NotSupportedError
- self.func_cache = {}
- self._aggregates = {}
- self.aggregate_instances = {}
- self._collations = {}
- if check_same_thread:
- self.thread_ident = _thread_get_ident()
+ def __del__(self):
+ if self._db:
+ _lib.sqlite3_close(self._db)
def close(self):
self._check_thread()
- if self.closed:
- return
- for statement in self.statements:
- obj = statement()
- if obj is not None:
- obj.finalize()
- self.closed = True
- ret = lib.sqlite3_close(self.db)
- self._reset_cursors()
- if ret != lib.SQLITE_OK:
- raise self._get_exception(ret)
+ self.__do_all_statements(Statement._finalize, True)
+
+ if self._db:
+ ret = _lib.sqlite3_close(self._db)
+ if ret != _lib.SQLITE_OK:
+ raise self._get_exception(ret)
+ self._db = None
def _check_closed(self):
- if getattr(self, 'closed', True):
+ if not self.__initialized:
+ raise ProgrammingError("Base Connection.__init__ not called.")
+ if not self._db:
raise ProgrammingError("Cannot operate on a closed database.")
def _check_closed_wrap(func):
@@ -463,13 +417,16 @@
return wrapper
def _check_thread(self):
- if not hasattr(self, 'thread_ident'):
- return
- if self.thread_ident != _thread_get_ident():
+ try:
+ if self.__thread_ident == _thread_get_ident():
+ return
+ except AttributeError:
+ pass
+ else:
raise ProgrammingError(
"SQLite objects created in a thread can only be used in that "
"same thread. The object was created in thread id %d and this "
- "is thread id %d", self.thread_ident, _thread_get_ident())
+ "is thread id %d", self.__thread_ident, _thread_get_ident())
def _check_thread_wrap(func):
@wraps(func)
@@ -480,29 +437,29 @@
def _get_exception(self, error_code=None):
if error_code is None:
- error_code = lib.sqlite3_errcode(self.db)
- error_message = ffi.string(lib.sqlite3_errmsg(self.db))
+ error_code = _lib.sqlite3_errcode(self._db)
+ error_message = _lib.sqlite3_errmsg(self._db).decode('utf-8')
- if error_code == lib.SQLITE_OK:
- raise ValueError("error signalled but got lib.SQLITE_OK")
- elif error_code in (lib.SQLITE_INTERNAL, lib.SQLITE_NOTFOUND):
+ if error_code == _lib.SQLITE_OK:
+ raise ValueError("error signalled but got SQLITE_OK")
+ elif error_code in (_lib.SQLITE_INTERNAL, _lib.SQLITE_NOTFOUND):
exc = InternalError
- elif error_code == lib.SQLITE_NOMEM:
+ elif error_code == _lib.SQLITE_NOMEM:
exc = MemoryError
elif error_code in (
- lib.SQLITE_ERROR, lib.SQLITE_PERM, lib.SQLITE_ABORT,
- lib.SQLITE_BUSY, lib.SQLITE_LOCKED, lib.SQLITE_READONLY,
- lib.SQLITE_INTERRUPT, lib.SQLITE_IOERR, lib.SQLITE_FULL,
- lib.SQLITE_CANTOPEN, lib.SQLITE_PROTOCOL, lib.SQLITE_EMPTY,
- lib.SQLITE_SCHEMA):
+ _lib.SQLITE_ERROR, _lib.SQLITE_PERM, _lib.SQLITE_ABORT,
+ _lib.SQLITE_BUSY, _lib.SQLITE_LOCKED, _lib.SQLITE_READONLY,
+ _lib.SQLITE_INTERRUPT, _lib.SQLITE_IOERR, _lib.SQLITE_FULL,
+ _lib.SQLITE_CANTOPEN, _lib.SQLITE_PROTOCOL, _lib.SQLITE_EMPTY,
+ _lib.SQLITE_SCHEMA):
exc = OperationalError
- elif error_code == lib.SQLITE_CORRUPT:
+ elif error_code == _lib.SQLITE_CORRUPT:
exc = DatabaseError
- elif error_code == lib.SQLITE_TOOBIG:
+ elif error_code == _lib.SQLITE_TOOBIG:
exc = DataError
- elif error_code in (lib.SQLITE_CONSTRAINT, lib.SQLITE_MISMATCH):
+ elif error_code in (_lib.SQLITE_CONSTRAINT, _lib.SQLITE_MISMATCH):
exc = IntegrityError
- elif error_code == lib.SQLITE_MISUSE:
+ elif error_code == _lib.SQLITE_MISUSE:
exc = ProgrammingError
else:
exc = DatabaseError
@@ -510,26 +467,38 @@
exc.error_code = error_code
return exc
+ def _remember_cursor(self, cursor):
+ self.__cursors.append(weakref.ref(cursor))
+ self.__cursors_counter += 1
+ if self.__cursors_counter < 200:
+ return
+ self.__cursors_counter = 0
+ self.__cursors = [r for r in self.__cursors if r() is not None]
+
def _remember_statement(self, statement):
- self.statements.append(weakref.ref(statement))
- self.statement_counter += 1
+ self.__statements.append(weakref.ref(statement))
+ self.__statements_counter += 1
+ if self.__statements_counter < 200:
+ return
+ self.__statements_counter = 0
+ self.__statements = [r for r in self.__statements if r() is not None]
- if self.statement_counter % 100 == 0:
- self.statements = [ref for ref in self.statements
- if ref() is not None]
+ def __do_all_statements(self, action, reset_cursors):
+ for weakref in self.__statements:
+ statement = weakref()
+ if statement is not None:
+ action(statement)
- def _reset_cursors(self):
- for cursor_ref in self.cursors:
- cursor = cursor_ref()
- if cursor:
- cursor.reset = True
+ if reset_cursors:
+ for weakref in self.__cursors:
+ cursor = weakref()
+ if cursor is not None:
+ cursor._reset = True
@_check_thread_wrap
@_check_closed_wrap
def __call__(self, sql):
- if not isinstance(sql, basestring):
- raise Warning("SQL is of wrong type. Must be string or unicode.")
- return self.statement_cache.get(sql, self.row_factory)
+ return self._statement_cache.get(sql, self.row_factory)
def cursor(self, factory=None):
self._check_thread()
@@ -558,73 +527,60 @@
return _iterdump(self)
def _begin(self):
- self._check_closed()
- if self._isolation_level is None:
- return
- if not lib.sqlite3_get_autocommit(self.db):
- return
- sql = "BEGIN " + self._isolation_level
- statement_star = ffi.new('sqlite3_stmt **')
- next_char = ffi.new('char **')
- ret = lib.sqlite3_prepare_v2(self.db, sql, -1, statement_star,
- next_char)
+ statement = c_void_p()
+ ret = _lib.sqlite3_prepare_v2(self._db, self.__begin_statement, -1,
+ byref(statement), None)
try:
- if ret != lib.SQLITE_OK:
+ if ret != _lib.SQLITE_OK:
raise self._get_exception(ret)
- ret = lib.sqlite3_step(statement_star[0])
- if ret != lib.SQLITE_DONE:
+ ret = _lib.sqlite3_step(statement)
+ if ret != _lib.SQLITE_DONE:
raise self._get_exception(ret)
+ self._in_transaction = True
finally:
- lib.sqlite3_finalize(statement_star[0])
+ _lib.sqlite3_finalize(statement)
def commit(self):
self._check_thread()
self._check_closed()
- if lib.sqlite3_get_autocommit(self.db):
+ if not self._in_transaction:
return
- for statement in self.statements:
- obj = statement()
- if obj is not None:
- obj.reset()
+ self.__do_all_statements(Statement._reset, False)
- statement_star = ffi.new('sqlite3_stmt **')
- next_char = ffi.new('char **')
- ret = lib.sqlite3_prepare_v2(self.db, b"COMMIT", -1, statement_star,
- next_char)
+ statement = c_void_p()
+ ret = _lib.sqlite3_prepare_v2(self._db, b"COMMIT", -1,
+ byref(statement), None)
try:
- if ret != lib.SQLITE_OK:
+ if ret != _lib.SQLITE_OK:
raise self._get_exception(ret)
- ret = lib.sqlite3_step(statement_star[0])
- if ret != lib.SQLITE_DONE:
+ ret = _lib.sqlite3_step(statement)
+ if ret != _lib.SQLITE_DONE:
raise self._get_exception(ret)
+ self._in_transaction = False
finally:
- lib.sqlite3_finalize(statement_star[0])
+ _lib.sqlite3_finalize(statement)
def rollback(self):
self._check_thread()
self._check_closed()
- if lib.sqlite3_get_autocommit(self.db):
+ if not self._in_transaction:
return
- for statement in self.statements:
- obj = statement()
- if obj is not None:
- obj.reset()
+ self.__do_all_statements(Statement._reset, True)
- statement_star = ffi.new('sqlite3_stmt **')
- next_char = ffi.new('char **')
- ret = lib.sqlite3_prepare_v2(self.db, b"ROLLBACK", -1, statement_star,
- next_char)
+ statement = c_void_p()
+ ret = _lib.sqlite3_prepare_v2(self._db, b"ROLLBACK", -1,
+ byref(statement), None)
try:
- if ret != lib.SQLITE_OK:
+ if ret != _lib.SQLITE_OK:
raise self._get_exception(ret)
- ret = lib.sqlite3_step(statement_star[0])
- if ret != lib.SQLITE_DONE:
+ ret = _lib.sqlite3_step(statement)
+ if ret != _lib.SQLITE_DONE:
raise self._get_exception(ret)
+ self._in_transaction = False
finally:
- lib.sqlite3_finalize(statement_star[0])
- self._reset_cursors()
+ _lib.sqlite3_finalize(statement)
def __enter__(self):
return self
@@ -639,29 +595,34 @@
@_check_closed_wrap
def create_function(self, name, num_args, callback):
try:
- closure = self.func_cache[callback]
+ c_closure, _ = self.__func_cache[callback]
except KeyError:
- @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)")
def closure(context, nargs, c_params):
_function_callback(callback, context, nargs, c_params)
- self.func_cache[callback] = closure
- ret = lib.sqlite3_create_function(self.db, name, num_args,
- lib.SQLITE_UTF8, ffi.NULL,
- closure, ffi.NULL, ffi.NULL)
- if ret != lib.SQLITE_OK:
+ c_closure = _FUNC(closure)
+ self.__func_cache[callback] = c_closure, closure
+
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ ret = _lib.sqlite3_create_function(self._db, name, num_args,
+ _lib.SQLITE_UTF8, None,
+ c_closure,
+ cast(None, _STEP),
+ cast(None, _FINAL))
+ if ret != _lib.SQLITE_OK:
raise self.OperationalError("Error creating function")
@_check_thread_wrap
@_check_closed_wrap
def create_aggregate(self, name, num_args, cls):
try:
- step_callback, final_callback = self._aggregates[cls]
+ c_step_callback, c_final_callback, _, _ = self.__aggregates[cls]
except KeyError:
- @ffi.callback("void(sqlite3_context*, int, sqlite3_value**)")
def step_callback(context, argc, c_params):
- res = lib.sqlite3_aggregate_context(context,
- ffi.sizeof("size_t"))
- aggregate_ptr = ffi.cast("size_t[1]", res)
+ aggregate_ptr = cast(
+ _lib.sqlite3_aggregate_context(
+ context, sizeof(c_ssize_t)),
+ POINTER(c_ssize_t))
if not aggregate_ptr[0]:
try:
@@ -669,13 +630,13 @@
except Exception:
msg = (b"user-defined aggregate's '__init__' "
b"method raised error")
- lib.sqlite3_result_error(context, msg, len(msg))
+ _lib.sqlite3_result_error(context, msg, len(msg))
return
aggregate_id = id(aggregate)
- self.aggregate_instances[aggregate_id] = aggregate
+ self.__aggregate_instances[aggregate_id] = aggregate
aggregate_ptr[0] = aggregate_id
else:
- aggregate = self.aggregate_instances[aggregate_ptr[0]]
+ aggregate = self.__aggregate_instances[aggregate_ptr[0]]
params = _convert_params(context, argc, c_params)
try:
@@ -683,33 +644,41 @@
except Exception:
msg = (b"user-defined aggregate's 'step' "
b"method raised error")
- lib.sqlite3_result_error(context, msg, len(msg))
+ _lib.sqlite3_result_error(context, msg, len(msg))
- @ffi.callback("void(sqlite3_context*)")
def final_callback(context):
- res = lib.sqlite3_aggregate_context(context,
- ffi.sizeof("size_t"))
- aggregate_ptr = ffi.cast("size_t[1]", res)
+ aggregate_ptr = cast(
+ _lib.sqlite3_aggregate_context(
+ context, sizeof(c_ssize_t)),
+ POINTER(c_ssize_t))
if aggregate_ptr[0]:
- aggregate = self.aggregate_instances[aggregate_ptr[0]]
+ aggregate = self.__aggregate_instances[aggregate_ptr[0]]
try:
val = aggregate.finalize()
except Exception:
msg = (b"user-defined aggregate's 'finalize' "
b"method raised error")
- lib.sqlite3_result_error(context, msg, len(msg))
+ _lib.sqlite3_result_error(context, msg, len(msg))
else:
_convert_result(context, val)
finally:
- del self.aggregate_instances[aggregate_ptr[0]]
+ del self.__aggregate_instances[aggregate_ptr[0]]
- self._aggregates[cls] = step_callback, final_callback
+ c_step_callback = _STEP(step_callback)
+ c_final_callback = _FINAL(final_callback)
- ret = lib.sqlite3_create_function(self.db, name, num_args,
- lib.SQLITE_UTF8, ffi.NULL, ffi.NULL,
- step_callback, final_callback)
- if ret != lib.SQLITE_OK:
+ self.__aggregates[cls] = (c_step_callback, c_final_callback,
+ step_callback, final_callback)
+
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ ret = _lib.sqlite3_create_function(self._db, name, num_args,
+ _lib.SQLITE_UTF8, None,
+ cast(None, _FUNC),
+ c_step_callback,
+ c_final_callback)
+ if ret != _lib.SQLITE_OK:
raise self._get_exception(ret)
@_check_thread_wrap
@@ -720,55 +689,60 @@
raise ProgrammingError("invalid character in collation name")
if callback is None:
- del self._collations[name]
- collation_callback = ffi.NULL
+ del self.__collations[name]
+ c_collation_callback = cast(None, _COLLATION)
else:
if not callable(callback):
raise TypeError("parameter must be callable")
- @ffi.callback("int(void*, int, const void*, int, const void*)")
def collation_callback(context, len1, str1, len2, str2):
- text1 = ffi.buffer(str1, len1)[:]
- text2 = ffi.buffer(str2, len2)[:]
+ text1 = string_at(str1, len1).decode('utf-8')
+ text2 = string_at(str2, len2).decode('utf-8')
return callback(text1, text2)
- self._collations[name] = collation_callback
+ c_collation_callback = _COLLATION(collation_callback)
+ self.__collations[name] = c_collation_callback
- ret = lib.sqlite3_create_collation(self.db, name, lib.SQLITE_UTF8,
- ffi.NULL, collation_callback)
- if ret != lib.SQLITE_OK:
+ if isinstance(name, unicode):
+ name = name.encode('utf-8')
+ ret = _lib.sqlite3_create_collation(self._db, name,
+ _lib.SQLITE_UTF8,
+ None,
+ c_collation_callback)
+ if ret != _lib.SQLITE_OK:
raise self._get_exception(ret)
@_check_thread_wrap
@_check_closed_wrap
def set_authorizer(self, callback):
try:
- authorizer = self.func_cache[callback]
+ c_authorizer, _ = self.__func_cache[callback]
except KeyError:
- @ffi.callback("int(void*, int, const char*, const char*, "
- "const char*, const char*)")
def authorizer(userdata, action, arg1, arg2, dbname, source):
try:
return int(callback(action, arg1, arg2, dbname, source))
except Exception:
- return lib.SQLITE_DENY
- self.func_cache[callback] = authorizer
+ return SQLITE_DENY
+ c_authorizer = _AUTHORIZER(authorizer)
- ret = lib.sqlite3_set_authorizer(self.db, authorizer, ffi.NULL)
- if ret != lib.SQLITE_OK:
+ self.__func_cache[callback] = c_authorizer, authorizer
+
+ ret = _lib.sqlite3_set_authorizer(self._db,
+ c_authorizer,
+ None)
+ if ret != _lib.SQLITE_OK:
raise self._get_exception(ret)
@_check_thread_wrap
@_check_closed_wrap
def set_progress_handler(self, callable, nsteps):
if callable is None:
- progress_handler = ffi.NULL
+ c_progress_handler = cast(None, _PROGRESS)
else:
try:
- progress_handler = self.func_cache[callable]
+ c_progress_handler, _ = self.__func_cache[callable]
except KeyError:
- @ffi.callback("int(void*)")
def progress_handler(userdata):
try:
ret = callable()
@@ -776,14 +750,23 @@
except Exception:
# abort query if error occurred
return 1
+ c_progress_handler = _PROGRESS(progress_handler)
- self.func_cache[callable] = progress_handler
- lib.sqlite3_progress_handler(self.db, nsteps, progress_handler,
- ffi.NULL)
+ self.__func_cache[callable] = c_progress_handler, progress_handler
+ ret = _lib.sqlite3_progress_handler(self._db, nsteps,
+ c_progress_handler,
+ None)
+ if ret != _lib.SQLITE_OK:
+ raise self._get_exception(ret)
+
+ if sys.version_info[0] >= 3:
+ def __get_in_transaction(self):
+ return self._in_transaction
+ in_transaction = property(__get_in_transaction)
def __get_total_changes(self):
self._check_closed()
- return lib.sqlite3_total_changes(self.db)
+ return _lib.sqlite3_total_changes(self._db)
total_changes = property(__get_total_changes)
def __get_isolation_level(self):
@@ -792,193 +775,190 @@
def __set_isolation_level(self, val):
if val is None:
self.commit()
- if isinstance(val, unicode):
- val = str(val)
+ else:
+ self.__begin_statement = str("BEGIN " + val).encode('utf-8')
self._isolation_level = val
isolation_level = property(__get_isolation_level, __set_isolation_level)
- if hasattr(lib, 'sqlite3_enable_load_extension'):
+ if _HAS_LOAD_EXTENSION:
@_check_thread_wrap
@_check_closed_wrap
def enable_load_extension(self, enabled):
- rc = lib.sqlite3_enable_load_extension(self.db, int(enabled))
- if rc != lib.SQLITE_OK:
+ rc = _lib.sqlite3_enable_load_extension(self._db, int(enabled))
+ if rc != _lib.SQLITE_OK:
raise OperationalError("Error enabling load extension")
-DML, DQL, DDL = range(3)
+class Cursor(object):
+ __initialized = False
+ __statement = None
-
-class CursorLock(object):
- def __init__(self, cursor):
- self.cursor = cursor
-
- def __enter__(self):
- if self.cursor.locked:
- raise ProgrammingError("Recursive use of cursors not allowed.")
- self.cursor.locked = True
-
- def __exit__(self, *args):
- self.cursor.locked = False
-
-
-class Cursor(object):
def __init__(self, con):
if not isinstance(con, Connection):
raise TypeError
- con._check_thread()
- con._check_closed()
- con.cursors.append(weakref.ref(self))
- self.connection = con
- self._description = None
+ self.__connection = con
+
self.arraysize = 1
self.row_factory = None
- self.rowcount = -1
- self.statement = None
- self.reset = False
- self.locked = False
+ self._reset = False
+ self.__locked = False
+ self.__closed = False
+ self.__description = None
+ self.__rowcount = -1
- def _check_closed(self):
- if not getattr(self, 'connection', None):
+ con._check_thread()
+ con._remember_cursor(self)
+
+ self.__initialized = True
+
+ def __del__(self):
+ if self.__statement:
+ self.__statement._reset()
+
+ def close(self):
+ self.__connection._check_thread()
+ self.__connection._check_closed()
+ if self.__statement:
+ self.__statement._reset()
+ self.__statement = None
+ self.__closed = True
+
+ def __check_cursor(self):
+ if not self.__initialized:
+ raise ProgrammingError("Base Cursor.__init__ not called.")
+ if self.__closed:
raise ProgrammingError("Cannot operate on a closed cursor.")
- self.connection._check_thread()
- self.connection._check_closed()
+ if self.__locked:
+ raise ProgrammingError("Recursive use of cursors not allowed.")
+ self.__connection._check_thread()
+ self.__connection._check_closed()
- def _check_and_lock(self):
- self._check_closed()
- return CursorLock(self)
+ def __check_cursor_wrap(func):
+ @wraps(func)
+ def wrapper(self, *args, **kwargs):
+ self.__check_cursor()
+ return func(self, *args, **kwargs)
+ return wrapper
- def execute(self, sql, params=None):
- if type(sql) is unicode:
- sql = sql.encode("utf-8")
-
- with self._check_and_lock():
- self._description = None
- self.reset = False
- self.statement = self.connection.statement_cache.get(
+ def __execute(self, multiple, sql, many_params):
+ self.__locked = True
+ try:
+ self._reset = False
+ if not isinstance(sql, basestring):
+ raise ValueError("operation parameter must be str or unicode")
+ self.__description = None
+ self.__rowcount = -1
+ self.__statement = self.__connection._statement_cache.get(
sql, self.row_factory)
- if self.connection._isolation_level is not None:
- if self.statement.kind == DDL:
- self.connection.commit()
- elif self.statement.kind == DML:
- self.connection._begin()
+ if self.__connection._isolation_level is not None:
+ if self.__statement._kind == Statement._DDL:
+ if self.__connection._in_transaction:
+ self.__connection.commit()
+ elif self.__statement._kind == Statement._DML:
+ if not self.__connection._in_transaction:
+ self.__connection._begin()
- self.statement.set_params(params)
+ if multiple and self.__statement._kind != Statement._DML:
+ raise ProgrammingError("executemany is only for DML statements")
- # Actually execute the SQL statement
- ret = lib.sqlite3_step(self.statement.statement)
- if ret not in (lib.SQLITE_DONE, lib.SQLITE_ROW):
- self.statement.reset()
- raise self.connection._get_exception(ret)
+ for params in many_params:
+ self.__statement._set_params(params)
- if self.statement.kind == DML:
- self.statement.reset()
+ # Actually execute the SQL statement
+ ret = _lib.sqlite3_step(self.__statement._statement)
+ if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW):
+ self.__statement._reset()
+ self.__connection._in_transaction = \
+ not _lib.sqlite3_get_autocommit(self.__connection._db)
+ raise self.__connection._get_exception(ret)
- if self.statement.kind == DQL and ret == lib.SQLITE_ROW:
- self.statement._build_row_cast_map()
- self.statement._readahead(self)
- else:
- self.statement.item = None
- self.statement.exhausted = True
+ if self.__statement._kind == Statement._DML:
+ self.__statement._reset()
- self.rowcount = -1
- if self.statement.kind == DML:
- self.rowcount = lib.sqlite3_changes(self.connection.db)
+ if self.__statement._kind == Statement._DQL and ret == _lib.SQLITE_ROW:
+ self.__statement._build_row_cast_map()
+ self.__statement._readahead(self)
+ if self.__statement._kind == Statement._DML:
+ if self.__rowcount == -1:
+ self.__rowcount = 0
+ self.__rowcount += _lib.sqlite3_changes(self.__connection._db)
+ finally:
+ self.__locked = False
return self
+ @__check_cursor_wrap
+ def execute(self, sql, params=[]):
+ return self.__execute(False, sql, [params])
+
+ @__check_cursor_wrap
def executemany(self, sql, many_params):
- if type(sql) is unicode:
- sql = sql.encode("utf-8")
-
- with self._check_and_lock():
- self._description = None
- self.reset = False
- self.statement = self.connection.statement_cache.get(
- sql, self.row_factory)
-
- if self.statement.kind == DML:
- self.connection._begin()
- else:
- raise ProgrammingError(
- "executemany is only for DML statements")
-
- self.rowcount = 0
- for params in many_params:
- self.statement.set_params(params)
- ret = lib.sqlite3_step(self.statement.statement)
- if ret != lib.SQLITE_DONE:
- raise self.connection._get_exception(ret)
- self.rowcount += lib.sqlite3_changes(self.connection.db)
-
- return self
+ return self.__execute(True, sql, many_params)
def executescript(self, sql):
- self._description = None
- self.reset = False
- if type(sql) is unicode:
- sql = sql.encode("utf-8")
- self._check_closed()
- statement_star = ffi.new('sqlite3_stmt **')
- tail = ffi.new('char **')
+ self.__check_cursor()
+ self._reset = False
+ if isinstance(sql, unicode):
+ sql = sql.encode('utf-8')
+ elif not isinstance(sql, str):
+ raise ValueError("script argument must be unicode or string.")
+ sql = c_char_p(sql)
+ statement = c_void_p()
- self.connection.commit()
+ self.__connection.commit()
while True:
- rc = lib.sqlite3_prepare(self.connection.db, sql, -1,
- statement_star, tail)
- sql = ffi.string(tail[0])
- if rc != lib.SQLITE_OK:
- raise self.connection._get_exception(rc)
+ rc = _lib.sqlite3_prepare(self.__connection._db, sql, -1,
+ byref(statement), byref(sql))
+ if rc != _lib.SQLITE_OK:
+ raise self.__connection._get_exception(rc)
- rc = lib.SQLITE_ROW
- while rc == lib.SQLITE_ROW:
- if not statement_star[0]:
- rc = lib.SQLITE_OK
+ rc = _lib.SQLITE_ROW
+ while rc == _lib.SQLITE_ROW:
+ if not statement:
+ rc = _lib.SQLITE_OK
else:
- rc = lib.sqlite3_step(statement_star[0])
+ rc = _lib.sqlite3_step(statement)
- if rc != lib.SQLITE_DONE:
- lib.sqlite3_finalize(statement_star[0])
- if rc == lib.SQLITE_OK:
- return self
+ if rc != _lib.SQLITE_DONE:
+ _lib.sqlite3_finalize(statement)
+ if rc == _lib.SQLITE_OK:
+ break
else:
- raise self.connection._get_exception(rc)
- rc = lib.sqlite3_finalize(statement_star[0])
- if rc != lib.SQLITE_OK:
- raise self.connection._get_exception(rc)
+ raise self.__connection._get_exception(rc)
- if not sql:
+ rc = _lib.sqlite3_finalize(statement)
+ if rc != _lib.SQLITE_OK:
+ raise self.__connection._get_exception(rc)
+
+ if not sql.value:
break
return self
+ def __check_reset(self):
+ if self._reset:
+ raise self.__connection.InterfaceError(
+ "Cursor needed to be reset because of commit/rollback "
+ "and can no longer be fetched from.")
+
def __iter__(self):
- return iter(self.fetchone, None)
+ return self
- def _check_reset(self):
- if self.reset:
- raise self.connection.InterfaceError(
- "Cursor needed to be reset because of commit/rollback and can "
- "no longer be fetched from.")
+ def __next__(self):
+ self.__check_cursor()
+ self.__check_reset()
+ if not self.__statement:
+ raise StopIteration
+ return self.__statement._next(self)
- # do all statements
+ if sys.version_info[0] < 3:
+ next = __next__
+ del __next__
+
def fetchone(self):
- self._check_closed()
- self._check_reset()
-
- if self.statement is None:
- return None
-
- try:
- return self.statement.next(self)
- except StopIteration:
- return None
+ return next(self, None)
def fetchmany(self, size=None):
- self._check_closed()
- self._check_reset()
- if self.statement is None:
- return []
if size is None:
size = self.arraysize
lst = []
@@ -989,29 +969,25 @@
return lst
def fetchall(self):
- self._check_closed()
- self._check_reset()
- if self.statement is None:
- return []
return list(self)
- def _getdescription(self):
- if self._description is None:
- self._description = self.statement._get_description()
- return self._description
+ def __get_connection(self):
+ return self.__connection
+ connection = property(__get_connection)
- def _getlastrowid(self):
- return lib.sqlite3_last_insert_rowid(self.connection.db)
+ def __get_rowcount(self):
+ return self.__rowcount
+ rowcount = property(__get_rowcount)
- def close(self):
- if not self.connection:
- return
- self._check_closed()
- if self.statement:
- self.statement.reset()
- self.statement = None
- self.connection.cursors.remove(weakref.ref(self))
- self.connection = None
+ def __get_description(self):
+ if self.__description is None:
+ self.__description = self.__statement._get_description()
+ return self.__description
+ description = property(__get_description)
+
+ def __get_lastrowid(self):
+ return _lib.sqlite3_last_insert_rowid(self.__connection._db)
+ lastrowid = property(__get_lastrowid)
def setinputsizes(self, *args):
pass
@@ -1019,92 +995,71 @@
def setoutputsize(self, *args):
pass
- description = property(_getdescription)
- lastrowid = property(_getlastrowid)
-
class Statement(object):
+ _DML, _DQL, _DDL = range(3)
+
+ _statement = None
+
def __init__(self, connection, sql):
- self.statement = ffi.NULL
- if not isinstance(sql, str):
- raise ValueError("sql must be a string")
- self.con = connection
- self.sql = sql # DEBUG ONLY
+ self.__con = connection
+ self.__con._remember_statement(self)
+
+ if not isinstance(sql, basestring):
+ raise Warning("SQL is of wrong type. Must be string or unicode.")
first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
- self.kind = DML
+ self._kind = Statement._DML
elif first_word in ("SELECT", "PRAGMA"):
- self.kind = DQL
+ self._kind = Statement._DQL
else:
- self.kind = DDL
- self.exhausted = False
- self.in_use = False
- #
- # set by set_row_factory
- self.row_factory = None
+ self._kind = Statement._DDL
- statement_star = ffi.new('sqlite3_stmt **')
- next_char = ffi.new('char **')
- ret = lib.sqlite3_prepare_v2(self.con.db, sql, -1,
- statement_star, next_char)
- self.statement = statement_star[0]
- if ret == lib.SQLITE_OK and not self.statement:
- # an empty statement, we work around that as it's the least trouble
- ret = lib.sqlite3_prepare_v2(self.con.db, "select 42", -1,
- statement_star, next_char)
- self.statement = statement_star[0]
- self.kind = DQL
+ self._in_use = False
+ self._row_factory = None
- if ret != lib.SQLITE_OK:
- raise self.con._get_exception(ret)
- self.con._remember_statement(self)
- if _check_remaining_sql(ffi.string(next_char[0])):
- raise Warning("One and only one statement required: %r" % (
- next_char[0],))
- # sql_char should remain alive until here
+ if isinstance(sql, unicode):
+ sql = sql.encode('utf-8')
+ sql = c_char_p(sql)
+ self._statement = c_void_p()
- self._build_row_cast_map()
+ ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1,
+ byref(self._statement), byref(sql))
+ if ret == _lib.SQLITE_OK and self._statement.value is None:
+ # an empty statement, work around that, as it's the least trouble
+ sql = c_char_p(b"select 42")
+ ret = _lib.sqlite3_prepare_v2(self.__con._db, sql, -1,
+ byref(self._statement), byref(sql))
+ self._kind = Statement._DQL
+ if ret != _lib.SQLITE_OK:
+ raise self.__con._get_exception(ret)
- def set_row_factory(self, row_factory):
- self.row_factory = row_factory
+ sql = sql.value.decode('utf-8')
+ if _check_remaining_sql(sql):
+ raise Warning("You can only execute one statement at a time.")
- def _build_row_cast_map(self):
- self.row_cast_map = []
- for i in xrange(lib.sqlite3_column_count(self.statement)):
- converter = None
+ def __del__(self):
+ if self._statement:
+ _lib.sqlite3_finalize(self._statement)
- if self.con.detect_types & PARSE_COLNAMES:
- colname = lib.sqlite3_column_name(self.statement, i)
- if colname != ffi.NULL:
- colname = ffi.string(colname)
- type_start = -1
- key = None
- for pos in range(len(colname)):
- if colname[pos] == '[':
- type_start = pos + 1
- elif colname[pos] == ']' and type_start != -1:
- key = colname[type_start:pos]
- converter = converters[key.upper()]
+ def _finalize(self):
+ if self._statement:
+ _lib.sqlite3_finalize(self._statement)
+ self._statement = None
+ self._in_use = False
- if converter is None and self.con.detect_types & PARSE_DECLTYPES:
- decltype = lib.sqlite3_column_decltype(self.statement, i)
- if decltype is not ffi.NULL:
- # if multiple words, use first,
- # eg. "INTEGER NOT NULL" => "INTEGER"
- decltype = ffi.string(decltype).split()[0]
- if '(' in decltype:
- decltype = decltype[:decltype.index('(')]
- converter = converters.get(decltype.upper(), None)
-
- self.row_cast_map.append(converter)
+ def _reset(self):
+ if self._in_use and self._statement:
+ _lib.sqlite3_reset(self._statement)
+ self._in_use = False
if sys.version_info[0] < 3:
def __check_decodable(self, param):
- if self.con.text_factory in (unicode, OptimizedUnicode,
- _unicode_text_factory):
+ if self.__con.text_factory in (unicode, OptimizedUnicode,
+ _unicode_text_factory):
for c in param:
if ord(c) & 0x80 != 0:
- raise self.con.ProgrammingError(
+ raise self.__con.ProgrammingError(
"You must not use 8-bit bytestrings unless "
"you use a text_factory that can interpret "
"8-bit bytestrings (like text_factory = str). "
@@ -1119,149 +1074,171 @@
param = adapt(param)
if param is None:
- lib.sqlite3_bind_null(self.statement, idx)
+ rc = _lib.sqlite3_bind_null(self._statement, idx)
elif isinstance(param, (bool, int, long)):
if -2147483648 <= param <= 2147483647:
- lib.sqlite3_bind_int(self.statement, idx, param)
+ rc = _lib.sqlite3_bind_int(self._statement, idx, param)
else:
- lib.sqlite3_bind_int64(self.statement, idx, param)
+ rc = _lib.sqlite3_bind_int64(self._statement, idx, param)
elif isinstance(param, float):
- lib.sqlite3_bind_double(self.statement, idx, param)
+ rc = _lib.sqlite3_bind_double(self._statement, idx, param)
elif isinstance(param, unicode):
param = param.encode("utf-8")
- lib.sqlite3_bind_text(self.statement, idx, param, len(param),
- _SQLITE_TRANSIENT)
+ rc = _lib.sqlite3_bind_text(self._statement, idx, param,
+ len(param), _lib.SQLITE_TRANSIENT)
elif isinstance(param, str):
self.__check_decodable(param)
- lib.sqlite3_bind_text(self.statement, idx, param, len(param),
- _SQLITE_TRANSIENT)
+ rc = _lib.sqlite3_bind_text(self._statement, idx, param,
+ len(param), _lib.SQLITE_TRANSIENT)
elif isinstance(param, (buffer, bytes)):
- lib.sqlite3_bind_blob(self.statement, idx, str(param), len(param),
- _SQLITE_TRANSIENT)
+ param = bytes(param)
+ rc = _lib.sqlite3_bind_blob(self._statement, idx, param,
+ len(param), _lib.SQLITE_TRANSIENT)
else:
- raise InterfaceError(
- "parameter type %s is not supported" % str(type(param)))
+ rc = -1
+ return rc
- def set_params(self, params):
- ret = lib.sqlite3_reset(self.statement)
- if ret != lib.SQLITE_OK:
- raise self.con._get_exception(ret)
- self.mark_dirty()
+ def _set_params(self, params):
+ self._in_use = True
- if params is None:
- if lib.sqlite3_bind_parameter_count(self.statement) != 0:
- raise ProgrammingError("wrong number of arguments")
- return
-
- params_type = None
- if isinstance(params, dict):
- params_type = dict
- else:
- params_type = list
-
- if params_type == list:
- if len(params) != lib.sqlite3_bind_parameter_count(self.statement):
- raise ProgrammingError("wrong number of arguments")
-
- for i in range(len(params)):
- self.__set_param(i + 1, params[i])
- else:
- param_count = lib.sqlite3_bind_parameter_count(self.statement)
- for idx in range(1, param_count + 1):
- param_name = lib.sqlite3_bind_parameter_name(self.statement,
- idx)
- if param_name == ffi.NULL:
- raise ProgrammingError("need named parameters")
- param_name = ffi.string(param_name)[1:]
+ num_params_needed = _lib.sqlite3_bind_parameter_count(self._statement)
+ if isinstance(params, (tuple, list)) or \
+ not isinstance(params, dict) and \
+ hasattr(params, '__getitem__'):
+ try:
+ num_params = len(params)
+ except TypeError:
+ num_params = -1
+ if num_params != num_params_needed:
+ raise ProgrammingError("Incorrect number of bindings supplied. "
+ "The current statement uses %d, and "
+ "there are %d supplied." %
+ (num_params_needed, num_params))
+ for i in range(num_params):
+ rc = self.__set_param(i + 1, params[i])
+ if rc != _lib.SQLITE_OK:
+ raise InterfaceError("Error binding parameter %d - "
+ "probably unsupported type." % i)
+ elif isinstance(params, dict):
+ for i in range(1, num_params_needed + 1):
+ param_name = _lib.sqlite3_bind_parameter_name(self._statement, i)
+ if param_name is None:
+ raise ProgrammingError("Binding %d has no name, but you "
+ "supplied a dictionary (which has "
+ "only names)." % i)
+ param_name = param_name.decode('utf-8')[1:]
try:
param = params[param_name]
except KeyError:
- raise ProgrammingError("missing parameter '%s'" % param)
- self.__set_param(idx, param)
+ raise ProgrammingError("You did not supply a value for "
+ "binding %d." % i)
+ rc = self.__set_param(i, param)
+ if rc != _lib.SQLITE_OK:
+ raise InterfaceError("Error binding parameter :%s - "
+ "probably unsupported type." %
+ param_name)
+ else:
+ raise ValueError("parameters are of unsupported type")
- def next(self, cursor):
- self.con._check_closed()
- self.con._check_thread()
- if self.exhausted:
- raise StopIteration
- item = self.item
+ def _build_row_cast_map(self):
+ if not self.__con._detect_types:
+ return
+ self.__row_cast_map = []
+ for i in xrange(_lib.sqlite3_column_count(self._statement)):
+ converter = None
- ret = lib.sqlite3_step(self.statement)
- if ret == lib.SQLITE_DONE:
- self.exhausted = True
- self.item = None
- elif ret != lib.SQLITE_ROW:
- exc = self.con._get_exception(ret)
- lib.sqlite3_reset(self.statement)
- raise exc
+ if self.__con._detect_types & PARSE_COLNAMES:
+ colname = _lib.sqlite3_column_name(self._statement, i)
+ if colname is not None:
+ colname = colname.decode('utf-8')
+ type_start = -1
+ key = None
+ for pos in range(len(colname)):
+ if colname[pos] == '[':
+ type_start = pos + 1
+ elif colname[pos] == ']' and type_start != -1:
+ key = colname[type_start:pos]
+ converter = converters[key.upper()]
- self._readahead(cursor)
- return item
+ if converter is None and self.__con._detect_types & PARSE_DECLTYPES:
+ decltype = _lib.sqlite3_column_decltype(self._statement, i)
+ if decltype is not None:
+ decltype = decltype.decode('utf-8')
+ # if multiple words, use first, eg.
+ # "INTEGER NOT NULL" => "INTEGER"
+ decltype = decltype.split()[0]
+ if '(' in decltype:
+ decltype = decltype[:decltype.index('(')]
+ converter = converters.get(decltype.upper(), None)
+
+ self.__row_cast_map.append(converter)
def _readahead(self, cursor):
- self.column_count = lib.sqlite3_column_count(self.statement)
row = []
- for i in xrange(self.column_count):
- typ = lib.sqlite3_column_type(self.statement, i)
+ num_cols = _lib.sqlite3_column_count(self._statement)
+ for i in xrange(num_cols):
+ if self.__con._detect_types:
+ converter = self.__row_cast_map[i]
+ else:
+ converter = None
- converter = self.row_cast_map[i]
- if converter is None:
- if typ == lib.SQLITE_NULL:
- val = None
- elif typ == lib.SQLITE_INTEGER:
- val = lib.sqlite3_column_int64(self.statement, i)
- elif typ == lib.SQLITE_FLOAT:
- val = lib.sqlite3_column_double(self.statement, i)
- elif typ == lib.SQLITE_TEXT:
- text = lib.sqlite3_column_text(self.statement, i)
- text_len = lib.sqlite3_column_bytes(self.statement, i)
- val = ffi.buffer(text, text_len)[:]
- val = self.con.text_factory(val)
- elif typ == lib.SQLITE_BLOB:
- blob = lib.sqlite3_column_blob(self.statement, i)
- blob_len = lib.sqlite3_column_bytes(self.statement, i)
- val = _BLOB_TYPE(ffi.buffer(blob, blob_len))
- else:
- blob = lib.sqlite3_column_blob(self.statement, i)
+ if converter is not None:
+ blob = _lib.sqlite3_column_blob(self._statement, i)
if not blob:
val = None
else:
- blob_len = lib.sqlite3_column_bytes(self.statement, i)
- val = ffi.buffer(blob, blob_len)[:]
+ blob_len = _lib.sqlite3_column_bytes(self._statement, i)
+ val = bytes(string_at(blob, blob_len))
val = converter(val)
+ else:
+ typ = _lib.sqlite3_column_type(self._statement, i)
+ if typ == _lib.SQLITE_NULL:
+ val = None
+ elif typ == _lib.SQLITE_INTEGER:
+ val = _lib.sqlite3_column_int64(self._statement, i)
+ val = int(val)
+ elif typ == _lib.SQLITE_FLOAT:
+ val = _lib.sqlite3_column_double(self._statement, i)
+ elif typ == _lib.SQLITE_TEXT:
+ text = _lib.sqlite3_column_text(self._statement, i)
+ text_len = _lib.sqlite3_column_bytes(self._statement, i)
+ val = string_at(text, text_len)
+ val = self.__con.text_factory(val)
+ elif typ == _lib.SQLITE_BLOB:
+ blob = _lib.sqlite3_column_blob(self._statement, i)
+ blob_len = _lib.sqlite3_column_bytes(self._statement, i)
+ val = _BLOB_TYPE(string_at(blob, blob_len))
row.append(val)
row = tuple(row)
- if self.row_factory is not None:
- row = self.row_factory(cursor, row)
- self.item = row
+ if self._row_factory is not None:
+ row = self._row_factory(cursor, row)
+ self._item = row
- def reset(self):
- self.row_cast_map = None
- ret = lib.sqlite3_reset(self.statement)
- self.in_use = False
- self.exhausted = False
- return ret
+ def _next(self, cursor):
+ try:
+ item = self._item
+ except AttributeError:
+ raise StopIteration
+ del self._item
- def finalize(self):
- lib.sqlite3_finalize(self.statement)
- self.statement = ffi.NULL
- self.in_use = False
+ ret = _lib.sqlite3_step(self._statement)
+ if ret not in (_lib.SQLITE_DONE, _lib.SQLITE_ROW):
+ _lib.sqlite3_reset(self._statement)
+ raise self.__con._get_exception(ret)
+ elif ret == _lib.SQLITE_ROW:
+ self._readahead(cursor)
- def mark_dirty(self):
- self.in_use = True
-
- def __del__(self):
- lib.sqlite3_finalize(self.statement)
- self.statement = ffi.NULL
+ return item
def _get_description(self):
- if self.kind == DML:
+ if self._kind == Statement._DML:
return None
desc = []
- for i in xrange(lib.sqlite3_column_count(self.statement)):
- name = lib.sqlite3_column_name(self.statement, i)
- name = ffi.string(name).split("[")[0].strip()
+ for i in xrange(_lib.sqlite3_column_count(self._statement)):
+ name = _lib.sqlite3_column_name(self._statement, i)
+ if name is not None:
+ name = name.decode('utf-8').split("[")[0].strip()
desc.append((name, None, None, None, None, None, None))
return desc
@@ -1346,20 +1323,21 @@
def _convert_params(con, nargs, params):
_params = []
for i in range(nargs):
- typ = lib.sqlite3_value_type(params[i])
- if typ == lib.SQLITE_NULL:
+ typ = _lib.sqlite3_value_type(params[i])
+ if typ == _lib.SQLITE_NULL:
val = None
- elif typ == lib.SQLITE_INTEGER:
- val = lib.sqlite3_value_int64(params[i])
- elif typ == lib.SQLITE_FLOAT:
- val = lib.sqlite3_value_double(params[i])
- elif typ == lib.SQLITE_TEXT:
- val = lib.sqlite3_value_text(params[i])
- val = unicode(ffi.string(val), 'utf-8')
- elif typ == lib.SQLITE_BLOB:
- blob = lib.sqlite3_value_blob(params[i])
- blob_len = lib.sqlite3_value_bytes(params[i])
- val = _BLOB_TYPE(ffi.buffer(blob, blob_len))
+ elif typ == _lib.SQLITE_INTEGER:
+ val = _lib.sqlite3_value_int64(params[i])
+ val = int(val)
+ elif typ == _lib.SQLITE_FLOAT:
+ val = _lib.sqlite3_value_double(params[i])
+ elif typ == _lib.SQLITE_TEXT:
+ val = _lib.sqlite3_value_text(params[i])
+ val = val.decode('utf-8')
+ elif typ == _lib.SQLITE_BLOB:
+ blob = _lib.sqlite3_value_blob(params[i])
+ blob_len = _lib.sqlite3_value_bytes(params[i])
+ val = _BLOB_TYPE(string_at(blob, blob_len))
else:
raise NotImplementedError
_params.append(val)
@@ -1368,18 +1346,18 @@
def _convert_result(con, val):
if val is None:
- lib.sqlite3_result_null(con)
+ _lib.sqlite3_result_null(con)
elif isinstance(val, (bool, int, long)):
- lib.sqlite3_result_int64(con, int(val))
+ _lib.sqlite3_result_int64(con, int(val))
elif isinstance(val, float):
- lib.sqlite3_result_double(con, val)
+ _lib.sqlite3_result_double(con, val)
elif isinstance(val, unicode):
val = val.encode('utf-8')
- lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT)
+ _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT)
elif isinstance(val, str):
- lib.sqlite3_result_text(con, val, len(val), _SQLITE_TRANSIENT)
+ _lib.sqlite3_result_text(con, val, len(val), _lib.SQLITE_TRANSIENT)
elif isinstance(val, (buffer, bytes)):
- lib.sqlite3_result_blob(con, str(val), len(val), _SQLITE_TRANSIENT)
+ _lib.sqlite3_result_blob(con, bytes(val), len(val), _lib.SQLITE_TRANSIENT)
else:
raise NotImplementedError
@@ -1390,10 +1368,30 @@
val = real_cb(*params)
except Exception:
msg = b"user-defined function raised exception"
- lib.sqlite3_result_error(context, msg, len(msg))
+ _lib.sqlite3_result_error(context, msg, len(msg))
else:
_convert_result(context, val)
+_FUNC = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p))
+_STEP = CFUNCTYPE(None, c_void_p, c_int, POINTER(c_void_p))
+_FINAL = CFUNCTYPE(None, c_void_p)
+_lib.sqlite3_create_function.argtypes = [c_void_p, c_char_p, c_int, c_int, c_void_p, _FUNC, _STEP, _FINAL]
+_lib.sqlite3_create_function.restype = c_int
+
+_lib.sqlite3_aggregate_context.argtypes = [c_void_p, c_int]
+_lib.sqlite3_aggregate_context.restype = c_void_p
+
+_COLLATION = CFUNCTYPE(c_int, c_void_p, c_int, c_void_p, c_int, c_void_p)
+_lib.sqlite3_create_collation.argtypes = [c_void_p, c_char_p, c_int, c_void_p, _COLLATION]
+_lib.sqlite3_create_collation.restype = c_int
+
+_PROGRESS = CFUNCTYPE(c_int, c_void_p)
+_lib.sqlite3_progress_handler.argtypes = [c_void_p, c_int, _PROGRESS, c_void_p]
+_lib.sqlite3_progress_handler.restype = c_int
+
+_AUTHORIZER = CFUNCTYPE(c_int, c_void_p, c_int, c_char_p, c_char_p, c_char_p, c_char_p)
+_lib.sqlite3_set_authorizer.argtypes = [c_void_p, _AUTHORIZER, c_void_p]
+_lib.sqlite3_set_authorizer.restype = c_int
converters = {}
adapters = {}
More information about the pypy-commit
mailing list