/* Code generated by script */ #include "sq_sqlite3.h" #include #include #include "lua-regex.h" SQ_OPT_STRING_STRLEN(); const SQChar *SQLite3_TAG = "SQLite3"; static const SQChar *SQLite3_Stmt_TAG = "SQLite3Stmt"; static const SQChar *SQLite3_Blob_TAG = "SQLite3Blob"; static const SQChar sqlite3_NULL_Name[] = _SC("sqlite3_NULL"); static const SQChar nullName[] = _SC("Null"); //return error if parameter exists but is not a blob //return 1 if the parameter exists and is a blob //return 0 if the parameter doesn't exists and creates a new blob static SQRESULT getOptionalBlob(HSQUIRRELVM v, SQInteger idx, SQBlob **blob) { if(sq_gettop(v) >= idx) { if(SQ_FAILED(sq_getinstanceup(v,3,(SQUserPointer*)blob,(SQUserPointer)SQBlob::SQBlob_TAG))) return sq_throwerror(v,_SC("expect a blob as second parameter")); if(!(*blob) || !(*blob)->IsValid()) return sq_throwerror(v,_SC("the blob is invalid")); } else { *blob = new SQBlob(0, 8192); return 0; } return 1; } static SQRESULT sqlite3_NULL_tostring(HSQUIRRELVM v) { sq_pushstring(v, "", 0); return 1; } SQRegFunction sqlite3_NULL_methods[]= { {_SC("_tostring"),sqlite3_NULL_tostring,1, _SC("u")}, {0,0} }; static SQRESULT get_sqlite3_instance(HSQUIRRELVM v, SQInteger idx, sq_sqlite3_sdb **sdb) { SQRESULT _rc_; if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)sdb,(void*)SQLite3_TAG)) < 0) return _rc_; if(!*sdb) return sq_throwerror(v, _SC("database is closed")); return _rc_; } static SQRESULT get_sqlite3_stmt_instance(HSQUIRRELVM v, SQInteger idx, sqlite3_stmt **stmt) { SQRESULT _rc_; if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)stmt,(void*)SQLite3_Stmt_TAG)) < 0) return _rc_; if(!*stmt) return sq_throwerror(v, _SC("statement is closed")); return _rc_; } static SQRESULT get_sqlite3_blob_instance(HSQUIRRELVM v, SQInteger idx, sqlite3_blob **blob) { SQRESULT _rc_; if((_rc_ = sq_getinstanceup(v,idx,(SQUserPointer*)blob,(void*)SQLite3_Blob_TAG)) < 0) return _rc_; if(!*blob) return sq_throwerror(v, _SC("blob is closed")); return _rc_; } //#define push_sqlite3_null(v) sq_getonregistrytable(v, sqlite3_NULL_Name, sizeof(sqlite3_NULL_Name)-1); //#define push_sqlite3_null(v) sq_pushobject(v, sqlite3_NULL); //#define push_sqlite3_null(v) sq_getbyname(v, 1, nullName, sizeof(nullName)-1) //#define push_sqlite3_null(v) sq_pushfromregistrytable(v, nullName, sizeof(nullName)-1) //#define push_sqlite3_null(v) {sq_pushregistrytable(v);sq_pushstring(v, sqlite3_NULL_Name, sizeof(sqlite3_NULL_Name)-1);sq_get(v, -2);sq_remove(v,-2);} //the line bellow is the fastest one, any other attempt till now was slower #define push_sqlite3_null(v) {sq_pushstring(v, nullName, sizeof(nullName)-1);sq_get(v, 1);} #define GET_sqlite3_INSTANCE_AT_VAR(idx, self) \ sq_sqlite3_sdb *sdb=NULL; \ if((_rc_ = get_sqlite3_instance(v,idx,&sdb)) < 0) return _rc_;\ sqlite3 *self = sdb->db; #define GET_sqlite3_INSTANCE_AT(idx) GET_sqlite3_INSTANCE_AT_VAR(idx, self) #define GET_sqlite3_INSTANCE() GET_sqlite3_INSTANCE_AT(1) //#define GET_sqlite3_INSTANCE() SQ_GET_INSTANCE(v, 1, sqlite3, SQLite3_TAG) #define GET_sqlite3_stmt_INSTANCE_AT(idx, var_name) \ sqlite3_stmt *var_name=NULL; \ if((_rc_ = get_sqlite3_stmt_instance(v,idx,&var_name)) < 0) return _rc_; #define GET_sqlite3_stmt_INSTANCE() GET_sqlite3_stmt_INSTANCE_AT(1, self) #define GET_sqlite3_blob_INSTANCE_AT(idx, var_name) \ sqlite3_blob *var_name=NULL; \ if((_rc_ = get_sqlite3_blob_instance(v,idx,&var_name)) < 0) return _rc_; #define GET_sqlite3_blob_INSTANCE() GET_sqlite3_blob_INSTANCE_AT(1, self) enum e_type_result {tr_first_row_first_col, tr_first_row, tr_all_rows, tr_ddml}; #define AS_STRING_ALWAYS 0x01 #define NULL_AS_EMPTY_STR 0x02 #define WITH_COL_NAMES 0x04 #define WITH_BLOB_AS_NULL 0x08 #define WITH_SQ_NULL 0x100 static void sqlite3_stmt_push_string(HSQUIRRELVM v, sqlite3_stmt *stmt, int col, int flags) { const char *value = (const char*) sqlite3_column_text(stmt, col); if(value) sq_pushstring(v, value, sqlite3_column_bytes(stmt, col)); else { if(flags & AS_STRING_ALWAYS) sq_pushliteral(v, ""); else push_sqlite3_null(v); } } static SQRESULT sqlite3_stmt_push_value(HSQUIRRELVM v, sqlite3_stmt *stmt, int col, int flags) { const char *value; int col_type = 0; if(flags & WITH_BLOB_AS_NULL) { col_type = sqlite3_column_type(stmt, col); if(col_type == SQLITE_BLOB) { if(flags & AS_STRING_ALWAYS) sq_pushliteral(v, ""); else push_sqlite3_null(v); return 1; } } if(flags & AS_STRING_ALWAYS) { sqlite3_stmt_push_string(v, stmt, col, flags); } else { if(!col_type) col_type = sqlite3_column_type(stmt, col); switch (col_type) { case SQLITE_INTEGER: { sqlite_int64 i64 = sqlite3_column_int64(stmt, col); SQInteger n = (SQInteger)i64; if (n == i64) sq_pushinteger(v, n); else sq_pushstring(v, (const char*) sqlite3_column_text(stmt, col), sqlite3_column_bytes(stmt, col)); } break; case SQLITE_FLOAT: sq_pushfloat(v, sqlite3_column_double(stmt, col)); break; case SQLITE_TEXT: sqlite3_stmt_push_string(v, stmt, col, flags); break; case SQLITE_BLOB: value = (const char*) sqlite3_column_blob(stmt, col); if(value) sq_pushstring(v, value, sqlite3_column_bytes(stmt, col)); else push_sqlite3_null(v); break; case SQLITE_NULL: if(flags & WITH_SQ_NULL) sq_pushnull(v); else push_sqlite3_null(v); break; default: if(flags & WITH_SQ_NULL) sq_pushnull(v); else push_sqlite3_null(v); break; } } return 1; } static void sqlite3_stmt_row_asArray(HSQUIRRELVM v, sqlite3_stmt *stmt, int flags) { int col_count = sqlite3_column_count(stmt); sq_newarray(v, col_count); for(int i=0; i params_start) { int nparams = sqlite3_bind_parameter_count(stmt); int nparams_given = _top_-params_start; if(nparams != nparams_given) { return sq_throwerror(v, "expect %d parameters but only %d given", nparams, nparams_given); } for(int i=1; i <= nparams; ++i) { int argn = i+params_start; _rc_ = sqlite3_stmt_bind_value(v, stmt, i, argn); if(_rc_ < 0) return _rc_; } } return SQ_OK; } static SQRESULT sq_sqlite3_stmt_prepare_aux(HSQUIRRELVM v, sqlite3 *db, sqlite3_stmt **stmt, int params_start) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_STRING(v, params_start, szSQL); if(sqlite3_prepare_v2(db, szSQL, szSQL_size, stmt, 0) != SQLITE_OK) { return sq_throwerror(v, sqlite3_errmsg(db)); } return sq_sqlite3_stmt_bind_vargv(v, db, *stmt, params_start); } static SQRESULT sq_sqlite3_stmt_releasehook(SQUserPointer p, SQInteger size, void */*ep*/) { sqlite3_stmt *stmt = ((sqlite3_stmt *)p); if(stmt) sqlite3_finalize(stmt); return 0; } static SQRESULT sq_sqlite3_stmt_constructor(HSQUIRRELVM v) { SQ_FUNC_VARS(v); _rc_ = SQ_ERROR; GET_sqlite3_INSTANCE_AT(2); sqlite3_stmt *stmt = 0; if(_top_ > 2) { _rc_ = sq_sqlite3_stmt_prepare_aux(v, self, &stmt, 3); } else { if(sqlite3_prepare_v2(self, "select 'statement not prepared';", -1, &stmt, 0) != SQLITE_OK) { _rc_ = sq_throwerror(v, sqlite3_errmsg(self)); } else _rc_ = SQ_OK; } sq_setinstanceup(v, 1, stmt); //replace self for this instance with this new sqlite3_stmt sq_setreleasehook(v,1, sq_sqlite3_stmt_releasehook); return _rc_; } static SQRESULT sq_sqlite3_stmt_get_db(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sqlite3 *db = sqlite3_db_handle(self); sq_pushuserpointer(v, db); if(sq_getonregistrytable(v) == SQ_OK) { sq_getweakrefval(v, -1); } else return sq_throwerror(v, _SC("could not retrive database, maybe it was already closed")); return 1; } static SQRESULT sq_sqlite3_stmt_stmt_ptr(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushuserpointer(v, self); return 1; } static SQRESULT sq_sqlite3_stmt_finalize(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_setinstanceup(v, 1, 0); //next calls will fail with "statement is closed" //printf("sq_sqlite3_stmt_finalize: %p : %s\n", self, sqlite3_sql(self)); sq_pushinteger(v, sqlite3_finalize(self)); return 1; } static SQRESULT sq_sqlite3_stmt_prepare(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sqlite3 *db = sqlite3_db_handle(self); sqlite3_stmt *stmt = 0; _rc_ = sq_sqlite3_stmt_prepare_aux(v, db, &stmt, 2); if(stmt) { sqlite3_finalize(self); //finalize the previous sqlite3_stmt sq_setinstanceup(v, 1, stmt); //replace self for this instance with this new sqlite3_stmt } return _rc_; } static SQRESULT sq_sqlite3_stmt_get_sql(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushstring(v, sqlite3_sql(self), -1); return 1; } static SQRESULT sq_sqlite3_stmt_bind(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, npar); return sqlite3_stmt_bind_value(v, self, npar, 3); } /** The number/order of fields should be the same to use this function it'll save temporary data convertion. */ static SQRESULT sq_sqlite3_stmt_bind_stmt0(HSQUIRRELVM v, int doExec) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); GET_sqlite3_stmt_INSTANCE_AT(2, stmt_src); int rc = SQLITE_OK, bind_count = sqlite3_bind_parameter_count(self); for(int i=0; i < bind_count; ++i) { rc = sqlite3_bind_value(self, i+1, sqlite3_column_value(stmt_src, i)); if(rc != SQLITE_OK) break; } if(doExec && rc == SQLITE_OK) { rc = sqlite3_step(self); sqlite3_reset(self); } sq_pushinteger(v, rc); return 1; } static SQRESULT sq_sqlite3_stmt_bind_stmt(HSQUIRRELVM v) { return sq_sqlite3_stmt_bind_stmt0(v, 0); } static SQRESULT sq_sqlite3_stmt_bind_exec_stmt(HSQUIRRELVM v) { return sq_sqlite3_stmt_bind_stmt0(v, 1); } static SQRESULT sq_sqlite3_stmt_bind_empty_null(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, npar); if(sq_gettype(v, 3) == OT_STRING && sq_getsize(v, 3) == 0) { sq_pushnull(v); sq_replace(v, 3); } return sqlite3_stmt_bind_value(v, self, npar, 3); } static SQRESULT sq_sqlite3_stmt_bind_blob(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, npar); SQ_GET_STRING(v, 3, blob); if(sqlite3_bind_blob(self, npar, blob, blob_size, SQLITE_TRANSIENT) != SQLITE_OK) { sqlite3 *db = sqlite3_db_handle(self); return sq_throwerror(v, sqlite3_errmsg(db)); } return SQ_OK; } static SQRESULT sq_sqlite3_stmt_bind_zeroblob(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, npar); SQ_GET_INTEGER(v, 3, nsize); if(sqlite3_bind_zeroblob(self, npar, nsize)) { sqlite3 *db = sqlite3_db_handle(self); return sq_throwerror(v, sqlite3_errmsg(db)); } return SQ_OK; } static SQRESULT sq_sqlite3_stmt_bind_values0(HSQUIRRELVM v, int isExec) { SQ_FUNC_VARS(v); GET_sqlite3_stmt_INSTANCE(); if (_top_ - 1 != sqlite3_bind_parameter_count(self)) return sq_throwerror(v, _SC("incorrect number of parameters to bind (%d given, %d to bind)"), _top_ - 1, sqlite3_bind_parameter_count(self)); for (int n = 2; n <= _top_; ++n) { if (sqlite3_stmt_bind_value(v, self, n-1, n) != SQ_OK) return SQ_ERROR; } if(isExec) { int rc = sqlite3_step(self); sqlite3_reset(self); sq_pushinteger(v, rc); return 1; } return 0; } static SQRESULT sq_sqlite3_stmt_bind_values(HSQUIRRELVM v) { return sq_sqlite3_stmt_bind_values0(v, 0); } static SQRESULT sq_sqlite3_stmt_bind_exec(HSQUIRRELVM v) { return sq_sqlite3_stmt_bind_values0(v, 1); } static SQRESULT sq_sqlite3_stmt_bind_exec_get_one(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQInteger rc = sq_sqlite3_stmt_bind_values0(v, 0); if(rc != SQ_OK) return rc; sq_getinteger(v, -1, &rc); if(rc == SQLITE_OK) { rc = sqlite3_step(self); if(rc == SQLITE_ROW) sqlite3_stmt_push_value(v, self, 0, 0); else sq_pushnull(v); sqlite3_reset(self); } else sq_pushnull(v); return 1; } static SQRESULT sq_sqlite3_stmt_bind_exec_get_first_row(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQInteger rc = sq_sqlite3_stmt_bind_values0(v, 0); if(rc != SQ_OK) return rc; sq_getinteger(v, -1, &rc); if(rc == SQLITE_OK) { rc = sqlite3_step(self); if(rc == SQLITE_ROW) sqlite3_stmt_row_asArray(v, self, NULL_AS_EMPTY_STR|AS_STRING_ALWAYS); else sq_pushnull(v); sqlite3_reset(self); } else sq_pushnull(v); return 1; } static SQRESULT sq_sqlite3_stmt_bind_names(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQObjectType ptype = sq_gettype(v, 2); int count = sqlite3_bind_parameter_count(self); int result; for (int n = 1; n <= count; ++n) { const char *name = sqlite3_bind_parameter_name(self, n); if (name && (name[0] == ':' || name[0] == '$' || name[0] == '@')) { if(ptype == OT_TABLE) { sq_pushstring(v, ++name, -1); if(sq_get(v, 2) == SQ_OK) { result = sqlite3_stmt_bind_value(v, self, n, -1); sq_poptop(v); } else return sq_throwerror(v, _SC("bind parameter (%s) not found"), name); } else return sq_throwerror(v, _SC("table expected to bind named parameters")); } else { if(ptype == OT_ARRAY) { sq_pushinteger(v, n); if(sq_get(v, 2) == SQ_OK) { result = sqlite3_stmt_bind_value(v, self, n, -1); sq_poptop(v); } else return sq_throwerror(v, _SC("bind parameter (%d) not found"), n); } else return sq_throwerror(v, _SC("array expected to bind numbered parameters")); } if (result != SQ_OK) return result; } return 0; } static SQRESULT sq_sqlite3_stmt_bind_parameter_index(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_STRING(v, 2, spar); sq_pushinteger(v, sqlite3_bind_parameter_index(self, spar)); return 1; } static SQRESULT sq_sqlite3_stmt_bind_parameter_count(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushinteger(v, sqlite3_bind_parameter_count(self)); return 1; } static SQRESULT sq_sqlite3_stmt_reset(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushinteger(v, sqlite3_reset(self)); return 1; } static SQRESULT sq_sqlite3_stmt_step(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushinteger(v, sqlite3_step(self)); return 1; } static SQRESULT sq_sqlite3_stmt_next_row(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushbool(v, sqlite3_step(self) == SQLITE_ROW); return 1; } static SQRESULT sq_sqlite3_stmt_col_count(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); sq_pushinteger(v, sqlite3_column_count(self)); return 1; } static SQRESULT sq_sqlite3_stmt_col_name(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, col); sq_pushstring(v, sqlite3_column_name(self, col), -1); return 1; } static SQRESULT sq_sqlite3_stmt_col_type(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, col); sq_pushinteger(v, sqlite3_column_type(self, col)); return 1; } static const char *get_column_type(sqlite3_stmt *stmt, int col) { const char *column_type; int icol_type = sqlite3_column_type(stmt, col); switch(icol_type) { case SQLITE_INTEGER: column_type = "INTEGER"; break; case SQLITE_FLOAT: column_type = "FLOAT"; break; case SQLITE_BLOB: column_type = "BLOB"; break; case SQLITE_TEXT: column_type = "TEXT"; break; case SQLITE_NULL: column_type = "NULL"; break; default: column_type = "unknown"; } return column_type; } static const char *get_column_dcltype(sqlite3_stmt *stmt, int col) { const char *column_type = sqlite3_column_decltype(stmt, col); if(!column_type) column_type = get_column_type(stmt, col); return column_type; } static SQRESULT sq_sqlite3_stmt_col_declared_type(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); SQ_GET_INTEGER(v, 2, col); sq_pushstring(v, get_column_dcltype(self, col), -1); return 1; } static SQRESULT sq_sqlite3_stmt_colsAsArray(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col_count = sqlite3_column_count(self); sq_newarray(v, col_count); for(int i=0; i start_pos) { int space_left = col_size - start_pos; sq_pushstring(v, value + start_pos, (space_left > size) ? size : space_left); } else value = NULL; } if(!value) push_sqlite3_null(v); return 1; } static SQRESULT sq_sqlite3_stmt_asBool(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col = get_col_index(v, self); if(col < 0) return col; const unsigned char *b = sqlite3_column_text(self, col); sq_pushbool(v, b && *b == '1'); return 1; } static SQRESULT sq_sqlite3_stmt_asInteger(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col = get_col_index(v, self); if(col < 0) return col; sq_pushinteger(v, sqlite3_column_int64(self, col)); return 1; } static SQRESULT sq_sqlite3_stmt_asFloat(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col = get_col_index(v, self); if(col < 0) return col; sq_pushfloat(v, sqlite3_column_double(self, col)); return 1; } static SQRESULT sq_sqlite3_stmt_StringOrNull(HSQUIRRELVM v, int withNull) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col = get_col_index(v, self); if(col < 0) return col; sqlite3_stmt_push_string(v, self, col, withNull ? 0 : NULL_AS_EMPTY_STR); return 1; } static SQRESULT sq_sqlite3_stmt_asString(HSQUIRRELVM v) { return sq_sqlite3_stmt_StringOrNull(v, 0); } static SQRESULT sq_sqlite3_stmt_asStringOrNull(HSQUIRRELVM v) { return sq_sqlite3_stmt_StringOrNull(v, 1); } static SQRESULT sq_sqlite3_stmt_asTable(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_stmt_INSTANCE(); SQ_OPT_INTEGER(v, 2, flags, 0); sqlite3_stmt_row_asTable(v, self, flags); return 1; } static SQRESULT sq_sqlite3_stmt_asArray(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_stmt_INSTANCE(); SQ_OPT_INTEGER(v, 2, flags, 0); sqlite3_stmt_row_asArray(v, self, flags); return 1; } static SQRESULT sq_sqlite3_stmt_asArrayOfArrays(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_stmt_INSTANCE(); SQ_OPT_INTEGER(v, 2, flags, 0); sqlite3_stmt_asArrayOfArrays(v, self, flags); sqlite3_reset(self); return 1; } static SQRESULT sq_sqlite3_stmt_asArrayOfTables(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_stmt_INSTANCE(); SQ_OPT_INTEGER(v, 2, flags, 0); sqlite3_stmt_asArrayOfTables(v, self, flags); sqlite3_reset(self); return 1; } /*utility functions*/ static void append_escaping_json(SQBlob &json, const char *sz) { if(sz) //escape string { int last_idx, idx; idx = last_idx = 0; for(; sz[idx]; ++idx) { char c = sz[idx]; switch(c) { case '"': case '\n': case '\r': case '\t': case '\b': case '\f': case '\\': { json.Write(sz+last_idx, idx-last_idx); last_idx = idx; if(c == '\n') { json.Write("\\n", 2); ++last_idx; } else if(c == '\t') { json.Write("\\t", 2); ++last_idx; } else if(c == '\b') { json.Write("\\b", 2); ++last_idx; } else if(c == '\f') { json.Write("\\f", 2); ++last_idx; } else if(c == '\r') { json.Write("\\r", 2); ++last_idx; } else { json.Write("\\", 1); } } } } //last part json.Write(sz+last_idx, idx-last_idx); } } static SQRESULT sq_sqlite3_stmt_asJsonArray(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_stmt_INSTANCE(); SQ_OPT_BOOL(v, 2, withMetadata, 0); int col_count = sqlite3_column_count(self); int i, value_type; const char* value; SQBlob *json = NULL; int has_blob = getOptionalBlob(v, 3, &json); if(has_blob == SQ_ERROR) return SQ_ERROR; if(withMetadata) { json->WriteZstr("{\n\"columns\":[\n"); for(i=0; i < col_count; ++i) { json->WriteZstr((i == 0 ? "\"" : ",\"")); const char *column_name = sqlite3_column_name(self, i); json->WriteZstr(column_name ? column_name : "unknown"); json->WriteZstr("\""); } json->WriteZstr("\n],\n\"column_types\":[\n"); for(i=0; i < col_count; ++i) { json->WriteZstr((i == 0 ? "\"" : ",\"")); json->WriteZstr(get_column_dcltype(self, i)); json->WriteZstr("\""); } json->WriteZstr("\n],\n\"rows\":[\n"); } else { json->WriteZstr("[\n"); } int row_count = 0; while(sqlite3_step(self) == SQLITE_ROW) { json->WriteZstr((row_count++ == 0 ? "[" : ",[")); for(i=0; i < col_count; ++i) { json->WriteZstr((i == 0 ? "\"" : ",\"")); //if get the type after sqlite3_column_text it always returns SQLITE_TEXT value_type = sqlite3_column_type(self, i); value = (const char*)sqlite3_column_text(self, i); if(value) { switch(value_type) { case SQLITE_BLOB: break; //no blobs in json case SQLITE_TEXT: { append_escaping_json(*json, value); } break; default: json->WriteZstr(value); } } json->WriteZstr("\""); } json->WriteZstr("]\n"); } json->WriteZstr("]"); if(withMetadata) json->WriteZstr("\n}"); if(has_blob) return 0; sq_pushstring(v, (const SQChar*)json->GetBuf(), json->Len()); delete json; return 1; } static SQRESULT sq_sqlite3_stmt_asJsonObject(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col_count = sqlite3_column_count(self); int i, value_type, record_count = 0; const char* value; SQBlob *json = NULL; int has_blob = getOptionalBlob(v, 2, &json); if(has_blob == SQ_ERROR) return SQ_ERROR; json->WriteZstr("{"); if(sqlite3_step(self) == SQLITE_ROW) { ++record_count; for(i=0; i < col_count; ++i) { json->WriteZstr((i == 0 ? "\"" : "\",\"")); append_escaping_json(*json, (const char*)sqlite3_column_name(self, i)); json->WriteZstr("\":\""); //if get the type after sqlite3_column_text it always returns SQLITE_TEXT value_type = sqlite3_column_type(self, i); value = (const char*)sqlite3_column_text(self, i); if(value) { switch(value_type) { case SQLITE_BLOB: break; //no blobs in json case SQLITE_TEXT: { append_escaping_json(*json, value); } break; default: json->WriteZstr(value); } } } json->WriteZstr("\""); } json->WriteZstr("}"); if(has_blob) return 0; if(record_count) sq_pushstring(v, (const SQChar*)json->GetBuf(), json->Len()); else sq_pushnull(v); delete json; return 1; } #define UNSIGNED(n) n##U #define IBYTE_MAX UNSIGNED(256) #define IBYTE1 UNSIGNED(240) #define IBYTE2 UNSIGNED(2287) #define IBYTE3 UNSIGNED(67823) #define IBYTE4 UNSIGNED(16777215) #define SLEMARK 254 #define SLEEND 255 static SQRESULT sle2array(HSQUIRRELVM v, const unsigned char *p, size_t sle_size, const unsigned char **next) { size_t size, data_len = 0; if(sle_size == 0) { *next = 0; return 0; } while(*p != SLEEND) //data finished now follow digest { size = *p++; if(size > IBYTE1) { if(size <= 248) { size = (size-241)*IBYTE_MAX + (*p++) + IBYTE1; } else if(size == 249) { size = 2288 + (IBYTE_MAX * (*p++)) + (*p++); } else if(size == 250) { size = ((*p++)<<16) + ((*p++)<<8) + (*p++); } else if(size == 251) { size = ((*p++)<<24) + ((*p++)<<16) + ((*p++)<<8) + (*p++); } else if(size == SLEMARK) { //reserved can be used for multi part data, metadata, digest, ... break; } } sq_pushstring(v, (const char*)p, size); sq_arrayappend(v, -2); p += size; data_len += size; if(data_len > sle_size) { //something went wrong here return sq_throwerror(v, "We got more data than expected !"); } } *next = ++p; return 0; } static SQRESULT sle2vec(HSQUIRRELVM v, const unsigned char *sle, size_t sle_size, const unsigned char **next) { int rc; sq_newarray(v, 0); if(sle[0] != '[') { return sq_throwerror(v, "Invalid encoded vector !"); } if(sle[1] == ']') { *next = sle+2; //empty array return 0; } if((rc = sle2array(v, sle+1, sle_size-1, next)) < 0) return rc; if(!*next || *next[0] != ']') { return sq_throwerror(v, "Invalid end of vector !"); } (*next)++; return 0; } static SQRESULT sq_sle2vecOfvec(HSQUIRRELVM v) { SQ_FUNC_VARS(v); SQBlob *blob = NULL; const SQChar *sle, *sle_start; SQInteger sle_size; SQObjectType ptype = sq_gettype(v, 2); switch(ptype) { case OT_STRING: sq_getstr_and_size(v, 2, &sle, &sle_size); break; case OT_INSTANCE: if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&blob,(SQUserPointer)SQBlob::SQBlob_TAG))) return sq_throwerror(v,_SC("invalid type tag")); if(!blob || !blob->IsValid()) return sq_throwerror(v,_SC("the blob is invalid")); sle = (const SQChar*)blob->GetBuf(); sle_size = blob->Len(); break; default: return sq_throwerror(v,_SC("invalid parameter 1 of type %s"), sq_gettypename(v, 2)); } if(sq_gettype(v, 3) != OT_ARRAY) return sq_throwerror(v,_SC("invalid parameter 2 of type %s"), sq_gettypename(v, 3)); SQ_OPT_INTEGER(v, 4, start, 0); if(start < 0) return sq_throwerror(v, _SC("invalid start position (%d)"), start); sq_push(v, 3); int rc, data_count = 1; const unsigned char *next; sle_start = sle + start; sle_size -= start; if(sle_start[0] != '[') { return sq_throwerror(v, "Invalid encoded vector !"); } if(sle_start[1] == ']') { //sq_pushinteger(v, start+2); return 1; //empty array } int saved_top = sq_gettop(v); if((rc=sle2vec(v, (const unsigned char *)sle_start+1, sle_size-1, &next)) < 0) return rc; while(next && *next == '[') { sq_arrayappend(v, -2); data_count++; if((rc=sle2vec(v, next, sle_size - (next - (const unsigned char *)sle_start), &next)) < 0) return rc; } if(sq_gettop(v) != saved_top) { //last added table left sq_arrayappend(v, -2); data_count++; } if(!next || *next != ']') { return sq_throwerror(v, "Invalid end of vector !"); } sq_pushinteger(v, ((const SQChar*)(++next)) - sle); return 1; } typedef unsigned char slebuf_t[8]; static int sleSize2buf(slebuf_t sle, size_t size) { size_t next_size; if(size <= IBYTE1) { sle[0] = size; return 1; } else if(size <= IBYTE2) { next_size = size - IBYTE1; sle[0] = next_size/IBYTE_MAX + 241; sle[1] = next_size%IBYTE_MAX; return 2; } else if(size <= IBYTE3) { sle[0] = 249; next_size = size - 2288; sle[1] = next_size/IBYTE_MAX; sle[2] = next_size%IBYTE_MAX; return 3; } else if(size <= IBYTE4) { sle[0] = 250; sle[1] = size >> 16; sle[2] = size >> 8; sle[3] = size; return 4; } else { sle[0] = 251; sle[1] = size >> 24; sle[2] = size >> 16; sle[3] = size >> 8; sle[4] = size; return 5; } return 0; } static SQRESULT sq_get_sle_size(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); slebuf_t slebuf; SQ_GET_INTEGER(v, 2, size); int slesize = sleSize2buf(slebuf, size); if(slesize) { sq_pushstring(v, (const char *)slebuf, slesize); return 1; } return 0; } static int add2sle(SQBlob &sle, const char *str, size_t size) { slebuf_t slebuf; int slesize = sleSize2buf(slebuf, size); if(slesize) sle.Write((const char *)slebuf, slesize); if(size) sle.Write(str, size); return size; } static SQRESULT sq_add2sle(HSQUIRRELVM v) { SQ_FUNC_VARS(v); SQ_GET_INSTANCE_VAR(v, 2, SQBlob, blob, SQBlob::SQBlob_TAG); SQ_GET_STRING(v, 3, str); SQ_OPT_INTEGER(v, 4, size, str_size); if(size < 0) return sq_throwerror(v, _SC("invalid size value (%d)"), size); sq_pushinteger(v, add2sle(*blob, str, size)); return 1; } static SQRESULT sq_sqlite3_stmt_asSleArray(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col_count = sqlite3_column_count(self); int i; const char *value; SQBlob *sle = NULL; int has_blob = getOptionalBlob(v, 2, &sle); if(has_blob == SQ_ERROR) return SQ_ERROR; sle->WriteZstr("[["); for(i=0; i < col_count; ++i) { value = sqlite3_column_name(self, i); add2sle(*sle, value, strlen(value)); } sle->WriteChar(SLEEND); sle->WriteChar(']'); while(sqlite3_step(self) == SQLITE_ROW) { sle->WriteChar('['); for(i=0; i < col_count; ++i) { switch(sqlite3_column_type(self, i)) { case SQLITE_BLOB: { add2sle(*sle, (const char*)sqlite3_column_blob(self, i), sqlite3_column_bytes(self, i)); } break; default: add2sle(*sle, (const char*)sqlite3_column_text(self, i), sqlite3_column_bytes(self, i)); } } sle->WriteChar(SLEEND); sle->WriteChar(']'); } sle->WriteChar(']'); if(has_blob) return 0; sq_pushstring(v, (const SQChar*)sle->GetBuf(), sle->Len()); delete sle; return 1; } static SQRESULT sq_sqlite3_stmt_all_blobs_size(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int total_size = 0, col_count = sqlite3_column_count(self); for(int i=0; i < col_count; ++i) { if(sqlite3_column_type(self, i) == SQLITE_BLOB) { total_size += sqlite3_column_bytes(self, i); } } sq_pushinteger(v, total_size); return 1; } static SQRESULT sq_sqlite3_stmt_colsSizeAsArray(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_stmt_INSTANCE(); int col_count = sqlite3_column_count(self); sq_newarray(v, col_count); for(int i=0; icapture[i].len; if(len == CAP_POSITION) sqlite3_result_int(context, ms->capture[i].init - ms->src_init); else sqlite3_result_text(context, ms->capture[0].init, ms->capture[0].len, SQLITE_TRANSIENT); } static void sqlite3_lua_find_base( sqlite3_context *context, int argc, sqlite3_value **argv, int funcType ) { assert(argc == 2); LuaMatchState ms; int isRegexp = funcType == FUNC_IS_REGEXP; const char *pattern = (const char *)sqlite3_value_text(argv[isRegexp ? 0 : 1]); const char *subject = (const char *)sqlite3_value_text(argv[isRegexp ? 1 : 0]); assert(argc == 2); if(!subject || !pattern){ sqlite3_result_null(context); return; } size_t pattern_len = strlen(pattern); size_t subject_len = strlen(subject); switch(funcType) { case FUNC_IS_MATCH: { ptrdiff_t rc = lua_str_match(&ms, subject, subject_len, pattern, pattern_len, 0, 0, 0, 0); if(ms.error) sqlite3_result_error(context, ms.error, strlen(ms.error)); else if(rc < 0) sqlite3_result_null(context); else if(ms.level){ if(ms.level == 1) push_match_capture(context, 0, &ms); else { //no way to differentiate more than one match push_match_capture(context, 0, &ms); } } else { sqlite3_result_text(context, subject + ms.start_pos, ms.end_pos-ms.start_pos+1, SQLITE_TRANSIENT); } } break; case FUNC_IS_FIND_COUNT: { int count = 0; ms.end_pos = 0; ptrdiff_t idx = -1; while((idx = lua_str_find(&ms, subject, subject_len, pattern, pattern_len, ms.end_pos, 0, 0, 0)) >= 0) ++count; sqlite3_result_int(context, count); } break; case FUNC_IS_FIND: case FUNC_IS_REGEXP: { ptrdiff_t idx = lua_str_find(&ms, subject, subject_len, pattern, pattern_len, 0, 0, NULL, NULL); if(idx >= 0) { sqlite3_result_int(context, funcType == FUNC_IS_FIND ? idx : 1); } else { if(ms.error) sqlite3_result_error(context, ms.error, strlen(ms.error)); else sqlite3_result_int(context, funcType == FUNC_IS_FIND ? idx : 0); } } break; } } static void sqlite3_lua_regexp( sqlite3_context *context, int argc, sqlite3_value **argv ) { sqlite3_lua_find_base(context, argc, argv, FUNC_IS_REGEXP); } static void sqlite3_lua_find( sqlite3_context *context, int argc, sqlite3_value **argv ) { sqlite3_lua_find_base(context, argc, argv, FUNC_IS_FIND); } static void sqlite3_lua_find_count( sqlite3_context *context, int argc, sqlite3_value **argv ) { sqlite3_lua_find_base(context, argc, argv, FUNC_IS_FIND_COUNT); } static void sqlite3_lua_match( sqlite3_context *context, int argc, sqlite3_value **argv ) { sqlite3_lua_find_base(context, argc, argv, FUNC_IS_MATCH); } static void sqlite3_lua_gsub( sqlite3_context *context, int argc, sqlite3_value **argv ) { assert(argc == 4); lua_char_buffer_st *result; const char *error_ptr; const char *subject = (const char *)sqlite3_value_text(argv[0]); const char *pattern = (const char *)sqlite3_value_text(argv[1]); const char *replacement = (const char *)sqlite3_value_text(argv[2]); int ntimes = sqlite3_value_int(argv[3]); if(ntimes < 0) ntimes = 0; if(!subject || !pattern || !replacement){ sqlite3_result_null(context); return; } result = lua_str_gsub(subject, strlen(subject), pattern, strlen(pattern), replacement, strlen(replacement), ntimes, &error_ptr, NULL, NULL); if(result){ sqlite3_result_text(context, result->buf, result->used, SQLITE_TRANSIENT); free(result); } else sqlite3_result_error(context, error_ptr, strlen(error_ptr)); } int set_sqlite3_lua_regex_func(sqlite3 *db) { int nErr = sqlite3_create_function(db, "lua_find", 2, SQLITE_UTF8, 0, sqlite3_lua_find, 0, 0); nErr += sqlite3_create_function(db, "lua_find_count", 2, SQLITE_UTF8, 0, sqlite3_lua_find_count, 0, 0); nErr += sqlite3_create_function(db, "lua_match", 2, SQLITE_UTF8, 0, sqlite3_lua_match, 0, 0); nErr += sqlite3_create_function(db, "lua_gsub", 4, SQLITE_UTF8, 0, sqlite3_lua_gsub, 0, 0); nErr += sqlite3_create_function(db, "lua_regexp", 2, SQLITE_UTF8, 0, sqlite3_lua_regexp, 0, 0); return nErr ? SQLITE_ERROR : SQLITE_OK; } static SQRESULT sq_sqlite3_close_release(HSQUIRRELVM v, sq_sqlite3_sdb *sdb) { SQRESULT rc = SQ_ERROR; //printf("sq_sqlite3_close_release:%p\n", sdb); if(sdb && sdb->db) { sqlite3 *db = sdb->db; sdb->db = NULL; //prevent double entry/free, see sq_pushregistrytable(sdb->v) bellow /* sqlite3_stmt* statement = NULL; int count = 0; while ((statement = sqlite3_next_stmt(db, NULL))) { printf("sq_sqlite3_close_release:stmt: %p : %s\n", statement, sqlite3_sql(statement)); sqlite3_finalize(statement); statement = c; count++; } if (count) return sq_throwerror(v, _SC("closing database with %d statements not closed."), count); */ int close_rc = sqlite3_close_v2(db) == SQLITE_OK; if(!v || (v && close_rc)) { rc = SQ_OK; //remove waekref from registrytable //printf("Closing %s\n", sqlite3_db_filename(db, "main")); sq_delete_on_registry_table(sdb->v, db); if(sdb->func) { sq_sqlite3_sdb_func *func, *func_next; func = sdb->func; while (func) { func_next = func->next; sq_release(sdb->v, &func->fn_step); sq_release(sdb->v, &func->fn_finalize); sq_release(sdb->v, &func->udata); sq_free(func, sizeof(sq_sqlite3_sdb_func)); func = func_next; } sdb->func = NULL; } /* 'free' all references */ sq_release(sdb->v, &sdb->busy_cb); sq_release(sdb->v, &sdb->busy_udata); sq_release(sdb->v, &sdb->progress_cb); sq_release(sdb->v, &sdb->progress_udata); sq_release(sdb->v, &sdb->trace_cb); sq_release(sdb->v, &sdb->trace_udata); sq_release(sdb->v, &sdb->update_hook_cb); sq_release(sdb->v, &sdb->update_hook_udata); sq_release(sdb->v, &sdb->authorizer_hook_cb); sq_release(sdb->v, &sdb->authorizer_hook_udata); sq_release(sdb->v, &sdb->null_value); sq_free(sdb, sizeof(sq_sqlite3_sdb)); } else { if(v) return sq_throwerror(v, sqlite3_errmsg(db)); } } return rc; } static SQRESULT sq_sqlite3_releasehook(SQUserPointer p, SQInteger size, void */*ep*/) { sq_sqlite3_sdb *sdb = ((sq_sqlite3_sdb *)p); sq_sqlite3_close_release(0, sdb); return 0; } static SQRESULT sq_sqlite3_constructor(HSQUIRRELVM v) { SQ_FUNC_VARS(v); SQ_GET_STRING(v, 2, dbname); SQ_OPT_INTEGER(v, 3, flags, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE | SQLITE_OPEN_SUBLATIN_NA_LIKE); //SQ_OPT_INTEGER(v, 3, flags, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE); sqlite3 *db; int rc = sqlite3_open_v2(dbname, &db, flags, 0); if(rc != SQLITE_OK) return sq_throwerror(v, "Failed to open database ! %d", rc); set_sqlite3_lua_regex_func(db); sq_sqlite3_sdb *sdb = (sq_sqlite3_sdb *)sq_malloc(sizeof(sq_sqlite3_sdb)); memset(sdb, 0, sizeof(sq_sqlite3_sdb)); sdb->db = db; sdb->v = v; sq_resetobject(&sdb->busy_cb); sq_resetobject(&sdb->busy_udata); sq_resetobject(&sdb->progress_cb); sq_resetobject(&sdb->progress_udata); sq_resetobject(&sdb->trace_cb); sq_resetobject(&sdb->trace_udata); sq_resetobject(&sdb->update_hook_cb); sq_resetobject(&sdb->update_hook_udata); sq_resetobject(&sdb->authorizer_hook_cb); sq_resetobject(&sdb->authorizer_hook_udata); sq_resetobject(&sdb->null_value); sq_setinstanceup(v, 1, sdb); sq_setreleasehook(v,1, sq_sqlite3_releasehook); //save a weakref to allow statement return it's db sq_pushuserpointer(v, sdb->db); sq_weakref(v, 1); sq_setonregistrytable(v); return 1; } static SQRESULT sq_sqlite3_close(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); if(sq_sqlite3_close_release(v, sdb) != SQ_OK) return SQ_ERROR; sq_setinstanceup(v, 1, 0); //next calls will fail with "database is closed" return 0; } static SQRESULT sq_sqlite3_db_ptr(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushuserpointer(v, self); return 1; } /* bool IsAutoCommitOn( ) */ static SQRESULT sq_sqlite3_IsAutoCommitOn(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushbool(v, sqlite3_get_autocommit(self) ? SQTrue : SQFalse); return 1; } /* int changes( ) */ static SQRESULT sq_sqlite3_changes(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushinteger(v, sqlite3_changes(self)); return 1; } static SQRESULT sq_sqlite3_exec(HSQUIRRELVM v) { return sqlite3_exec_fmt(v, tr_all_rows); } /* int exec_one_dml( const char * szSQL, ... ) */ static SQRESULT sq_sqlite3_exec_one_dml(HSQUIRRELVM v) { return sqlite3_exec_fmt(v, tr_ddml); } /* int exec_dml( const char * szSQL ) */ static SQRESULT sq_sqlite3_exec_dml(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, szSQL); char *errmsg; if(sqlite3_exec(self, szSQL, NULL, NULL, &errmsg) != SQLITE_OK){ sq_throwerror(v, errmsg); sqlite3_free(errmsg); return SQ_ERROR; } sq_pushinteger(v, sqlite3_changes(self)); return 1; } /* bool exec_get_one( std::string & result , const char * szSQL ) */ static SQRESULT sq_sqlite3_exec_get_one(HSQUIRRELVM v) { return sqlite3_exec_fmt(v, tr_first_row_first_col); } static SQRESULT sq_sqlite3_exec_get_first_row(HSQUIRRELVM v) { return sqlite3_exec_fmt(v, tr_first_row); } /* const char * get_db_name( ) */ static SQRESULT sq_sqlite3_get_db_name(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushstring(v, sqlite3_db_filename(self, "main"), -1); return 1; } /* sqlite3_int64 last_row_id( ) */ static SQRESULT sq_sqlite3_last_row_id(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushinteger(v, sqlite3_last_insert_rowid(self)); return 1; } /* stmt * prepare( const char * sql ) */ static SQRESULT sq_sqlite3_prepare(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); //GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, sql); sq_pushstring(v, SQLite3_Stmt_TAG, -1); if(sq_getonroottable(v) == SQ_ERROR) return SQ_ERROR; sq_pushroottable(v); sq_push(v, 1); sq_push(v, 2); if(sq_call(v, 3, SQTrue, SQFalse) != SQ_OK) return SQ_ERROR; return 1; } //sqlite3_blob static SQRESULT sq_sqlite3_blob_releasehook(SQUserPointer p, SQInteger size, void */*ep*/) { sqlite3_blob *self = ((sqlite3_blob *)p); if(self) sqlite3_blob_close(self); return 0; } static SQRESULT sq_sqlite3_blob_close(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_blob_INSTANCE(); sq_setinstanceup(v, 1, 0); //next calls will fail with "blob is closed" sq_pushinteger(v, sqlite3_blob_close(self)); return 1; } static SQRESULT sq_sqlite3_blob_reopen(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_blob_INSTANCE(); SQ_GET_INTEGER(v, 2, iRow); int rc = sqlite3_blob_reopen(self, iRow); if(rc != SQLITE_OK) return sq_sqlite3_blob_close(v); sq_pushinteger(v, rc); return 1; } static SQRESULT sq_sqlite3_blob_bytes(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_blob_INSTANCE(); sq_pushinteger(v, sqlite3_blob_bytes(self)); return 1; } static SQRESULT sq_sqlite3_blob_read(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_blob_INSTANCE(); SQ_OPT_INTEGER(v, 2, size, 0); SQ_OPT_INTEGER(v, 3, offset, 0); if(!size) size = sqlite3_blob_bytes(self); SQChar *buf = sq_getscratchpad(v, size); int rc = sqlite3_blob_read(self, buf, size, offset); if(rc == SQLITE_OK) sq_pushstring(v, buf, size); else sq_pushnull(v); return 1; } static SQRESULT sq_sqlite3_blob_write(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_blob_INSTANCE(); SQ_GET_STRING(v, 2, buf); SQ_OPT_INTEGER(v, 3, size, buf_size); SQ_OPT_INTEGER(v, 4, offset, 0); int rc = sqlite3_blob_write(self, buf, size, offset); sq_pushinteger(v, rc); return 1; } static SQRESULT sq_sqlite3_blob_open(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, zDb); SQ_GET_STRING(v, 3, zTable); SQ_GET_STRING(v, 4, zColumn); SQ_GET_INTEGER(v, 5, iRow); SQ_OPT_INTEGER(v, 6, flags, 0); sqlite3_blob *pBlob; int rc = sqlite3_blob_open(self, zDb, zTable, zColumn, iRow, flags, &pBlob); if(rc == SQLITE_OK) { sq_pushstring(v, SQLite3_Blob_TAG, -1); if(sq_getonregistrytable(v) == SQ_ERROR) return SQ_ERROR; sq_createinstance(v, -1); sq_setinstanceup(v, -1, pBlob); sq_setreleasehook(v, -1, sq_sqlite3_blob_releasehook); } else sq_pushnull(v); return 1; } #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_sqlite3_blob_##name,nparams,tycheck} static SQRegFunction sq_sqlite3_blob_methods[] = { _DECL_FUNC(close, 1, _SC("x")), _DECL_FUNC(reopen, 2, _SC("xi")), _DECL_FUNC(bytes, 1, _SC("x")), _DECL_FUNC(read, -1, _SC("xii")), _DECL_FUNC(write, -2, _SC("xsii")), {0,0} }; #undef _DECL_FUNC /* void set_busy_timeout( int nMillisecs ) */ static SQRESULT sq_sqlite3_set_busy_timeout(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); //GET_sqlite3_INSTANCE(); SQ_GET_INTEGER(v, 2, nMillisecs); //self->set_busy_timeout(nMillisecs); return 0; } /* int total_changes( ) */ static SQRESULT sq_sqlite3_total_changes(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushinteger(v, sqlite3_total_changes(self)); return 1; } static SQRESULT sq_sqlite3_enable_shared_cache(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_BOOL(v, 2, bhow); sq_pushbool(v, sqlite3_enable_shared_cache(bhow) == SQLITE_OK); return 1; } static SQRESULT sq_sqlite3_sleep(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQ_GET_INTEGER(v, 2, n); sqlite3_sleep(n); return 0; } static SQRESULT sq_sqlite3_version(HSQUIRRELVM v) { sq_pushstring(v, sqlite3_libversion(), -1); return 1; } static SQRESULT sq_sqlite3_threadsafe(HSQUIRRELVM v) { sq_pushinteger(v, sqlite3_threadsafe()); return 1; } static SQRESULT sq_sqlite3_config_single_thread(HSQUIRRELVM v) { sq_pushinteger(v, sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)); return 1; } static SQRESULT sq_sqlite3_config_multi_thread(HSQUIRRELVM v) { sq_pushinteger(v, sqlite3_config(SQLITE_CONFIG_MULTITHREAD)); return 1; } static SQRESULT sq_sqlite3_config_serialized(HSQUIRRELVM v) { sq_pushinteger(v, sqlite3_config(SQLITE_CONFIG_SERIALIZED)); return 1; } static SQRESULT sq_sqlite3_errcode(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushinteger(v, sqlite3_errcode(self)); return 1; } static SQRESULT sq_sqlite3_errmsg(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sq_pushstring(v, sqlite3_errmsg(self), -1); return 1; } #ifndef WIN32 static SQRESULT sq_sqlite3_temp_directory(HSQUIRRELVM v) { SQ_FUNC_VARS(v); const char *oldtemp = sqlite3_temp_directory; sq_pushstring(v, oldtemp, -1); if (_top_ > 1) { SQ_GET_STRING(v, 2, temp); if (sqlite3_temp_directory) { sqlite3_free((char*)sqlite3_temp_directory); } if (temp && temp_size) { sqlite3_temp_directory = sqlite3_mprintf("%s", temp); } else { sqlite3_temp_directory = NULL; } } return 1; } #endif #ifdef SQLITE_HAS_CODEC //#include "codecext.h" /* ** Params: db, sql ** returns: code, compiled length or error message */ static SQRESULT sq_sqlite3_key(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, key); sq_pushinteger(v, sqlite3_key_v2(self, 0, key, key_size)); return 1; } /* ** Params: db, sql ** returns: code, compiled length or error message */ static SQRESULT sq_sqlite3_rekey(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, key); sq_pushinteger(v, sqlite3_rekey_v2(self, 0, key, key_size)); return 1; } #endif #if !defined(SQLITE_OMIT_PROGRESS_CALLBACK) || !SQLITE_OMIT_PROGRESS_CALLBACK /* ** progress handler: ** Params: database, number of opcodes, callback function, userdata ** ** callback function: ** Params: userdata ** returns: 0 to return immediatly and return SQLITE_ABORT, non-zero to continue */ static int db_progress_callback(void *udata) { SQInteger result = 1; /* abort by default */ sq_sqlite3_sdb *sdb = (sq_sqlite3_sdb*)udata; HSQUIRRELVM v = sdb->v; int top = sq_gettop(v); sq_pushobject(v, sdb->progress_cb); sq_pushroottable(v); //this sq_pushobject(v, sdb->progress_udata); /* call squilu function */ if (sq_call(v, 2, SQTrue, SQFalse) == SQ_OK) sq_getinteger(v, -1, &result); sq_settop(v, top); return result; } static SQRESULT sq_sqlite3_progress_handler(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); /* clear progress handler */ sqlite3_progress_handler(self, 0, NULL, NULL); sq_release(v, &sdb->progress_cb); sq_release(v, &sdb->progress_udata); sq_resetobject(&sdb->progress_cb); sq_resetobject(&sdb->progress_udata); SQObjectType otype = sq_gettype(v, 2); if (_top_ > 1 && (otype != OT_NULL)) { SQ_GET_INTEGER(v, 2, nop); if(sq_gettype(v, 3) != OT_CLOSURE) return sq_throwerror(v, _SC("invalid second parameter expected closure")); sq_getstackobj(v, 3, &sdb->progress_cb); sq_addref(v, &sdb->progress_cb); if(_top_ > 3) { sq_getstackobj(v, 4, &sdb->progress_udata); sq_addref(v, &sdb->progress_udata); } /* set progress callback */ sqlite3_progress_handler(self, nop, db_progress_callback, sdb); } return 0; } #else /* #if !defined(SQLITE_OMIT_PROGRESS_CALLBACK) || !SQLITE_OMIT_PROGRESS_CALLBACK */ static SQRESULT sq_sqlite3_progress_handler(HSQUIRRELVM v) { return sq_throwerror(v, _SC("progress callback support disabled at compile time")); return 0; } #endif /* #if !defined(SQLITE_OMIT_PROGRESS_CALLBACK) || !SQLITE_OMIT_PROGRESS_CALLBACK */ /* ** trace callback: ** Params: database, callback function, userdata ** ** callback function: ** Params: userdata, sql */ static void db_trace_callback(void *udata, const char *sql) { sq_sqlite3_sdb *sdb = (sq_sqlite3_sdb*)udata; HSQUIRRELVM v = sdb->v; int top = sq_gettop(v); /* setup squirrel callback call */ sq_pushobject(v, sdb->trace_cb); sq_pushroottable(v); sq_pushobject(v, sdb->trace_udata); sq_pushstring(v, sql, -1); /* traced sql statement */ /* call squirrel function */ sq_call(v, 3, SQFalse, SQFalse); /* ignore any error generated by this function */ sq_settop(v, top); } static SQRESULT sq_sqlite3_trace(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); /* clear trace handler */ sqlite3_trace(self, NULL, NULL); sq_release(v, &sdb->trace_cb); sq_release(v, &sdb->trace_udata); sq_resetobject(&sdb->trace_cb); sq_resetobject(&sdb->trace_udata); SQObjectType otype = sq_gettype(v, 2); if (_top_ > 1 && (otype != OT_NULL)) { if(sq_gettype(v, 2) != OT_CLOSURE) return sq_throwerror(v, _SC("invalid fisrt parameter expected closure")); sq_getstackobj(v, 2, &sdb->trace_cb); sq_addref(v, &sdb->trace_cb); if(_top_ > 2) { sq_getstackobj(v, 3, &sdb->trace_udata); sq_addref(v, &sdb->trace_udata); } /* set trace callback */ if(_top_ > 3) { SQBool b; sq_getbool(v, 4, &b); sqlite3_trace_v0(self, db_trace_callback, sdb, b == SQTrue); } else sqlite3_trace(self, db_trace_callback, sdb); } return 0; } /* ** update hook callback: ** Params: database, callback function, userdata ** ** callback function: ** Params: userdata, sql */ static void db_update_hook_callback(void *udata, int update_type, char const *db_name, char const *table_name, sqlite3_int64 rowid) { sq_sqlite3_sdb *sdb = (sq_sqlite3_sdb*)udata; HSQUIRRELVM v = sdb->v; int top = sq_gettop(v); /* setup squirrel callback call */ sq_pushobject(v, sdb->update_hook_cb); sq_pushroottable(v); sq_pushobject(v, sdb->update_hook_udata); sq_pushinteger(v, update_type); sq_pushstring(v, db_name, -1); sq_pushstring(v, table_name, -1); sq_pushinteger(v, rowid); /* call squirrel function */ sq_call(v, 6, SQFalse, SQFalse); /* ignore any error generated by this function */ sq_settop(v, top); } static SQRESULT sq_sqlite3_update_hook(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); /* clear update handler */ sqlite3_update_hook(self, NULL, NULL); sq_release(v, &sdb->update_hook_cb); sq_release(v, &sdb->update_hook_udata); sq_resetobject(&sdb->update_hook_cb); sq_resetobject(&sdb->update_hook_udata); SQObjectType otype = sq_gettype(v, 2); if (_top_ > 1 && (otype != OT_NULL)) { if(sq_gettype(v, 2) != OT_CLOSURE) return sq_throwerror(v, _SC("invalid fisrt parameter expected closure")); sq_getstackobj(v, 2, &sdb->update_hook_cb); sq_addref(v, &sdb->update_hook_cb); if(_top_ > 2) { sq_getstackobj(v, 3, &sdb->update_hook_udata); sq_addref(v, &sdb->update_hook_udata); } /* set update_hook callback */ sqlite3_update_hook(self, db_update_hook_callback, sdb); } return 0; } /* ** authorizer hook callback: ** Params: database, callback function, userdata ** ** callback function: ** Params: userdata, sql */ #if 0 /******************************************* 3rd ************ 4th ***********/ #define SQLITE_CREATE_INDEX 1 /* Index Name Table Name */ #define SQLITE_CREATE_TABLE 2 /* Table Name NULL */ #define SQLITE_CREATE_TEMP_INDEX 3 /* Index Name Table Name */ #define SQLITE_CREATE_TEMP_TABLE 4 /* Table Name NULL */ #define SQLITE_CREATE_TEMP_TRIGGER 5 /* Trigger Name Table Name */ #define SQLITE_CREATE_TEMP_VIEW 6 /* View Name NULL */ #define SQLITE_CREATE_TRIGGER 7 /* Trigger Name Table Name */ #define SQLITE_CREATE_VIEW 8 /* View Name NULL */ #define SQLITE_DELETE 9 /* Table Name NULL */ #define SQLITE_DROP_INDEX 10 /* Index Name Table Name */ #define SQLITE_DROP_TABLE 11 /* Table Name NULL */ #define SQLITE_DROP_TEMP_INDEX 12 /* Index Name Table Name */ #define SQLITE_DROP_TEMP_TABLE 13 /* Table Name NULL */ #define SQLITE_DROP_TEMP_TRIGGER 14 /* Trigger Name Table Name */ #define SQLITE_DROP_TEMP_VIEW 15 /* View Name NULL */ #define SQLITE_DROP_TRIGGER 16 /* Trigger Name Table Name */ #define SQLITE_DROP_VIEW 17 /* View Name NULL */ #define SQLITE_INSERT 18 /* Table Name NULL */ #define SQLITE_PRAGMA 19 /* Pragma Name 1st arg or NULL */ #define SQLITE_READ 20 /* Table Name Column Name */ #define SQLITE_SELECT 21 /* NULL NULL */ #define SQLITE_TRANSACTION 22 /* Operation NULL */ #define SQLITE_UPDATE 23 /* Table Name Column Name */ #define SQLITE_ATTACH 24 /* Filename NULL */ #define SQLITE_DETACH 25 /* Database Name NULL */ #define SQLITE_ALTER_TABLE 26 /* Database Name Table Name */ #define SQLITE_REINDEX 27 /* Index Name NULL */ #define SQLITE_ANALYZE 28 /* Table Name NULL */ #define SQLITE_CREATE_VTABLE 29 /* Table Name Module Name */ #define SQLITE_DROP_VTABLE 30 /* Table Name Module Name */ #define SQLITE_FUNCTION 31 /* NULL Function Name */ #define SQLITE_SAVEPOINT 32 /* Operation Savepoint Name */ #define SQLITE_COPY 0 /* No longer used */ #define SQLITE_RECURSIVE 33 /* NULL NULL */ #endif static int db_authorizer_hook_callback(void *udata, int action_code, char const *param3, char const *param4, char const *param5, char const *param6) { sq_sqlite3_sdb *sdb = (sq_sqlite3_sdb*)udata; HSQUIRRELVM v = sdb->v; int top = sq_gettop(v); SQInteger result = SQLITE_OK; /* setup squirrel callback call */ sq_pushobject(v, sdb->authorizer_hook_cb); sq_pushroottable(v); sq_pushobject(v, sdb->authorizer_hook_udata); sq_pushinteger(v, action_code); sq_pushstring(v, param3, -1); sq_pushstring(v, param4, -1); sq_pushstring(v, param5, -1); sq_pushstring(v, param6, -1); /* call squilu function */ /* ignore any error generated by this function */ if (sq_call(v, 7, SQTrue, SQFalse) == SQ_OK) sq_getinteger(v, -1, &result); sq_settop(v, top); return result; } static SQRESULT sq_sqlite3_set_authorizer(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); /* clear trace handler */ sqlite3_set_authorizer(self, NULL, NULL); sq_release(v, &sdb->authorizer_hook_cb); sq_release(v, &sdb->authorizer_hook_udata); sq_resetobject(&sdb->authorizer_hook_cb); sq_resetobject(&sdb->authorizer_hook_udata); SQObjectType otype = sq_gettype(v, 2); if (_top_ > 1 && (otype != OT_NULL)) { if(sq_gettype(v, 2) != OT_CLOSURE) return sq_throwerror(v, _SC("invalid fisrt parameter expected closure")); sq_getstackobj(v, 2, &sdb->authorizer_hook_cb); sq_addref(v, &sdb->authorizer_hook_cb); if(_top_ > 2) { sq_getstackobj(v, 3, &sdb->authorizer_hook_udata); sq_addref(v, &sdb->authorizer_hook_udata); } /* set authorizer_hook callback */ sqlite3_set_authorizer(self, db_authorizer_hook_callback, sdb); } return 0; } /* ** busy handler: ** Params: database, callback function, userdata ** ** callback function: ** Params: userdata, number of tries ** returns: 0 to return immediatly and return SQLITE_BUSY, non-zero to try again */ static int db_busy_callback(void *udata, int tries) { SQBool retry = SQFalse; /* abort by default */ sq_sqlite3_sdb *sdb = (sq_sqlite3_sdb*)udata; HSQUIRRELVM v = sdb->v; int top = sq_gettop(v); sq_pushobject(v, sdb->busy_cb); sq_pushroottable(v); sq_pushobject(v, sdb->busy_udata); sq_pushinteger(v, tries); /* call squilu function */ if (sq_call(v, 3, SQTrue, SQFalse) == SQ_OK) sq_getbool(v, -1, &retry); sq_settop(v, top); return retry == SQTrue; } static SQRESULT sq_sqlite3_busy_handler(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); /* clear busy handler */ sqlite3_busy_handler(self, NULL, NULL); sq_release(v, &sdb->busy_cb); sq_release(v, &sdb->busy_udata); sq_resetobject(&sdb->busy_cb); sq_resetobject(&sdb->busy_udata); SQObjectType otype = sq_gettype(v, 2); if (_top_ > 1 && (otype != OT_NULL)) { if(sq_gettype(v, 2) != OT_CLOSURE) return sq_throwerror(v, _SC("invalid fisrt parameter expected closure")); sq_getstackobj(v, 2, &sdb->busy_cb); sq_addref(v, &sdb->busy_cb); if(_top_ > 2) { sq_getstackobj(v, 3, &sdb->busy_udata); sq_addref(v, &sdb->busy_udata); } /* set busy callback */ sqlite3_busy_handler(self, db_busy_callback, sdb); } return 0; } static SQRESULT sq_sqlite3_busy_timeout(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); SQ_GET_INTEGER(v, 2, timeout); sqlite3_busy_timeout(self, timeout); /* if there was a timeout callback registered, it is now ** invalid/useless. free any references we may have */ sq_release(v, &sdb->busy_cb); sq_resetobject(&sdb->busy_cb); sq_release(v, &sdb->busy_udata); sq_resetobject(&sdb->busy_udata); return 0; } static SQRESULT sq_sqlite3_interrupt(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); sqlite3_interrupt(self); return 0; } /* ** ======================================================= ** User Defined Functions - Context Methods ** ======================================================= */ typedef struct { sqlite3_context *ctx; HSQOBJECT udata; } sq_sqlite3_context_st; static const SQChar sq_sqlite3_context_TAG[] = _SC(":sqlite3:ctx"); static SQRESULT sq_sqlite3_context_releasehook(SQUserPointer p, SQInteger size, void */*ep*/) { sq_sqlite3_context_st *ctx = ((sq_sqlite3_context_st *)p); /* 'free' all references */ sq_free(ctx, sizeof(sq_sqlite3_context_st)); return 0; } static SQRESULT sq_sqlite3_context_constructor(HSQUIRRELVM v) { sq_sqlite3_context_st *ctx = (sq_sqlite3_context_st*)sq_malloc(sizeof(sq_sqlite3_context_st)); ctx->ctx = NULL; sq_resetobject(&ctx->udata); sq_setinstanceup(v, 1, ctx); sq_setreleasehook(v,1, sq_sqlite3_context_releasehook); return 1; } #define SQ_SQLITE3_GETCONTEXT(v, idx) \ sq_sqlite3_context_st *self;\ if((_rc_ = sq_getinstanceup(v, idx, (void**)&self, (void*)sq_sqlite3_context_TAG)) < 0) return _rc_; #define GET_sqlite3_context_INSTANCE() SQ_SQLITE3_GETCONTEXT(v,1) static SQRESULT sq_sqlite3_context__tostring(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); char buff[64]; snprintf(buff, sizeof(buff), "sqlite function context (%p)", self); sq_pushstring(v, buff, -1); return 1; } static SQRESULT sq_sqlite3_context_check_aggregate(HSQUIRRELVM v, sq_sqlite3_context_st *ctx) { sq_sqlite3_sdb_func *func = (sq_sqlite3_sdb_func*)sqlite3_user_data(ctx->ctx); if (sq_isclosure(func->fn_finalize)) { return sq_throwerror(v, "attempt to call aggregate method from scalar function"); } return 1; } static SQRESULT sq_sqlite3_context_user_data(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); sq_sqlite3_sdb_func *func = (sq_sqlite3_sdb_func*)sqlite3_user_data(self->ctx); sq_pushobject(v, func->udata); return 1; } static SQRESULT sq_sqlite3_context_aggregate_data(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_context_INSTANCE(); sq_sqlite3_context_check_aggregate(v, self); if(_top_ < 2) { sq_pushobject(v, self->udata); } else { sq_release(v, &self->udata); sq_getstackobj(v, 2, &self->udata); sq_addref(v, &self->udata); } return 0; } static SQRESULT sq_sqlite3_context_aggregate_count(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); sq_sqlite3_context_check_aggregate(v, self); sq_pushinteger(v, sqlite3_aggregate_count(self->ctx)); return 1; } struct sq_sqlite3_context_aux_data_st { HSQUIRRELVM vm; HSQOBJECT data; }; static SQRESULT sq_sqlite3_context_get_aux_data(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_INTEGER(v, 2, argn); sq_sqlite3_context_aux_data_st *data = (sq_sqlite3_context_aux_data_st*)sqlite3_get_auxdata(self->ctx, argn); if(data) { sq_pushobject(v, data->data); } else { sq_pushnull(v); } return 1; } static void sq_sqlite3_context_free_aux_data(void *aux_data) { sq_sqlite3_context_aux_data_st *data = (sq_sqlite3_context_aux_data_st*)aux_data; if(data) { sq_release(data->vm, &data->data); sqlite3_free(data); } } static SQRESULT sq_sqlite3_context_set_aux_data(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_INTEGER(v, 2, argn); sq_sqlite3_context_aux_data_st *data = (sq_sqlite3_context_aux_data_st*)sqlite3_malloc(sizeof(*data)); if(data) { data->vm = v; sq_resetobject(&data->data); sq_getstackobj(v, 3, &data->data); sq_addref(v, &data->data); sqlite3_set_auxdata(self->ctx, argn, data, sq_sqlite3_context_free_aux_data); } return 0; } static SQRESULT sq_sqlite3_context_result_blob(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_STRING(v, 2, blob); sqlite3_result_blob(self->ctx, (const void*)blob, blob_size, SQLITE_TRANSIENT); return 0; } static SQRESULT sq_sqlite3_context_result_double(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_FLOAT(v, 2, d); sqlite3_result_double(self->ctx, d); return 0; } static SQRESULT sq_sqlite3_context_result_error(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_STRING(v,2, err); sqlite3_result_error(self->ctx, err, err_size); return 0; } static SQRESULT sq_sqlite3_context_result_int(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_INTEGER(v, 2, i); sqlite3_result_int(self->ctx, i); return 0; } static SQRESULT sq_sqlite3_context_result_null(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); sqlite3_result_null(self->ctx); return 0; } static SQRESULT sq_sqlite3_context_result_text(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_STRING(v, 2, text); sqlite3_result_text(self->ctx, text, text_size, SQLITE_TRANSIENT); return 0; } static SQRESULT sq_sqlite3_context_result_subtype(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_INTEGER(v, 2, subtype); sqlite3_result_subtype(self->ctx, subtype); return 0; } /* no way to recover parameter value after function call static SQRESULT sq_sqlite3_context_value_subtype(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_context_INSTANCE(); SQ_GET_INTEGER(v, 2, param_idx); sq_pushinteger(v, sqlite3_value_subtype(self->ctx, subtype)); return 1; } */ #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_sqlite3_context_##name,nparams,tycheck} static SQRegFunction sq_sqlite3_context_methods[] = { _DECL_FUNC(constructor, 1, _SC("x")), _DECL_FUNC(user_data, 1, _SC("x")), _DECL_FUNC(aggregate_data, -1, _SC("x.")), _DECL_FUNC(aggregate_count, 1, _SC("x")), _DECL_FUNC(result_null, 1, _SC("x")), _DECL_FUNC(result_double, 2, _SC("xn")), _DECL_FUNC(result_int, 2, _SC("xi")), _DECL_FUNC(result_text, 2, _SC("xs")), _DECL_FUNC(result_blob, 2, _SC("xs")), _DECL_FUNC(result_error, 2, _SC("xs")), _DECL_FUNC(result_subtype, 2, _SC("xi")), //_DECL_FUNC(value_subtype, 2, _SC("xi")), _DECL_FUNC(get_aux_data, 2, _SC("xi")), _DECL_FUNC(set_aux_data, 3, _SC("xi.")), _DECL_FUNC(_tostring, -1, _SC("x")), {0,0} }; #undef _DECL_FUNC /* ** callback functions used when calling registered sql functions */ static void sqlite3_push_value(HSQUIRRELVM v, sqlite3_value *value) { const char *tmp_value; switch (sqlite3_value_type(value)) { case SQLITE_TEXT: tmp_value = (const char*) sqlite3_value_text(value); if(tmp_value) sq_pushstring(v, tmp_value, sqlite3_value_bytes(value)); else push_sqlite3_null(v); break; case SQLITE_INTEGER: { sqlite_int64 i64 = sqlite3_value_int64(value); SQInteger n = (SQInteger)i64; if (n == i64) sq_pushinteger(v, n); else sq_pushstring(v, (const char*) sqlite3_value_text(value), sqlite3_value_bytes(value)); } break; case SQLITE_FLOAT: sq_pushfloat(v, sqlite3_value_double(value)); break; case SQLITE_BLOB: tmp_value = (const char*) sqlite3_value_blob(value); if(tmp_value) sq_pushstring(v, tmp_value, sqlite3_value_bytes(value)); else push_sqlite3_null(v); break; case SQLITE_NULL: push_sqlite3_null(v); break; default: /* things done properly (SQLite + SquiLu SQLite) ** this should never happen */ push_sqlite3_null(v); break; } } //#if 0 static SQRESULT new_context_instance(HSQUIRRELVM v, sq_sqlite3_context_st **ctx) { sq_pushregistrytable(v); sq_pushstring(v,_SC("sqite3_context"),-1); int rc = sq_rawget(v, -2); sq_remove(v, -2); //remove registrytable sq_pushroottable(v); rc = sq_call(v, 1, SQTrue, SQFalse); sq_remove(v, -2); //class rc = sq_getinstanceup(v, -1, (void**)ctx, (void*)sq_sqlite3_context_TAG); return rc; } /* scalar function to be called ** callback params: context, values... */ static void db_sql_normal_function(sqlite3_context *context, int argc, sqlite3_value **argv) { sq_sqlite3_sdb_func *func = (sq_sqlite3_sdb_func*)sqlite3_user_data(context); HSQUIRRELVM v = func->sdb->v; int n; sq_sqlite3_context_st *ctx; int top = sq_gettop(v); /* ensure there is enough space in the stack */ sq_reservestack(v, argc + 5); sq_pushobject(v, func->fn_step); sq_pushroottable(v); if (!sq_isclosure(func->fn_finalize)) { new_context_instance(v, &ctx); } else { /* reuse context userdata value */ void *p = sqlite3_aggregate_context(context, 1); /* i think it is OK to use assume that using a light user data ** as an entry on SquiLu REGISTRY table will be unique */ sq_pushregistrytable(v); sq_pushuserpointer(v, p); /* context table */ if(sq_rawget(v, -2) != SQ_OK) { /* not yet created? */ sq_poptop(v); //remove null new_context_instance(v, &ctx); sq_pushuserpointer(v, p); sq_push(v, -2); sq_rawset(v, -4); //insert into registrytable } sq_remove(v, -2); //remove registrytable } /* push params */ for (n = 0; n < argc; ++n) { sqlite3_push_value(v, argv[n]); } /* set context */ ctx->ctx = context; if (sq_call(v, argc + 2, SQFalse, SQFalse) != SQ_OK) //2 = roottable + ctx { sqlite3_result_error(context, sq_getlasterror_str(v), -1); } /* invalidate context */ ctx->ctx = NULL; if (!sq_isclosure(func->fn_finalize)) { sq_release(v, &ctx->udata); sq_resetobject(&ctx->udata); } sq_settop(v, top); } static void db_sql_finalize_function(sqlite3_context *context) { sq_sqlite3_sdb_func *func = (sq_sqlite3_sdb_func*)sqlite3_user_data(context); HSQUIRRELVM v = func->sdb->v; void *p = sqlite3_aggregate_context(context, 1); /* minimal mem usage */ sq_sqlite3_context_st *ctx; int top = sq_gettop(v); sq_pushobject(v, func->fn_finalize); sq_pushroottable(v); /* i think it is OK to use assume that using a light user data ** as an entry on SquiLu REGISTRY table will be unique */ sq_pushregistrytable(v); sq_pushuserpointer(v, p); /* remove it from registry but we'll use it last time here */ /* context table */ if(sq_deleteslot(v, -2, SQTrue) != SQ_OK) { /* not yet created? - shouldn't happen in finalize function */ sq_pop(v, 1); new_context_instance(v, &ctx); sq_pushuserpointer(v, p); sq_push(v, -2); sq_rawset(v, -4); } sq_remove(v, -2); //registrytable /* set context */ ctx->ctx = context; if (sq_call(v, 1, SQFalse, SQFalse) != SQ_OK) { sqlite3_result_error(context, sq_getlasterror_str(v), -1); } /* invalidate context */ ctx->ctx = NULL; /* cleanup context */ sq_release(v, &ctx->udata); sq_resetobject(&ctx->udata); sq_settop(v, top); } /* ** Register a normal function ** Params: db, function name, number arguments, [ callback | step, finalize], user data ** Returns: true on sucess ** ** Normal function: ** Params: context, params ** ** Aggregate function: ** Params of step: context, params ** Params of finalize: context */ static SQRESULT db_register_function(HSQUIRRELVM v, int aggregate) { SQ_FUNC_VARS(v); SQInteger ftype = 0; GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, name); SQ_GET_INTEGER(v, 3, nargs); if(sq_gettype(v, 4) != OT_CLOSURE) return sq_throwerror(v, "invalid parameter 3 expected closure"); if (aggregate) { if(sq_gettype(v,5) != OT_CLOSURE) return sq_throwerror(v, "invalid parameter 4 expected closure"); } else { sq_optinteger(v, 5, &ftype, 0); } sq_sqlite3_sdb_func *func; /* maybe an alternative way to allocate memory should be used/avoided */ func = (sq_sqlite3_sdb_func*)sq_malloc(sizeof(sq_sqlite3_sdb_func)); memset(func, 0, sizeof(sq_sqlite3_sdb_func)); _rc_ = sqlite3_create_function( self, name, nargs, SQLITE_UTF8 | (ftype == SQLITE_DETERMINISTIC ? ftype : 0), func, aggregate ? NULL : db_sql_normal_function, aggregate ? db_sql_normal_function : NULL, aggregate ? db_sql_finalize_function : NULL ); if (_rc_ == SQLITE_OK) { /* save registered function in db function list */ func->sdb = sdb; func->next = sdb->func; sdb->func = func; /* save the setp/normal function callback */ sq_resetobject(&func->fn_step); sq_getstackobj(v, 4, &func->fn_step); sq_addref(v, &func->fn_step); /* save the finalize function callback */ sq_resetobject(&func->fn_finalize); if (aggregate) { sq_getstackobj(v, 5, &func->fn_finalize); sq_addref(v, &func->fn_finalize); } /* save user data */ sq_resetobject(&func->udata); int udata_idx = aggregate ? 6 : 5; if(_top_ >= udata_idx) { sq_getstackobj(v, udata_idx, &func->udata); sq_addref(v, &func->udata); } } else { /* free allocated memory */ sq_free(func, sizeof(sq_sqlite3_sdb_func)); } sq_pushbool(v, _rc_ == SQLITE_OK ? 1 : 0); return 1; } //#endif static SQRESULT sq_sqlite3_create_function(HSQUIRRELVM v) { return db_register_function(v, 0); } static SQRESULT sq_sqlite3_create_aggregate(HSQUIRRELVM v) { return db_register_function(v, 1); } static SQRESULT sq_sqlite3_backup(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, fname); SQ_OPT_STRING(v, 3, dbSrcName, _SC("main")); SQ_OPT_STRING(v, 4, dbDestName, _SC("main")); sqlite3 *pDest; sqlite3_backup *pBackup; int rc = sqlite3_open(fname, &pDest); if(rc!=SQLITE_OK) { sqlite3_close(pDest); return sq_throwerror(v, _SC("SQLite can't open %s"), fname); } pBackup = sqlite3_backup_init(pDest, dbDestName, self, dbSrcName); if( pBackup==0 ){ rc = sq_throwerror(v, _SC("Error: %s\n"), sqlite3_errmsg(pDest)); sqlite3_close(pDest); } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){} sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = SQ_OK; }else{ rc = sq_throwerror(v, _SC("Error: %s\n"), sqlite3_errmsg(pDest)); } sqlite3_close(pDest); return rc; } static SQRESULT sq_sqlite3_restore(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, fname); SQ_OPT_STRING(v, 3, dbSrcName, _SC("main")); SQ_OPT_STRING(v, 4, dbDestName, _SC("main")); sqlite3 *pSrc; sqlite3_backup *pBackup; int nTimeout = 0; int rc = sqlite3_open(fname, &pSrc); if(rc!=SQLITE_OK) { sqlite3_close(pSrc); return sq_throwerror(v, _SC("SQLite can't open %s"), fname); } pBackup = sqlite3_backup_init(self, dbDestName, pSrc, dbSrcName); if( pBackup==0 ){ sqlite3_close(pSrc); return sq_throwerror(v, _SC("Error: %s\n"), sqlite3_errmsg(self)); } while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK || rc==SQLITE_BUSY ){ if( rc==SQLITE_BUSY ){ if( nTimeout++ >= 3 ) break; sqlite3_sleep(100); } } sqlite3_backup_finish(pBackup); if( rc==SQLITE_DONE ){ rc = SQ_OK; }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){ rc = sq_throwerror(v, _SC("Error: source database is busy\n")); }else{ rc = sq_throwerror(v, _SC("Error: %s\n"), sqlite3_errmsg(self)); } sqlite3_close(pSrc); return rc; } #ifndef SQLITE_OMIT_LOAD_EXTENSION static SQRESULT sq_sqlite3_enable_load_extension(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); GET_sqlite3_INSTANCE(); SQ_GET_BOOL(v, 2, onOff); sqlite3_enable_load_extension(self, onOff); return 0; } #endif #if 0 /** The number/order of fields should be the same to use this function it'll save temporary data convertion. */ static SQRESULT sq_sqlite3_exec_loop(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sqlite3_INSTANCE(); SQ_GET_STRING(v, 2, outer_sql); SQ_GET_STRING(v, 3, inner1_sql); SQ_OPT_STRING(v, 4, inner2_sql, NULL); sqlite3_stmt *stmt_outer = NULL, *stmt_inner1 = NULL, *stmt_inner2 = NULL; int rc = sqlite3_prepare_v2(self, outer_sql, outer_sql_size, &stmt_outer, NULL); if(rc == SQLITE_OK) { rc = sqlite3_prepare_v2(self, inner1_sql, inner1_sql_size, &stmt_inner1, NULL); if(rc == SQLITE_OK) { if(inner2_sql) { rc = sqlite3_prepare_v2(self, inner2_sql, inner2_sql_size, &stmt_inner2, NULL); } if(rc == SQLITE_OK) { int outer_col_count = sqlite3_column_count(stmt_outer); int inner1_param_count = sqlite3_bind_parameter_count(stmt_inner1); int inner2_param_count = stmt_inner2 ? sqlite3_bind_parameter_count(stmt_inner2) : -1; if( (inner1_param_count <= outer_col_count) && ((inner2_param_count > 0) && (inner2_param_count <= outer_col_count) ) ) { while(sqlite3_step(stmt_outer) == SQLITE_ROW) { for(int i=0; i < inner1_param_count; ++i) { rc = sqlite3_bind_value(stmt_inner1, i+1, sqlite3_column_value(stmt_outer, i)); if(rc != SQLITE_OK) break; } if(rc == SQLITE_OK) { rc = sqlite3_step(stmt_inner1); sqlite3_reset(stmt_inner1); } if(rc != SQLITE_DONE) break; if((inner2_param_count > 0) && (sqlite3_changes(self) == 0)) { for(int i=0; i < inner2_param_count; ++i) { rc = sqlite3_bind_value(stmt_inner2, i+1, sqlite3_column_value(stmt_outer, i)); if(rc != SQLITE_OK) break; } if(rc == SQLITE_OK) { rc = sqlite3_step(stmt_inner2); sqlite3_reset(stmt_inner2); } if(rc != SQLITE_DONE) break; } } } else { return sq_throwerror(v, _SC("bind parameter count mismatch expect %d : %d but got outer %d"), inner1_param_count, inner2_param_count, outer_col_count); } } } } if(stmt_outer) sqlite3_finalize(stmt_outer); if(stmt_inner1) sqlite3_finalize(stmt_inner1); if(stmt_inner2) sqlite3_finalize(stmt_inner2); sq_pushinteger(v, rc); return 1; } #endif // 0 #define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_sqlite3_##name,nparams,tycheck} static SQRegFunction sq_sqlite3_methods[] = { _DECL_FUNC(constructor, -2, _SC("xsi")), _DECL_FUNC(close, 1, _SC("x")), _DECL_FUNC(db_ptr, 1, _SC("x")), _DECL_FUNC(IsAutoCommitOn, 1, _SC("x")), _DECL_FUNC(version, 1, _SC("x|y")), _DECL_FUNC(threadsafe, 1, _SC("x|y")), _DECL_FUNC(config_single_thread, 1, _SC("y")), _DECL_FUNC(config_multi_thread, 1, _SC("y")), _DECL_FUNC(config_serialized, 1, _SC("y")), _DECL_FUNC(errcode, 1, _SC("x")), _DECL_FUNC(errmsg, 1, _SC("x")), _DECL_FUNC(sleep, 1, _SC("x")), _DECL_FUNC(interrupt, 1, _SC("x")), _DECL_FUNC(progress_handler, -2, _SC("x i|o c .")), _DECL_FUNC(trace, -2, _SC("x c|o .")), _DECL_FUNC(update_hook, -2, _SC("x c|o .")), _DECL_FUNC(set_authorizer, -2, _SC("x c|o .")), _DECL_FUNC(busy_handler, -2, _SC("x c|o .")), _DECL_FUNC(busy_timeout, 2, _SC("xi")), _DECL_FUNC(create_function, -4, _SC("xsic.")), _DECL_FUNC(create_aggregate, -5, _SC("xsicc.")), #ifndef WIN32 _DECL_FUNC(temp_directory, 2, _SC("xs")), #endif _DECL_FUNC(enable_shared_cache, 2, _SC("xb")), _DECL_FUNC(changes, 1, _SC("x")), _DECL_FUNC(exec, -2, _SC("x s|x")), _DECL_FUNC(exec_dml, 2, _SC("xs")), _DECL_FUNC(exec_one_dml, -2, _SC("x s|x")), _DECL_FUNC(exec_get_first_row, -2, _SC("x s|x")), _DECL_FUNC(exec_get_one, -2, _SC("x s|x")), //_DECL_FUNC(exec_loop, -3, _SC("x sss")), _DECL_FUNC(get_db_name, 1, _SC("x")), _DECL_FUNC(last_row_id, 1, _SC("x")), _DECL_FUNC(prepare, 2, _SC("xs")), _DECL_FUNC(blob_open, -5, _SC("xsssii")), _DECL_FUNC(set_busy_timeout, -1, _SC("xi")), _DECL_FUNC(total_changes, 1, _SC("x")), _DECL_FUNC(backup, -2, _SC("xsss")), _DECL_FUNC(restore, -2, _SC("xsss")), #ifndef SQLITE_OMIT_LOAD_EXTENSION _DECL_FUNC(enable_load_extension, 2, _SC("xb")), #endif #ifdef SQLITE_HAS_CODEC _DECL_FUNC(key, 2, _SC("xs")), _DECL_FUNC(rekey, 2, _SC("xs")), #endif {0,0} }; #undef _DECL_FUNC #define INT_CONST(v,num) sq_pushstring(v,_SC(#num),-1);sq_pushinteger(v,num);sq_newslot(v,-3,SQTrue); #ifdef __cplusplus extern "C" { #endif SQRESULT sqext_register_SQLite3(HSQUIRRELVM v) { sq_insertfunc(v, _SC("sle2vecOfvec"), sq_sle2vecOfvec, -2, _SC(". s|x a i"), SQTrue); sq_insertfunc(v, _SC("get_sle_size"), sq_get_sle_size, -2, _SC(".i"), SQTrue); sq_insertfunc(v, _SC("add2sle"), sq_add2sle, -3, _SC(".xsi"), SQTrue); sq_pushconsttable(v); #define INT_SLE_CONST(num) sq_pushstring(v,_SC("SLE_" #num),-1);sq_pushinteger(v,num);sq_newslot(v,-3,SQTrue); INT_SLE_CONST(IBYTE1); INT_SLE_CONST(IBYTE2); INT_SLE_CONST(IBYTE3); INT_SLE_CONST(IBYTE4); INT_SLE_CONST(IBYTE_MAX); INT_SLE_CONST(SLEMARK); INT_SLE_CONST(SLEEND); sq_poptop(v); //remove const table HSQOBJECT sqlite3_NULL; sq_pushregistrytable(v); sq_pushstring(v, sqlite3_NULL_Name,-1); sq_newuserdata(v, sizeof(void*)); sq_settypetag(v, -1, (SQUserPointer)sqlite3_NULL_Name); sq_resetobject(&sqlite3_NULL); sq_getstackobj(v, -1, &sqlite3_NULL); sq_newtable(v); sq_insert_reg_funcs(v, sqlite3_NULL_methods); sq_setdelegate(v, -2); sq_newslot(v,-3,SQTrue); sq_pushstring(v,_SC("sqite3_context"),-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(SQUserPointer)sq_sqlite3_context_TAG); sq_insert_reg_funcs(v, sq_sqlite3_context_methods); sq_newslot(v,-3,SQTrue); sq_pushstring(v,SQLite3_Blob_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(SQUserPointer)SQLite3_Blob_TAG); sq_insert_reg_funcs(v, sq_sqlite3_blob_methods); sq_newslot(v,-3,SQTrue); sq_poptop(v); //remove registrytable sq_pushstring(v,SQLite3_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(SQUserPointer)SQLite3_TAG); sq_insert_reg_funcs(v, sq_sqlite3_methods); INT_CONST(v,SQLITE_OPEN_CREATE); INT_CONST(v,SQLITE_OPEN_READWRITE); INT_CONST(v,SQLITE_OPEN_SHAREDCACHE); INT_CONST(v,SQLITE_OPEN_SUBLATIN_NA_LIKE); INT_CONST(v,SQLITE_OK); INT_CONST(v,SQLITE_BUSY); INT_CONST(v,SQLITE_DONE); INT_CONST(v,SQLITE_DETERMINISTIC); INT_CONST(v,SQLITE_ERROR); INT_CONST(v,SQLITE_INTERRUPT); INT_CONST(v,SQLITE_MISUSE); INT_CONST(v,SQLITE_ROW); INT_CONST(v,SQLITE_LOCKED_SHAREDCACHE); INT_CONST(v,SQLITE_BUSY_RECOVERY); INT_CONST(v,SQLITE_BUSY_SNAPSHOT); INT_CONST(v,SQLITE_CANTOPEN_NOTEMPDIR); INT_CONST(v,SQLITE_CANTOPEN_ISDIR); INT_CONST(v,SQLITE_CANTOPEN_FULLPATH); INT_CONST(v,SQLITE_CANTOPEN_CONVPATH); INT_CONST(v,SQLITE_CORRUPT_VTAB); INT_CONST(v,SQLITE_READONLY_RECOVERY); INT_CONST(v,SQLITE_READONLY_CANTLOCK); INT_CONST(v,SQLITE_READONLY_ROLLBACK); INT_CONST(v,SQLITE_READONLY_DBMOVED); INT_CONST(v,SQLITE_ABORT_ROLLBACK); INT_CONST(v,SQLITE_CONSTRAINT_CHECK); INT_CONST(v,SQLITE_CONSTRAINT_COMMITHOOK); INT_CONST(v,SQLITE_CONSTRAINT_FOREIGNKEY); INT_CONST(v,SQLITE_CONSTRAINT_FUNCTION); INT_CONST(v,SQLITE_CONSTRAINT_NOTNULL); INT_CONST(v,SQLITE_CONSTRAINT_PRIMARYKEY); INT_CONST(v,SQLITE_CONSTRAINT_TRIGGER); INT_CONST(v,SQLITE_CONSTRAINT_UNIQUE); INT_CONST(v,SQLITE_CONSTRAINT_VTAB); INT_CONST(v,SQLITE_CONSTRAINT_ROWID); INT_CONST(v,SQLITE_NOTICE_RECOVER_WAL); INT_CONST(v,SQLITE_NOTICE_RECOVER_ROLLBACK); INT_CONST(v,SQLITE_WARNING_AUTOINDEX); /*Authorizer codes*/ INT_CONST(v, SQLITE_IGNORE); INT_CONST(v, SQLITE_DENY); INT_CONST(v, SQLITE_CREATE_INDEX); INT_CONST(v, SQLITE_CREATE_TABLE); INT_CONST(v, SQLITE_CREATE_TEMP_INDEX); INT_CONST(v, SQLITE_CREATE_TEMP_TABLE); INT_CONST(v, SQLITE_CREATE_TEMP_TRIGGER); INT_CONST(v, SQLITE_CREATE_TEMP_VIEW); INT_CONST(v, SQLITE_CREATE_TRIGGER); INT_CONST(v, SQLITE_CREATE_VIEW); INT_CONST(v, SQLITE_DELETE); INT_CONST(v, SQLITE_DROP_INDEX); INT_CONST(v, SQLITE_DROP_TABLE); INT_CONST(v, SQLITE_DROP_TEMP_INDEX); INT_CONST(v, SQLITE_DROP_TEMP_TABLE); INT_CONST(v, SQLITE_DROP_TEMP_TRIGGER); INT_CONST(v, SQLITE_DROP_TEMP_VIEW); INT_CONST(v, SQLITE_DROP_TRIGGER); INT_CONST(v, SQLITE_DROP_VIEW); INT_CONST(v, SQLITE_INSERT); INT_CONST(v, SQLITE_PRAGMA); INT_CONST(v, SQLITE_READ); INT_CONST(v, SQLITE_SELECT); INT_CONST(v, SQLITE_TRANSACTION); INT_CONST(v, SQLITE_UPDATE); INT_CONST(v, SQLITE_ATTACH); INT_CONST(v, SQLITE_DETACH); INT_CONST(v, SQLITE_ALTER_TABLE); INT_CONST(v, SQLITE_REINDEX); INT_CONST(v, SQLITE_ANALYZE); INT_CONST(v, SQLITE_CREATE_VTABLE); INT_CONST(v, SQLITE_DROP_VTABLE); INT_CONST(v, SQLITE_FUNCTION); INT_CONST(v, SQLITE_SAVEPOINT); INT_CONST(v, SQLITE_COPY); INT_CONST(v, SQLITE_RECURSIVE); //push sqlite3_NULL as a member sq_pushstring(v, nullName,-1); sq_pushobject(v, sqlite3_NULL); sq_newslot(v,-3,SQTrue); sq_newslot(v,-3,SQTrue); #ifdef SQLITE_ENABLE_SESSION sq_pushstring(v, SQLite3_Session_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(SQUserPointer)SQLite3_Session_TAG); sq_insert_reg_funcs(v, sq_sqlite3_session_methods); sq_newslot(v,-3,SQTrue); #endif // SQLITE_ENABLE_SESSION sq_pushstring(v, SQLite3_Stmt_TAG,-1); sq_newclass(v,SQFalse); sq_settypetag(v,-1,(SQUserPointer)SQLite3_Stmt_TAG); sq_insert_reg_funcs(v, sq_sqlite3_stmt_methods); INT_CONST(v,SQLITE_INTEGER); INT_CONST(v,SQLITE_FLOAT); INT_CONST(v,SQLITE_NULL); INT_CONST(v,SQLITE_TEXT); INT_CONST(v,SQLITE_BLOB); INT_CONST(v,SQLITE_OK); INT_CONST(v,SQLITE_DONE); INT_CONST(v,SQLITE_ROW); INT_CONST(v,AS_STRING_ALWAYS); INT_CONST(v,NULL_AS_EMPTY_STR); INT_CONST(v,WITH_COL_NAMES); INT_CONST(v,WITH_BLOB_AS_NULL); INT_CONST(v,WITH_SQ_NULL); //push sqlite3_NULL as a member sq_pushstring(v, nullName,-1); sq_pushobject(v, sqlite3_NULL); sq_newslot(v,-3,SQTrue); sq_newslot(v,-3,SQTrue); return 1; } #ifdef __cplusplus } #endif