import stat
from collections import OrderedDict
from cffi import FFI
import datetime
import time
import sys
import weakref
from codecs import utf_8_encode, utf_8_decode
from threading import _get_ident as thread_get_ident

ffi = FFI()
sqlite = ffi.dlopen("sqlite3")

# pysqlite version information
version = "2.6.0"

# pysqlite constants
PARSE_COLNAMES = 1
PARSE_DECLTYPES = 2




###########################################
# BEGIN Wrapped SQLite C API and constants
###########################################


ffi.cdef("""
typedef struct sqlite3 sqlite3;
typedef struct sqlite3_stmt sqlite3_stmt;
typedef void (*sqlite3_destructor_type)(void*);
typedef struct sqlite3_context sqlite3_context;
typedef struct Mem sqlite3_value;
const char *sqlite3_errmsg(sqlite3*);
int sqlite3_open_v2(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs);
int sqlite3_close(sqlite3*);
int sqlite3_busy_timeout(sqlite3 *, int ms);
int sqlite3_total_changes(sqlite3*);
int sqlite3_prepare(sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail);
int sqlite3_prepare_v2(sqlite3 *db,const char *zSql,int nByte,sqlite3_stmt **ppStmt,const char **pzTail);
int sqlite3_step(sqlite3_stmt*);
int sqlite3_reset(sqlite3_stmt *pStmt);
int sqlite3_finalize(sqlite3_stmt *pStmt);
int sqlite3_column_count(sqlite3_stmt *pStmt);
const char *sqlite3_column_name(sqlite3_stmt*, int N);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
int64_t sqlite3_column_int64(sqlite3_stmt*, int iCol);
double sqlite3_column_double(sqlite3_stmt*, int iCol);
int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
const char *sqlite3_column_decltype(sqlite3_stmt*,int);
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_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);
int sqlite3_clear_bindings(sqlite3_stmt*);
int sqlite3_value_type(sqlite3_value*);
int64_t sqlite3_value_int64(sqlite3_value*);
int sqlite3_value_int(sqlite3_value*);
double sqlite3_value_double(sqlite3_value*);
int sqlite3_bind_parameter_count(sqlite3_stmt*);
int sqlite3_value_bytes(sqlite3_value*);
const unsigned char *sqlite3_value_text(sqlite3_value*); //Not used.
const void *sqlite3_value_blob(sqlite3_value*);
int sqlite3_changes(sqlite3*);
void sqlite3_result_error(sqlite3_context*, const char*, int);
void sqlite3_result_int64(sqlite3_context*, int64_t);
void sqlite3_result_double(sqlite3_context*, double);
void sqlite3_result_null(sqlite3_context*);
void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
int sqlite3_complete(const char *sql);
int sqlite3_errcode(sqlite3 *db);
const char *sqlite3_libversion(void);
int sqlite3_open(char *, sqlite3 **ppDb);
typedef void (*ljsqlite3_cbstep)(sqlite3_context*,int,sqlite3_value**);
typedef void (*ljsqlite3_cbfinal)(sqlite3_context*);

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*)
);
int sqlite3_get_autocommit(sqlite3*);
int sqlite3_create_collation(
  		void*, 
  		const char *, 
  		int eTextRep, 
  		void *pArg,
  		int(*)(void *, int, void*, int, void*)
	);
	int sqlite3_process_handler(void *, int, int(*)(void *), void *);
	 
	int sqlite3_set_authorizer(
  		void*,
  		int (*)(void*,int,const char*,const char*,const char*,const char*),
  		void *
	);
	

int64_t sqlite3_last_insert_rowid(sqlite3*);
int sqlite3_bind_int64(sqlite3_stmt*, int, int64_t);
/*
typedef struct {
  sqlite3* _ptr;
  bool     _closed;
} ljsqlite3_conn;

typedef struct {
  sqlite3_stmt* _ptr;
  bool          _closed;
  sqlite3*      _conn;
  int32_t       _code;
} ljsqlite3_stmt;

*/

struct sqlite3_index_info {
  /* Inputs */
  int nConstraint;           /* Number of entries in aConstraint */
  struct sqlite3_index_constraint {
     int iColumn;              /* Column on left-hand side of constraint */
     unsigned char op;         /* Constraint operator */
     unsigned char usable;     /* True if this constraint is usable */
     int iTermOffset;          /* Used internally - xBestIndex should ignore */
  } *aConstraint;            /* Table of WHERE clause constraints */
  int nOrderBy;              /* Number of terms in the ORDER BY clause */
  struct sqlite3_index_orderby {
     int iColumn;              /* Column number */
     unsigned char desc;       /* True for DESC.  False for ASC. */
  } *aOrderBy;               /* The ORDER BY clause */
  
  
  /* Outputs */
  struct sqlite3_index_constraint_usage {
    int argvIndex;           /* if >0, constraint is part of argv to xFilter */
    unsigned char omit;      /* Do not code a test for this constraint */
  } *aConstraintUsage;
  int idxNum;                /* Number used to identify the index */
  char *idxStr;              /* String, possibly obtained from sqlite3_malloc */
  int needToFreeIdxStr;      /* Free idxStr using sqlite3_free() if true */
  int orderByConsumed;       /* True if output is already ordered */
  double estimatedCost;      /* Estimated cost of using this index */
};



typedef struct sqlite3_vtab sqlite3_vtab;
typedef struct sqlite3_index_info sqlite3_index_info;
typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
typedef struct sqlite3_module sqlite3_module;
typedef long long int sqlite_int64;
typedef unsigned long long int sqlite_uint64;
typedef sqlite_int64 sqlite3_int64;
typedef sqlite_uint64 sqlite3_uint64;

struct sqlite3_vtab {
  const sqlite3_module *pModule;  /* The module for this virtual table */
  int nRef;                       /* Used internally */
  char *zErrMsg;                  /* Error message from sqlite3_mprintf() */
  /* Virtual table implementations will typically add additional fields */
};
struct sqlite3_vtab_cursor {
  sqlite3_vtab *pVtab;      /* Virtual table of this cursor */
  /* Virtual table implementations will typically add additional fields */
int n;
};
struct sqlite3_module {
  int iVersion;
  int (*xCreate)(sqlite3*, void *pAux,
               int argc, const char *const*argv,
               sqlite3_vtab **ppVTab, char**);
  int (*xConnect)(sqlite3*, void *pAux,
               int argc, const char *const*argv,
               sqlite3_vtab **ppVTab, char**);
  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  int (*xDisconnect)(sqlite3_vtab *pVTab);
  int (*xDestroy)(sqlite3_vtab *pVTab);
  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
  int (*xClose)(sqlite3_vtab_cursor*);
  int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
                int argc, sqlite3_value **argv);
  int (*xNext)(sqlite3_vtab_cursor*);
  int (*xEof)(sqlite3_vtab_cursor*);
  int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
  int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
  int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
  int (*xBegin)(sqlite3_vtab *pVTab);
  int (*xSync)(sqlite3_vtab *pVTab);
  int (*xCommit)(sqlite3_vtab *pVTab);
  int (*xRollback)(sqlite3_vtab *pVTab);
  int (*xFindFunction)(sqlite3_vtab *pVtab, int nArg, const char *zName,
                       void (**pxFunc)(sqlite3_context*,int,sqlite3_value**),
                       void **ppArg);
  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
  /* The methods above are in version 1 of the sqlite_module object. Those 
  ** below are for version 2 and greater. */
  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
  int (*xRelease)(sqlite3_vtab *pVTab, int);
  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
};
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable);
int sqlite3_create_module(
  sqlite3 *db,               /* SQLite connection to register module with */
  const char *zName,         /* Name of the module */
  const sqlite3_module *p,   /* Methods for the module */
  void *pClientData         /* Client data for xCreate/xConnect */
  );
  void *sqlite3_malloc(int);
void *sqlite3_realloc(void*, int);
void sqlite3_free(void*);
"""
)

sqresult_text = sqlite.sqlite3_result_text

SQLITE_TRANSIENT = ffi.cast("void *",-1)

FTS3_FULLSCAN_SEARCH = 0
SQLITE_OK = 0
SQLITE_ERROR = 1
SQLITE_INTERNAL = 2
SQLITE_PERM = 3
SQLITE_ABORT = 4
SQLITE_BUSY = 5
SQLITE_LOCKED = 6
SQLITE_NOMEM = 7
SQLITE_READONLY = 8
SQLITE_INTERRUPT = 9
SQLITE_IOERR = 10
SQLITE_CORRUPT = 11
SQLITE_NOTFOUND = 12
SQLITE_FULL = 13
SQLITE_CANTOPEN = 14
SQLITE_PROTOCOL = 15
SQLITE_EMPTY = 16
SQLITE_SCHEMA = 17
SQLITE_TOOBIG = 18
SQLITE_CONSTRAINT = 19
SQLITE_MISMATCH = 20
SQLITE_MISUSE = 21
SQLITE_NOLFS = 22
SQLITE_AUTH = 23
SQLITE_FORMAT = 24
SQLITE_RANGE = 25
SQLITE_NOTADB = 26
SQLITE_ROW = 100
SQLITE_DONE = 101
SQLITE_INTEGER = 1
SQLITE_FLOAT = 2
SQLITE_BLOB = 4
SQLITE_NULL = 5
SQLITE_TEXT = 3
SQLITE3_TEXT = 3


SQLITE_UTF8 = 1

SQLITE_DENY     = 1
SQLITE_IGNORE   = 2

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
SQLITE_CREATE_VTABLE            = 29
SQLITE_DROP_VTABLE              = 30
SQLITE_FUNCTION                 = 31

# SQLite C API



HAS_LOAD_EXTENSION = hasattr(sqlite, "sqlite3_enable_load_extension")
if HAS_LOAD_EXTENSION:
    ffi.cdef("""int sqlite3_enable_load_extension(sqlite3 *db, int onoff);""")
    


##########################################
# END Wrapped SQLite C API and constants
##########################################

# SQLite version information
sqlite_version = sqlite.sqlite3_libversion()


class ExecutionCompleteError(StandardError): 
    pass

class Error(StandardError):
    pass

class SQLError(StandardError):
    pass 

class Warning(StandardError):
    pass

class InterfaceError(Error):
    pass

class DatabaseError(Error):
    pass

class InternalError(DatabaseError):
    pass

class OperationalError(DatabaseError):
    pass

class ProgrammingError(DatabaseError):
    pass

class IntegrityError(DatabaseError):
    pass

class DataError(DatabaseError):
    pass

class NotSupportedError(DatabaseError):
    pass

class ConstraintError(DatabaseError):
    pass

def complete(*args):
    return sqlite.sqlite3_complete(args[0].encode('utf-8'))


def apswversion():
    return "MSPW ver 0.01"

def sqlitelibversion():
    return ffi.string(sqlite.sqlite3_libversion())

def connect(database, **kwargs):
    factory = kwargs.get("factory", Connection)
    return factory(database, **kwargs)

def unicode_text_factory(x):
    return x


class StatementCache(object):
     def __init__(self, connection, maxcount):
        self.connection = connection
        self.maxcount = maxcount
        self.cache = OrderedDict()

     def get(self, sql, row_factory):
        try:


            stat = self.cache[sql]

        except KeyError:

            stat = Statement(self.connection, sql)

            self.cache[sql] = stat
            if len(self.cache) > self.maxcount:
                self.cache.popitem(0)

        #
        if stat.in_use:
            stat = Statement(self.connection, sql)
        stat.set_row_factory(row_factory)
        return stat


class Connection(object):
    def __init__(self, database, timeout=None, detect_types=0, isolation_level="",
                 check_same_thread=True, factory=None, cached_statements=100):
        
        db_p = ffi.new("sqlite3 **")
        if sqlite.sqlite3_open(database, db_p) != SQLITE_OK:
            raise OperationalError("Could not open database")

        self.db = db_p[0]

        if timeout is not None:
            timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds
            sqlite.sqlite3_busy_timeout(self.db, timeout)

        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.Error = Error
        self.Warning = Warning
        self.InterfaceError = InterfaceError
        self.DatabaseError = DatabaseError
        self.InternalError = InternalError
        self.OperationalError = OperationalError
        self.ProgrammingError = ProgrammingError
        self.IntegrityError = IntegrityError
        self.DataError = DataError
        self.NotSupportedError = NotSupportedError

        self.func_cache = {}
        self._aggregates = {}
        self._vtdatasource = {}
        self._vtmodules = {}
        self._vttables = {}
        self._vtcursors = []
        self._vtcursorrowdata = []
        self._vtcursorinstances = []
        self._vtcursorcolumn = []
        self._vtcursoreof = []
        self._vttmp = {}
        self.aggregate_instances = {}
        self._collations = {}
        if check_same_thread:
            self.thread_ident = thread_get_ident()

    def _get_exception(self, error_code = None):
        if error_code is None:
            error_code = sqlite.sqlite3_errcode(self.db)
        error_message = ffi.string(sqlite.sqlite3_errmsg(self.db))

        if error_code == SQLITE_OK:
            raise ValueError("error signalled but got SQLITE_OK")
        elif error_code in (SQLITE_INTERNAL, SQLITE_NOTFOUND):
            exc = InternalError
        elif error_code == SQLITE_NOMEM:
            exc = MemoryError
        elif error_code in (SQLITE_ERROR, SQLITE_PERM, SQLITE_ABORT, SQLITE_BUSY, SQLITE_LOCKED,
            SQLITE_READONLY, SQLITE_INTERRUPT, SQLITE_IOERR, SQLITE_FULL, SQLITE_CANTOPEN,
            SQLITE_PROTOCOL, SQLITE_EMPTY, SQLITE_SCHEMA):
            exc = OperationalError
        elif error_code == SQLITE_CORRUPT:
            exc = DatabaseError
        elif error_code == SQLITE_TOOBIG:
            exc = DataError
        elif error_code in (SQLITE_CONSTRAINT, SQLITE_MISMATCH):
            exc = IntegrityError
        elif error_code == SQLITE_MISUSE:
            exc = ProgrammingError
        else:
            exc = DatabaseError
        exc = exc(error_message)
        exc.error_code = error_code
        return exc

    def _remember_statement(self, statement):
        self.statements.append(weakref.ref(statement))
        self.statement_counter += 1

        if self.statement_counter % 100 == 0:
            self.statements = [ref for ref in self.statements if ref() is not None]

    def _check_thread(self):
        if not hasattr(self, 'thread_ident'):
            return
        if self.thread_ident != thread_get_ident():
            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())

    def _reset_cursors(self):
        for cursor_ref in self.cursors:
            cursor = cursor_ref()
            if cursor:
                cursor.reset = True

    def cursor(self, factory=None):
        self._check_thread()
        self._check_closed()
        if factory is None:
            factory = Cursor
        cur = factory(self)
        if self.row_factory is not None:
            cur.row_factory = self.row_factory
        return cur

    def executemany(self, *args):
        self._check_closed()
        cur = Cursor(self)
        if self.row_factory is not None:
            cur.row_factory = self.row_factory
        return cur.executemany(*args)

    def execute(self, *args):
        self._check_closed()
        cur = Cursor(self)
        if self.row_factory is not None:
            cur.row_factory = self.row_factory
        return cur.execute(*args)

    def executescript(self, *args):
        self._check_closed()
        cur = Cursor(self)
        if self.row_factory is not None:
            cur.row_factory = self.row_factory
        return cur.executescript(*args)

    def __call__(self, sql):
        self._check_closed()
        if not isinstance(sql, (str, unicode)):
            raise Warning("SQL is of wrong type. Must be string or unicode.")
        statement = self.statement_cache.get(sql, self.row_factory)
        return statement

    def _get_isolation_level(self):
        return self._isolation_level
    def _set_isolation_level(self, val):
        if val is None:
            self.commit()
        if isinstance(val, unicode):
            val = str(val)
        self._isolation_level = val
    isolation_level = property(_get_isolation_level, _set_isolation_level)

    def _begin(self):
       
        self._check_closed()
        if self._isolation_level is None:
            return
        if sqlite.sqlite3_get_autocommit(self.db):
            
                sql = "BEGIN " + self._isolation_level
                statement_p = ffi.new("sqlite3_stmt **")
                next_char = ffi.new("char *")
                
                ret = sqlite.sqlite3_prepare_v2(self.db, sql, -1, statement_p, next_char)
                
                statement = statement_p[0]
                
                if ret != SQLITE_OK:
                    raise self._get_exception(ret)
                ret = sqlite.sqlite3_step(statement)
                if ret != SQLITE_DONE:
                    raise self._get_exception(ret)
            
                
                sqlite.sqlite3_finalize(statement)
                

    def commit(self):
        
        self._check_thread()
        self._check_closed()
        if sqlite.sqlite3_get_autocommit(self.db):
            return
        
        for statement in self.statements:
            obj = statement()
            if obj is not None:
                obj.reset()

        try:
            sql = "COMMIT"
            statement_p = ffi.new("char **")
            next_char = ffi.new("char *")
            ret = sqlite.sqlite3_prepare_v2(self.db, sql, -1, statement_p, next_char)
            statement = statement_p[0]
            if ret != SQLITE_OK:
                raise self._get_exception(ret)
            ret = sqlite.sqlite3_step(statement)
            if ret != SQLITE_DONE:
                raise self._get_exception(ret)
        finally:
            
            sqlite.sqlite3_finalize(statement)

    def rollback(self):
        self._check_thread()
        self._check_closed()
        if sqlite.sqlite3_get_autocommit(self.db):
            return

        for statement in self.statements:
            obj = statement()
            if obj is not None:
                obj.reset()

        try:
            sql = "ROLLBACK"
            statement_p = ffi.new("char **")
            next_char = ffi.new("char *")
            ret = sqlite.sqlite3_prepare_v2(self.db, sql, -1, statement_p, next_char)
            statement = statement_p[0]
            if ret != SQLITE_OK:
                raise self._get_exception(ret)
            ret = sqlite.sqlite3_step(statement)
            if ret != SQLITE_DONE:
                raise self._get_exception(ret)
        finally:
            sqlite.sqlite3_finalize(statement)
            self._reset_cursors()

    def _check_closed(self):
        if getattr(self, 'closed', True):
            raise ProgrammingError("Cannot operate on a closed database.")

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, exc_tb):
        if exc_type is None and exc_value is None and exc_tb is None:
            self.commit()
        else:
            self.rollback()

    def _get_total_changes(self):
        return sqlite.sqlite3_total_changes(self.db)
    total_changes = property(_get_total_changes)

    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 = sqlite.sqlite3_close(self.db)
        self._reset_cursors()
        if ret != SQLITE_OK:
            raise self._get_exception(ret)

    def create_collation(self, name, callback):
        self._check_thread()
        self._check_closed()
        name = name.upper()
        if not name.replace('_', '').isalnum():
            raise ProgrammingError("invalid character in collation name")

        if callback is None:
            del self._collations[name]
            c_collation_callback = cast(None, COLLATION)
        else:
            if not callable(callback):
                raise TypeError("parameter must be callable")

            def collation_callback(context, len1, str1, len2, str2):
                text1 = ffi.string(str1)
                text2 = ffi.string(str2)

                return callback(text1, text2)

            c_collation_callback = COLLATION(collation_callback)
            self._collations[name] = c_collation_callback
	

        ret = sqlite.sqlite3_create_collation(self.db, name,
                                              SQLITE_UTF8,
                                              None,
                                              c_collation_callback)
        if ret != SQLITE_OK:
            raise self._get_exception(ret)

    def set_progress_handler(self, callable, nsteps):
        self._check_thread()
        self._check_closed()
        if callable is None:
            c_progress_handler = cast(None, PROGRESS)
        else:
            try:
                c_progress_handler, _ = self.func_cache[callable]
            except KeyError:
                def progress_handler(userdata):
                    try:
                        ret = callable()
                        return bool(ret)
                    except Exception:
                        # abort query if error occurred
                        return 1
                c_progress_handler = PROGRESS(progress_handler)

                self.func_cache[callable] = c_progress_handler, progress_handler
        ret = sqlite.sqlite3_progress_handler(self.db, nsteps,
                                              c_progress_handler,
                                              None)
        if ret != SQLITE_OK:
            raise self._get_exception(ret)

    def set_authorizer(self, callback):
        self._check_thread()
        self._check_closed()

        try:
            c_authorizer, _ = self.func_cache[callback]
        except KeyError:
            def authorizer(userdata, action, arg1, arg2, dbname, source):
                try:
                    return int(callback(action, arg1, arg2, dbname, source))
                except Exception:
                    return SQLITE_DENY
            c_authorizer = AUTHORIZER(authorizer)

            self.func_cache[callback] = c_authorizer, authorizer

        ret = sqlite.sqlite3_set_authorizer(self.db,
                                            c_authorizer,
                                            None)
        if ret != SQLITE_OK:
            raise self._get_exception(ret)

    def createscalarfunction(self, name, callback, num_args = -1):
        self._check_thread()
        self._check_closed()
	
        try:
            c_closure, _ = self.func_cache[callback]
        except KeyError:
            #def closure(context, nargs, c_params):
            #    function_callback(callback, context, nargs, c_params)

            def closure(context, nargs, params):
                try:
                    val=callback(*[_sqlite_to_python[sqlite.sqlite3_value_type(params[i])](params[i]) for i in xrange(nargs)])
                    _python_to_sqlite[val.__class__](context,val)
                except Exception, e:
                    msg = "user-defined function raised exception: "+str(e)
                    sqlite.sqlite3_result_error(context, msg, len(msg))

            c_closure = ffi.callback("void(sqlite3_context*,int,sqlite3_value**)", closure)
            self.func_cache[callback] = c_closure, closure

        ret = sqlite.sqlite3_create_function(self.db, name, num_args,
                                             SQLITE_UTF8, ffi.NULL,
                                             c_closure,
                                             ffi.NULL,
                                             ffi.NULL)
        if ret != SQLITE_OK:
            raise self.OperationalError("Error creating function")


    def createaggregatefunction(self, name, cls, num_args = -1):
        self._check_thread()
        self._check_closed()
        
        try:
            
            c_step_callback, c_final_callback, _, _ = self._aggregates[cls]
        except KeyError:
            def step_callback(context, nargs, params):
                
                aggregate_ptr = ffi.cast("ssize_t *",
                    sqlite.sqlite3_aggregate_context(
                    context, ffi.sizeof("ssize_t")) )

                if not aggregate_ptr[0]:
                    try:
                        aggregate,_,_ = cls()
                        
                    except Exception:
                        msg = ("user-defined aggregate's '__init__' "
                               "method raised error")
                        sqlite.sqlite3_result_error(context, msg, len(msg))
                        return
                    aggregate_id = id(aggregate)
                    self.aggregate_instances[aggregate_id] = aggregate
                    aggregate_ptr[0] = aggregate_id
                else:
                    aggregate = self.aggregate_instances[aggregate_ptr[0]]

                try:
                    aggregate.step(*[_sqlite_to_python[sqlite.sqlite3_value_type(params[i])](params[i]) for i in xrange(nargs)])
                except Exception:
                    msg = ("user-defined aggregate's 'step' "
                           "method raised error")
                    sqlite.sqlite3_result_error(context, msg, len(msg))

            def final_callback(context):
                
                aggregate_ptr = ffi.cast( "ssize_t *",
                    sqlite.sqlite3_aggregate_context(
                    context, ffi.sizeof("ssize_t")) )
                
                if aggregate_ptr[0]:
                    
                    aggregate = self.aggregate_instances[aggregate_ptr[0]]
                    
                    try:
                        val = aggregate.final()
                        
                    except Exception:
                        msg = ("user-defined aggregate's 'finalize' "
                               "method raised error")
                        
                        sqlite.sqlite3_result_error(context, msg, len(msg))
                    else:
                        
                        _python_to_sqlite[val.__class__](context,val)
                        
                    finally:
                        
                        del self.aggregate_instances[aggregate_ptr[0]]

            c_step_callback = ffi.callback("void(sqlite3_context*,int,sqlite3_value**)", step_callback)
            c_final_callback = ffi.callback("void(sqlite3_context*)", final_callback)
            
            

            self._aggregates[cls] = (c_step_callback, c_final_callback,
                                     step_callback, final_callback)

        ret = sqlite.sqlite3_create_function(self.db, name, num_args,
                                             SQLITE_UTF8, ffi.NULL,
                                             ffi.NULL,
                                             c_step_callback,
                                             c_final_callback)
        if ret != SQLITE_OK:
            raise self._get_exception(ret)
        
    def createmodule(self, name, datasource):
        self._check_thread()
        self._check_closed()

        self._vtdatasource[datasource] = datasource

            # Represents a table
        try:
            vtmodule = self._vtmodules[name](0)
               
        except KeyError:
            closure = lambda x:x
            closure.lastrow = None
            closure.lastcursorid = None

            def xCreate(db, paux, argc, argv , ppvtab , pzErr): #int (*xCreate)(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**);
                
                pzErr[0] = sqlite.sqlite3_malloc(100)
                
                schema , table = datasource.Create(self,ffi.string(argv[0]), ffi.string(argv[1]), ffi.string(argv[2]), *tuple([ffi.string(argv[i]) for i in xrange(3,argc)]))
		
                
                newvtab = ffi.new("sqlite3_vtab *")
                ppvtab[0] = newvtab

                self._vttables[newvtab] = table
                
                
                ret = sqlite.sqlite3_declare_vtab(db, schema.encode('utf-8'))
                
                if ret != SQLITE_OK:
                    raise self._get_exception(ret)
                
                return SQLITE_OK
            
            xConnect = xCreate

            def xBestIndex(pvtab, pInfo): #int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
               
                pInfo.idxNum = FTS3_FULLSCAN_SEARCH
                pInfo.estimatedCost = 500000
                #try:
                
                #    bestIndex = self._vttables[pvtab].BestIndex()
                #except:
                
                #    pass
                return SQLITE_OK
            
            def xDisconnect(pvtab): #int (*xDisconnect)(sqlite3_vtab *pVTab);
                #print 'xDisconnect'
                try:
                    del self._vttables[pvtab]
                except:
                    pass
                return SQLITE_OK

            xDestroy = xDisconnect
            
            def xOpen(pvtab , ppcursor):  # int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
                
                newcursor = ffi.new("sqlite3_vtab_cursor *")  
                
                newcursor.n = len(self._vtcursors)
                self._vtcursors.append(newcursor)
                instance = self._vttables[pvtab].Open()
                self._vtcursorinstances.append(instance)
                
                self._vtcursorcolumn.append(instance.Column)
                self._vtcursoreof.append(instance.Eof)
                ppcursor[0] = newcursor
                
                return SQLITE_OK
            
            def xClose(vtabcursor): #int (*xClose)(sqlite3_vtab_cursor*);
                #print 'xClose'
                #print vtabcursor.n
                
                try:
                    self._vtcursorinstances[vtabcursor.n].Close()
                except:
                    pass

                try:
                    self._vtcursors.pop(vtabcursor.n)
                    self._vtcursorinstances.pop(vtabcursor.n)
                    
                    self._vtcursorcolumn.pop(vtabcursor.n)
                    self._vtcursoreof.pop(vtabcursor.n)
                except:
                    pass
                                
                return SQLITE_OK
            
            def xFilter(vtabcursor, idxnum , idxstr , argc , argv) : #int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv);
                #print 'xFilter'
                #print vtabcursor.n
                
                try:                
                    self._vtcursorinstances[vtabcursor.n].Filter()
                except:
                    pass
        
                return SQLITE_OK
            
            def xNext(vtabcursor): #int (*xNext)(sqlite3_vtab_cursor*);
                #print 'xNext'
                #print vtabcursor.n
                self._vtcursorinstances[vtabcursor.n].Next()
                return SQLITE_OK
            
            def xEof(vtabcursor): #int (*xEof)(sqlite3_vtab_cursor*);
                #print 'xEof'
                #print vtabcursor.n
                eof = 1
                try:
                    eof = self._vtcursoreof[vtabcursor.n]()
                except:
                    eof = 1
        
                return eof

            def xNextFast(vtabcursor):
                self._vtcursorinstances[vtabcursor.n].Next()
                return SQLITE_OK

            def xColumnFast(vtabcursor,context,col):
                val = self._vtcursorinstances[vtabcursor.n].row[col]
		
                _python_to_sqlite[val.__class__](context,val)                
                return SQLITE_OK

            def xColumn(vtabcursor, context , col): # int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
                
                #print vtabcursor.n
                val = self._vtcursorcolumn[vtabcursor.n](col)
                _python_to_sqlite[val.__class__](context,val)
                return SQLITE_OK
                
            
            def xRowid(vtabcursor, pRowid): # int (*xRowid)(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid);
                
                pRowid[0] = ffi.cast('sqlite3_int64', self._vtcursorinstances[vtabcursor.n].Rowid() )
            
            def xUpdate(pvtab,val,num) : #int (*xUpdate)(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *);
                
                return SQLITE_OK
                        
            def xCommit(pvtab): #int (*xCommit)(sqlite3_vtab *pVTab);
                return SQLITE_OK

            def xSync(pvtab): #int (*xCommit)(sqlite3_vtab *pVTab);
                return SQLITE_OK
            
            def xBegin(pvtab): #int (*xCommit)(sqlite3_vtab *pVTab);
                return SQLITE_OK
           
            def xRollback(pvtab): #  int (*xRollback)(sqlite3_vtab *pVTab);
                print 17
            
            def xRename(pvtab, znew): #  int (*xRename)(sqlite3_vtab *pVtab, const char *zNew);
                print 18
            
            def xSavepoint(pvtab, num): #  int (*xSavepoint)(sqlite3_vtab *pVTab, int);
                print 19
            
            def xRelease(pvtab , num): #  int (*xRelease)(sqlite3_vtab *pVTab, int);
                print 20
                return SQLITE_OK
            
            def xRollbackTo(pvtab , num): #  int (*xRollbackTo)(sqlite3_vtab *pVTab, int);
                print 21
            
            vtmodule = ffi.new("sqlite3_module *")

            xCreateCallback = ffi.callback("int(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**)", xCreate)
            xConnectCallback = ffi.callback("int(sqlite3*, void *pAux, int argc, const char *const*argv, sqlite3_vtab **ppVTab, char**)", xConnect) 
            xBestIndexCallback  = ffi.callback("int(sqlite3_vtab *pVTab, sqlite3_index_info*)", xBestIndex)
            xDestroyCallback = ffi.callback("int(sqlite3_vtab *pVTab)", xDestroy)
            xDisconnectCallback = ffi.callback("int(sqlite3_vtab *pVTab)", xDisconnect)
            xOpenCallback = ffi.callback("int(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursfactoryor)", xOpen)
            xCloseCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xClose)
            xFilterCallback = ffi.callback("int(sqlite3_vtab_cursor*, int idxNum, const char *idxStr, int argc, sqlite3_value **argv)", xFilter)
            xEofCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xEof)  
            xRowidCallback = ffi.callback("int(sqlite3_vtab_cursor*, sqlite3_int64 *pRowid)", xRowid) 
            xUpdateCallback = ffi.callback("int(sqlite3_vtab *, int, sqlite3_value **, sqlite3_int64 *)", xUpdate)
            xBeginCallback = ffi.NULL #ffi.callback("int(sqlite3_vtab *pVTab)", xBegin)
            xSyncCallback = ffi.NULL # ffi.callback("int(sqlite3_vtab *pVTab)", xSync)
            xCommitCallback = ffi.NULL #ffi.callback("int(sqlite3_vtab *pVTab)", xCommit)
            xRollbackCallback = ffi.callback("int(sqlite3_vtab *pVTab)", xRollback)
            xRenameCallback = ffi.callback("int(sqlite3_vtab *pVtab, const char *zNew)", xRename)
            xSavepointCallback = ffi.callback("int(sqlite3_vtab *pVTab, int)", xSavepoint)
            xReleaseCallback = ffi.callback("int(sqlite3_vtab *pVTab, int)", xRelease)
            xRollbackToCallback = ffi.callback("int(sqlite3_vtab *pVTab, int)", xRollbackTo)
            xFindFunctionCallback = ffi.NULL

            if '_madisVT' in datasource.__dict__ and datasource._madisVT == True:
                xNextCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xNextFast)
                xColumnCallback = ffi.callback("int(sqlite3_vtab_cursor*, sqlite3_context*, int)", xColumnFast)
            else:
                xNextCallback = ffi.callback("int(sqlite3_vtab_cursor*)", xNext)
                xColumnCallback = ffi.callback("int(sqlite3_vtab_cursor*, sqlite3_context*, int)", xColumn)

            vtmodule.xCreate = xCreateCallback
            vtmodule.xConnect =  xConnectCallback
            vtmodule.xBestIndex = xBestIndexCallback
            vtmodule.xDisconnect = xDisconnectCallback
            vtmodule.xDestroy = xDestroyCallback
            vtmodule.xOpen = xOpenCallback
            vtmodule.xClose = xCloseCallback
            vtmodule.xFilter = xFilterCallback
            vtmodule.xNext = xNextCallback
            vtmodule.xEof = xEofCallback
            vtmodule.xColumn = xColumnCallback
            vtmodule.xRowid = xRowidCallback
            vtmodule.xUpdate = xUpdateCallback
            vtmodule.xBegin = xBeginCallback
            vtmodule.xSync = xSyncCallback
            vtmodule.xCommit = xCommitCallback
            vtmodule.xRollback = xRollbackCallback
            vtmodule.xRename = xRenameCallback
            vtmodule.xSavepoint = xSavepointCallback

            vtmodule.xRelease = xReleaseCallback
    
            vtmodule.xRollbackTo = xRollbackToCallback
            vtmodule.xFindFunction = xFindFunctionCallback

            self._vtmodules[datasource] = (vtmodule, xCreate, xConnect, xBestIndex, xDisconnect, xDestroy, xOpen, 
		xClose, xFilter, xNext, xEof, xColumn, xRowid, xUpdate, xBegin,xSync,xCommit,
		xRollback, xRename, xSavepoint, xRelease, xRollbackTo, xCreateCallback, xConnectCallback, xBestIndexCallback, xDestroyCallback,xDisconnectCallback , 
        xOpenCallback, xCloseCallback, xFilterCallback, xNextCallback, xEofCallback,  xColumnCallback, xRowidCallback, xUpdateCallback, xBeginCallback, 
         xSyncCallback, xCommitCallback, xRollbackCallback, xRenameCallback, xSavepointCallback, xReleaseCallback,  xRollbackToCallback, xFindFunctionCallback,
        xNextFast, xColumnFast
        )
        
#        int sqlite3_create_module_v2(
#  sqlite3 *db,               /* SQLite connection to register module with */
#  const char *zName,         /* Name of the module */
#  const sqlite3_module *p,   /* Methods for the module */
#  void *pClientData,         /* Client data for xCreate/xConnect */
#  void(*xDestroy)(void*)     /* Module destructor function */
#  );

        ret = sqlite.sqlite3_create_module(self.db, name , vtmodule ,ffi.NULL)
        if ret != SQLITE_OK:
            raise self._get_exception(ret)
        
	
    def iterdump(self):
        from sqlite3.dump import _iterdump
        return _iterdump(self)

    #if HAS_LOAD_EXTENSION:
    def enableloadextension(self, enabled):
            self._check_thread()
            self._check_closed()
            return
            rc = sqlite.sqlite3_enable_load_extension(self.db, int(enabled))
                        
            if rc != SQLITE_OK:
                raise OperationalError("Error enabling load extension")

DML, DQL, DDL = range(3)

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.arraysize = 1
        self.row_factory = None
        self.rowcount = -1
        self.statement = None
        self.reset = False
        self.locked = False

    def _check_closed(self):
        if not getattr(self, 'connection', None):
            raise ProgrammingError("Cannot operate on a closed cursor.")
        self.connection._check_thread() 
        self.connection._check_closed()

    def _check_and_lock(self):
        self._check_closed()
        return CursorLock(self)



    


    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(
                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()

            self.statement.set_params(params)

            # Actually execute the SQL statement
            ret = sqlite.sqlite3_step(self.statement.statement)


            if ret not in (SQLITE_DONE, SQLITE_ROW):
                self.statement.reset()
                raise self.connection._get_exception(ret)

            if self.statement.kind == DML:
                self.statement.reset()

            if self.statement.kind == DQL and ret == SQLITE_ROW:
                self.statement._build_row_cast_map()
                self.statement._readahead(self)
            else:
                self.statement.item = None
                self.statement.exhausted = True

            self.rowcount = -1
            if self.statement.kind == DML:
                self.rowcount = sqlite.sqlite3_changes(self.connection.db)

        return self
        
            
            
       
        

    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 = sqlite.sqlite3_step(self.statement.statement)
                if ret != SQLITE_DONE:
                    raise self.connection._get_exception(ret)
                self.rowcount += sqlite.sqlite3_changes(self.connection.db)

        return self

    def executescript(self, sql):
        self._description = None
        self.reset = False
        if type(sql) is unicode:
            sql = sql.encode("utf-8")
        self._check_closed()
        statement = None
        statement_p = ffi.new("sqlite3_stmt **",statement)

        c_sql = ffi.new("char[]",sql)

        c_sql_p = ffi.new("char**",c_sql)

	
        self.connection.commit()
        while True:
            
            rc = sqlite.sqlite3_prepare(self.connection.db, c_sql, -1, statement_p, c_sql_p)
            
            c_sql = c_sql_p[0]
            statement = statement_p[0]
            if rc != SQLITE_OK:
                raise self.connection._get_exception(rc)

            rc = SQLITE_ROW
            while rc == SQLITE_ROW:
                if not statement:
                    rc = SQLITE_OK
                else:
                    rc = sqlite.sqlite3_step(statement)

            if rc != SQLITE_DONE:
                sqlite.sqlite3_finalize(statement)
                if rc == SQLITE_OK:
                    return self
                else :
                    raise self.connection._get_exception(rc)
            rc = sqlite.sqlite3_finalize(statement)
            if rc != SQLITE_OK:
                raise self.connection._get_exception(rc)

            if not c_sql:
                break
        return self

    def __iter__(self):
        return iter(self.fetchone, None)

    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.")

    # do all statements
    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

    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 = []
        for row in self:
            lst.append(row)
            if len(lst) == size:
                break
        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 _getlastrowid(self):
        return sqlite.sqlite3_last_insert_rowid(self.connection.db)

    def close(self,*args):
        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 setinputsizes(self, *args):
        pass
    def setoutputsize(self, *args):
        pass


    description = property(_getdescription)
    getdescription = _getdescription
    lastrowid = property(_getlastrowid)

class Statement(object):
    def __init__(self, connection, sql):
        self.statement = None
        self.column_count = None
        
        if not isinstance(sql, str):
            raise ValueError("sql must be a string")
        
        self.con = connection
        self.sql = sql # DEBUG ONLY
        first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper()
        if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"):
            self.kind = DML
        elif first_word in ("SELECT", "PRAGMA"):
            self.kind = DQL
        else:
            self.kind = DDL
        
        self.exhausted = False
        self.in_use = False
        #
        # set by set_row_factory
        self.row_factory = None

       
        self.statement_p = ffi.new("sqlite3_stmt **",self.statement)
        
        next_char = ffi.new("char[]","")
        
        mynext_char = ffi.new("char**",next_char)
        sql_char = ffi.new("char[]",sql)
        
        try :
            
            ret = sqlite.sqlite3_prepare_v2(self.con.db, sql_char, -1, self.statement_p, mynext_char)
            
        except Exception,e:
            print str(e)
        next_char = ffi.string(mynext_char[0])
        self.statement = self.statement_p[0]
        
        if ret == SQLITE_OK and self.statement is None:
            
            # an empty statement, we work around that, as it's the least trouble
            ret = sqlite.sqlite3_prepare_v2(self.con.db, "select 42", -1, self.statement_p, next_char)
            self.kind = DQL
         
        if ret != SQLITE_OK:
            raise self.con._get_exception(ret)

        self.con._remember_statement(self)
        
        if _check_remaining_sql(next_char):
            raise Warning("One and only one statement required: %r" % (
                next_char,))
        # sql_char should remain alive until here
        
        self._build_row_cast_map()
        
       
    def set_row_factory(self, row_factory):
        self.row_factory = row_factory

    def _build_row_cast_map(self):
        self.row_cast_map = []
        for i in xrange(sqlite.sqlite3_column_count(self.statement)):
            converter = None

            if self.con.detect_types & PARSE_COLNAMES:
                colname = sqlite.sqlite3_column_name(self.statement, i)
                if colname is not None:
                    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()]

            if converter is None and self.con.detect_types & PARSE_DECLTYPES:
                decltype = sqlite.sqlite3_column_decltype(self.statement, i)
                if decltype is not None:
                    decltype = decltype.split()[0]      # if multiple words, use first, eg. "INTEGER NOT NULL" => "INTEGER"
                    if '(' in decltype:
                        decltype = decltype[:decltype.index('(')]
                    converter = converters.get(decltype.upper(), None)

            self.row_cast_map.append(converter)

    def _check_decodable(self, param):
        if self.con.text_factory in (unicode, OptimizedUnicode, unicode_text_factory):
            for c in param:
                if ord(c) & 0x80 != 0:
                    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). "
                            "It is highly recommended that you instead "
                            "just switch your application to Unicode strings.")

    def set_param(self, idx, param):
        cvt = converters.get(type(param))
        if cvt is not None:
            cvt = param = cvt(param)

        param = adapt(param)

        if param is None:
            sqlite.sqlite3_bind_null(self.statement, idx)
        elif type(param) in (bool, int, long):
            if -2147483648 <= param <= 2147483647:
                sqlite.sqlite3_bind_int(self.statement, idx, param)
            else:
                sqlite.sqlite3_bind_int64(self.statement, idx, param)
        elif type(param) is float:
            sqlite.sqlite3_bind_double(self.statement, idx, param)
        elif isinstance(param, str):
            self._check_decodable(param)
            sqlite.sqlite3_bind_text(self.statement, idx, param, len(param), SQLITE_TRANSIENT)
        elif isinstance(param, unicode):
            param = param.encode("utf-8")
            sqlite.sqlite3_bind_text(self.statement, idx, param, len(param), SQLITE_TRANSIENT)
        elif type(param) is buffer:
            sqlite.sqlite3_bind_blob(self.statement, idx, str(param), len(param), SQLITE_TRANSIENT)
        else:
            raise InterfaceError("parameter type %s is not supported" % str(type(param)))

    def set_params(self, params):
        
        
        ret = sqlite.sqlite3_reset(self.statement)
       
        if ret != SQLITE_OK:
            raise self.con._get_exception(ret)
        self.mark_dirty()
        
        if params is None:
            if sqlite.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) != sqlite.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:
            for idx in range(1, sqlite.sqlite3_bind_parameter_count(self.statement) + 1):
                param_name = sqlite.sqlite3_bind_parameter_name(self.statement, idx)
                if param_name is None:
                    raise ProgrammingError("need named parameters")
                param_name = param_name[1:]
                try:
                    param = params[param_name]
                except KeyError:
                    raise ProgrammingError("missing parameter '%s'" %param)
                self.set_param(idx, param)

    def next(self, cursor):
        self.con._check_closed()
        self.con._check_thread()
        if self.exhausted:
            raise StopIteration
        item = self.item

        ret = sqlite.sqlite3_step(self.statement)
        if ret == SQLITE_DONE:
            self.exhausted = True
            self.item = None
        elif ret != SQLITE_ROW:
            exc = self.con._get_exception(ret)
            sqlite.sqlite3_reset(self.statement)
            raise exc

        self._readahead(cursor)
        return item


    
    def _readahead(self, cursor):
        if self.column_count == None:
            self.column_count = sqlite.sqlite3_column_count(self.statement)

#        for i in xrange(self.column_count):
#            typ = sqlite.sqlite3_column_type(self.statement, i)

#            converter = self.row_cast_map[i]
#            if converter is None:
#                if typ == SQLITE_INTEGER:
#                    val = sqlite.sqlite3_column_int64(self.statement, i)
#                    if -sys.maxint-1 <= val <= sys.maxint:
#                        val = int(val)
#                elif typ == SQLITE_FLOAT:
#                    val = sqlite.sqlite3_column_double(self.statement, i)
#                elif typ == SQLITE_BLOB:
#                    blob_len = sqlite.sqlite3_column_bytes(self.statement, i)
#                    blob = sqlite.sqlite3_column_blob(self.statement, i)
#                    val = buffer(ffi.string(blobb))
#                elif typ == SQLITE_NULL:
#                    val = None
#                elif typ == SQLITE_TEXT:
#                    text_len = sqlite.sqlite3_column_bytes(self.statement, i)
#                    text = sqlite.sqlite3_column_text(self.statement, i)
#                    val = ffi.string(text)
#                    val = self.con.text_factory(val)
#            else:
#                blob = sqlite.sqlite3_column_blob(self.statement, i)
#                if not blob:
#                    val = None
#                else:
#                    blob_len = sqlite.sqlite3_column_bytes(self.statement, i)
#                    val = ffi.string(blob)
#                    val = converter(val)
#            row.append(val)
#        row = tuple(row)

        self.item = tuple(_sqlite_to_python_statement[ sqlite.sqlite3_column_type(self.statement, i) ](self.statement, i) for i in xrange(self.column_count))
        if self.row_factory is not None:
            self.item = self.row_factory(cursor, self.item)

    def reset(self):
        self.row_cast_map = None
        ret = sqlite.sqlite3_reset(self.statement)
        self.in_use = False
        self.exhausted = False
        return ret

    def finalize(self):
        sqlite.sqlite3_finalize(self.statement)
        self.statement = None
        self.in_use = False

    def mark_dirty(self):
        self.in_use = True

    def __del__(self):
        sqlite.sqlite3_finalize(self.statement)
        self.statement = None

    def _get_description(self):
        if self.kind == DML:
            return ()
        desc = []
        for i in xrange(sqlite.sqlite3_column_count(self.statement)):
            name = ffi.string(sqlite.sqlite3_column_name(self.statement, i)).split("[")[0].strip()
            desc.append((name,None))
        return desc



class Row(object):
    def __init__(self, cursor, values):
        self.description = cursor.description
        self.values = values

    def __getitem__(self, item):
        if type(item) is int:
            return self.values[item]
        else:
            item = item.lower()
            for idx, desc in enumerate(self.description):
                if desc[0].lower() == item:
                    return self.values[idx]
            raise KeyError

    def keys(self):
        return [desc[0] for desc in self.description]

    def __eq__(self, other):
        if not isinstance(other, Row):
            return NotImplemented
        if self.description != other.description:
            return False
        if self.values != other.values:
            return False
        return True

    def __ne__(self, other):
        return not self == other

    def __hash__(self):
        return hash(tuple(self.description)) ^ hash(tuple(self.values))

def _check_remaining_sql(s):
    state = "NORMAL"
    for char in s:
        if char == chr(0):
            
            return 0
        elif char == '-':
            if state == "NORMAL":
                state = "LINECOMMENT_1"
            elif state == "LINECOMMENT_1":
                state = "IN_LINECOMMENT"
        elif char in (' ', '\t'):
            pass
        elif char == '\n':
            if state == "IN_LINECOMMENT":
                state = "NORMAL"
        elif char == '/':
            if state == "NORMAL":
                state = "COMMENTSTART_1"
            elif state == "COMMENTEND_1":
                state = "NORMAL"
            elif state == "COMMENTSTART_1":
                return 1
        elif char == '*':
            if state == "NORMAL":
                return 1
            elif state == "LINECOMMENT_1":
                return 1
            elif state == "COMMENTSTART_1":
                state = "IN_COMMENT"
            elif state == "IN_COMMENT":
                state = "COMMENTEND_1"
        else:
            if state == "COMMENTEND_1":
                state = "IN_COMMENT"
            elif state == "IN_LINECOMMENT":
                pass
            elif state == "IN_COMMENT":
                pass
            else:
                return 1
    return 0

_sqlite_to_python=[
None,
lambda x:sqlite.sqlite3_value_int64(x),
lambda x:sqlite.sqlite3_value_double(x),
lambda x:unicode(ffi.string(sqlite.sqlite3_value_text(x)),'utf-8'),
lambda x:buffer(ffi.string(sqlite.sqlite3_value_blob(x))),
lambda x:None]

def _python_unicode_to_sqlite(context, val):
    val, _ = utf_8_encode(val)
    sqresult_text(context, val, -1, SQLITE_TRANSIENT)

_python_to_sqlite={type(u'unicode'): _python_unicode_to_sqlite,
                   type('str'): lambda context,val:sqlite.sqlite3_result_text(context, val, -1, SQLITE_TRANSIENT),
                   type(1): lambda context,val:sqlite.sqlite3_result_int64(context, val),
                   type(sys.maxint+1): lambda context,val:sqlite.sqlite3_result_int64(context, val),
                   type(0.1):  lambda context,val:sqlite.sqlite3_result_double(context, val),
                   type(None): lambda context,val:sqlite.sqlite3_result_null(context),
                   type(True): lambda context,val:sqlite.sqlite3_result_int64(context, int(val)),
                   type(buffer('')): lambda context,val:sqlite.sqlite3_result_blob(context, str(val), len(val), SQLITE_TRANSIENT)}


_sqlite_to_python_statement=[
None,
lambda st, i: sqlite.sqlite3_column_int64(st, i),
lambda st, i:sqlite.sqlite3_column_double(st, i),
lambda st, i:unicode(ffi.string(sqlite.sqlite3_column_text(st, i)),'utf_8'),
lambda st, i:buffer(ffi.string(sqlite.sqlite3_column_blob(st, i))),
lambda st, i:None]



def _convert_params(con, nargs, params):
    _params  = []
    for i in xrange(nargs):
        typ = sqlite.sqlite3_value_type(params[i])
        if typ == SQLITE_INTEGER:
            val = sqlite.sqlite3_value_int64(params[i])
            if -sys.maxint-1 <= val <= sys.maxint:
                val = int(val)
        elif typ == SQLITE_FLOAT:
            val = sqlite.sqlite3_value_double(params[i])
        elif typ == SQLITE_BLOB:
            blob_len = sqlite.sqlite3_value_bytes(params[i])
            blob = sqlite.sqlite3_value_blob(params[i])
            val = buffer(ffi.string(blob))
        elif typ == SQLITE_NULL:
            val = None
        elif typ == SQLITE_TEXT:
            val = sqlite.sqlite3_value_text(params[i])
            # XXX changed from con.text_factory
            val = ffi.string(val)
        else:
            raise NotImplementedError
        _params.append(val)
    return _params

def _convert_result(con, val):
    if val is None:
        sqlite.sqlite3_result_null(con)
    elif isinstance(val, (bool, int, long)):
        sqlite.sqlite3_result_int64(con, int(val))
    elif isinstance(val, str):
        # XXX ignoring unicode issue
        sqlite.sqlite3_result_text(con, val, len(val), SQLITE_TRANSIENT)
    elif isinstance(val, unicode):
        val = val.encode('utf-8')
        sqlite.sqlite3_result_text(con, val, len(val), SQLITE_TRANSIENT)
    elif isinstance(val, float):
        sqlite.sqlite3_result_double(con, val)
    elif isinstance(val, buffer):
        sqlite.sqlite3_result_blob(con, str(val), len(val), SQLITE_TRANSIENT)
    else:
        raise NotImplementedError

def function_callback(real_cb, context, nargs, c_params):

 
    params = _convert_params(context, nargs, c_params)
    try:
        val = real_cb(*params)
    except Exception:
        msg = "user-defined function raised exception"
        sqlite.sqlite3_result_error(context, msg, len(msg))
    else:
        _convert_result(context, val)



converters = {}
adapters = {}

class PrepareProtocol(object):
    pass

def register_adapter(typ, callable):
    adapters[typ, PrepareProtocol] = callable

def register_converter(name, callable):
    converters[name.upper()] = callable

def register_adapters_and_converters():
    def adapt_date(val):
        return val.isoformat()

    def adapt_datetime(val):
        return val.isoformat(" ")

    def convert_date(val):
        return datetime.date(*map(int, val.split("-")))

    def convert_timestamp(val):
        datepart, timepart = val.split(" ")
        year, month, day = map(int, datepart.split("-"))
        timepart_full = timepart.split(".")
        hours, minutes, seconds = map(int, timepart_full[0].split(":"))
        if len(timepart_full) == 2:
            microseconds = int(timepart_full[1])
        else:
            microseconds = 0

        val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds)
        return val


    register_adapter(datetime.date, adapt_date)
    register_adapter(datetime.datetime, adapt_datetime)
    register_converter("date", convert_date)
    register_converter("timestamp", convert_timestamp)

def adapt(val, proto=PrepareProtocol):
    # look for an adapter in the registry
    adapter = adapters.get((type(val), proto), None)
    if adapter is not None:
        return adapter(val)

    # try to have the protocol adapt this object
    if hasattr(proto, '__adapt__'):
        try:
            adapted = proto.__adapt__(val)
        except TypeError:
            pass
        else: 
            if adapted is not None:
                return adapted

    # and finally try to have the object adapt itself
    if hasattr(val, '__conform__'):
        try:
            adapted = val.__conform__(proto)
        except TypeError:
            pass
        else:
            if adapted is not None:
                return adapted

    return val

register_adapters_and_converters()

def OptimizedUnicode(s):
    try:
        val = unicode(s, "ascii").encode("ascii")
    except UnicodeDecodeError:
        val = unicode(s, "utf-8")
    return val
