| /* |
| ** This file requires access to sqlite3.c static state in order to |
| ** implement certain WASM-specific features, and thus directly |
| ** includes that file. Unlike the rest of sqlite3.c, this file |
| ** requires compiling with -std=c99 (or equivalent, or a later C |
| ** version) because it makes use of features not available in C89. |
| ** |
| ** At its simplest, to build sqlite3.wasm either place this file |
| ** in the same directory as sqlite3.c/h before compilation or use the |
| ** -I/path flag to tell the compiler where to find both of those |
| ** files, then compile this file. For example: |
| ** |
| ** emcc -o sqlite3.wasm ... -I/path/to/sqlite3-c-and-h sqlite3-wasm.c |
| */ |
| #define SQLITE_WASM |
| #ifdef SQLITE_WASM_ENABLE_C_TESTS |
| /* |
| ** Code blocked off by SQLITE_WASM_TESTS is intended solely for use in |
| ** unit/regression testing. They may be safely omitted from |
| ** client-side builds. The main unit test script, tester1.js, will |
| ** skip related tests if it doesn't find the corresponding functions |
| ** in the WASM exports. |
| */ |
| # define SQLITE_WASM_TESTS 1 |
| #else |
| # define SQLITE_WASM_TESTS 0 |
| #endif |
| |
| /* |
| ** Threading and file locking: JS is single-threaded. Each Worker |
| ** thread is a separate instance of the JS engine so can never access |
| ** the same db handle as another thread, thus multi-threading support |
| ** is unnecessary in the library. Because the filesystems are virtual |
| ** and local to a given wasm runtime instance, two Workers can never |
| ** access the same db file at once, with the exception of OPFS. |
| ** |
| ** Summary: except for the case of OPFS, which supports locking using |
| ** its own API, threading and file locking support are unnecessary in |
| ** the wasm build. |
| */ |
| |
| /* |
| ** Undefine any SQLITE_... config flags which we specifically do not |
| ** want defined. Please keep these alphabetized. |
| */ |
| #undef SQLITE_OMIT_DESERIALIZE |
| #undef SQLITE_OMIT_MEMORYDB |
| |
| /* |
| ** Define any SQLITE_... config defaults we want if they aren't |
| ** overridden by the builder. Please keep these alphabetized. |
| */ |
| |
| /**********************************************************************/ |
| /* SQLITE_D... */ |
| #ifndef SQLITE_DEFAULT_CACHE_SIZE |
| /* |
| ** The OPFS impls benefit tremendously from an increased cache size |
| ** when working on large workloads, e.g. speedtest1 --size 50 or |
| ** higher. On smaller workloads, e.g. speedtest1 --size 25, they |
| ** clearly benefit from having 4mb of cache, but not as much as a |
| ** larger cache benefits the larger workloads. Speed differences |
| ** between 2x and nearly 3x have been measured with ample page cache. |
| */ |
| # define SQLITE_DEFAULT_CACHE_SIZE -16384 |
| #endif |
| #if !defined(SQLITE_DEFAULT_PAGE_SIZE) |
| /* |
| ** OPFS performance is improved by approx. 12% with a page size of 8kb |
| ** instead of 4kb. Performance with 16kb is equivalent to 8kb. |
| ** |
| ** Performance difference of kvvfs with a page size of 8kb compared to |
| ** 4kb, as measured by speedtest1 --size 4, is indeterminate: |
| ** measurements are all over the place either way and not |
| ** significantly different. |
| */ |
| # define SQLITE_DEFAULT_PAGE_SIZE 8192 |
| #endif |
| #ifndef SQLITE_DEFAULT_UNIX_VFS |
| # define SQLITE_DEFAULT_UNIX_VFS "unix-none" |
| #endif |
| #undef SQLITE_DQS |
| #define SQLITE_DQS 0 |
| |
| /**********************************************************************/ |
| /* SQLITE_ENABLE_... */ |
| /* |
| ** Unconditionally enable API_ARMOR in the WASM build. It ensures that |
| ** public APIs behave predictable in the face of passing illegal NULLs |
| ** or ranges which might otherwise invoke undefined behavior. |
| */ |
| #undef SQLITE_ENABLE_API_ARMOR |
| #define SQLITE_ENABLE_API_ARMOR 1 |
| |
| #ifndef SQLITE_ENABLE_BYTECODE_VTAB |
| # define SQLITE_ENABLE_BYTECODE_VTAB 1 |
| #endif |
| #ifndef SQLITE_ENABLE_DBPAGE_VTAB |
| # define SQLITE_ENABLE_DBPAGE_VTAB 1 |
| #endif |
| #ifndef SQLITE_ENABLE_DBSTAT_VTAB |
| # define SQLITE_ENABLE_DBSTAT_VTAB 1 |
| #endif |
| #ifndef SQLITE_ENABLE_EXPLAIN_COMMENTS |
| # define SQLITE_ENABLE_EXPLAIN_COMMENTS 1 |
| #endif |
| #ifndef SQLITE_ENABLE_FTS4 |
| # define SQLITE_ENABLE_FTS4 1 |
| #endif |
| #ifndef SQLITE_ENABLE_MATH_FUNCTIONS |
| # define SQLITE_ENABLE_MATH_FUNCTIONS 1 |
| #endif |
| #ifndef SQLITE_ENABLE_OFFSET_SQL_FUNC |
| # define SQLITE_ENABLE_OFFSET_SQL_FUNC 1 |
| #endif |
| #ifndef SQLITE_ENABLE_PREUPDATE_HOOK |
| # define SQLITE_ENABLE_PREUPDATE_HOOK 1 /*required by session extension*/ |
| #endif |
| #ifndef SQLITE_ENABLE_RTREE |
| # define SQLITE_ENABLE_RTREE 1 |
| #endif |
| #ifndef SQLITE_ENABLE_SESSION |
| # define SQLITE_ENABLE_SESSION 1 |
| #endif |
| #ifndef SQLITE_ENABLE_STMTVTAB |
| # define SQLITE_ENABLE_STMTVTAB 1 |
| #endif |
| #ifndef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION |
| # define SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION |
| #endif |
| |
| /**********************************************************************/ |
| /* SQLITE_O... */ |
| #ifndef SQLITE_OMIT_DEPRECATED |
| # define SQLITE_OMIT_DEPRECATED 1 |
| #endif |
| #ifndef SQLITE_OMIT_LOAD_EXTENSION |
| # define SQLITE_OMIT_LOAD_EXTENSION 1 |
| #endif |
| #ifndef SQLITE_OMIT_SHARED_CACHE |
| # define SQLITE_OMIT_SHARED_CACHE 1 |
| #endif |
| #ifndef SQLITE_OMIT_UTF16 |
| # define SQLITE_OMIT_UTF16 1 |
| #endif |
| #ifndef SQLITE_OS_KV_OPTIONAL |
| # define SQLITE_OS_KV_OPTIONAL 1 |
| #endif |
| |
| /**********************************************************************/ |
| /* SQLITE_S... */ |
| #ifndef SQLITE_STRICT_SUBTYPE |
| # define SQLITE_STRICT_SUBTYPE 1 |
| #endif |
| |
| /**********************************************************************/ |
| /* SQLITE_T... */ |
| #ifndef SQLITE_TEMP_STORE |
| # define SQLITE_TEMP_STORE 2 |
| #endif |
| #ifndef SQLITE_THREADSAFE |
| # define SQLITE_THREADSAFE 0 |
| #endif |
| |
| /**********************************************************************/ |
| /* SQLITE_USE_... */ |
| #ifndef SQLITE_USE_URI |
| # define SQLITE_USE_URI 1 |
| #endif |
| |
| #ifdef SQLITE_WASM_EXTRA_INIT |
| # define SQLITE_EXTRA_INIT sqlite3_wasm_extra_init |
| #endif |
| |
| #include <assert.h> |
| |
| /* |
| ** SQLITE_WASM_EXPORT is functionally identical to EMSCRIPTEN_KEEPALIVE |
| ** but is not Emscripten-specific. It explicitly marks functions for |
| ** export into the target wasm file without requiring explicit listing |
| ** of those functions in Emscripten's -sEXPORTED_FUNCTIONS=... list |
| ** (or equivalent in other build platforms). Any function with neither |
| ** this attribute nor which is listed as an explicit export will not |
| ** be exported from the wasm file (but may still be used internally |
| ** within the wasm file). |
| ** |
| ** The functions in this file (sqlite3-wasm.c) which require exporting |
| ** are marked with this flag. They may also be added to any explicit |
| ** build-time export list but need not be. All of these APIs are |
| ** intended for use only within the project's own JS/WASM code, and |
| ** not by client code, so an argument can be made for reducing their |
| ** visibility by not including them in any build-time export lists. |
| ** |
| ** 2022-09-11: it's not yet _proven_ that this approach works in |
| ** non-Emscripten builds. If not, such builds will need to export |
| ** those using the --export=... wasm-ld flag (or equivalent). As of |
| ** this writing we are tied to Emscripten for various reasons |
| ** and cannot test the library with other build environments. |
| */ |
| #define SQLITE_WASM_EXPORT __attribute__((used,visibility("default"))) |
| // See also: |
| //__attribute__((export_name("theExportedName"), used, visibility("default"))) |
| |
| /* |
| ** Which sqlite3.c we're using needs to be configurable to enable |
| ** building against a custom copy, e.g. the SEE variant. Note that we |
| ** #include the .c file, rather than the header, so that the WASM |
| ** extensions have access to private API internals. |
| ** |
| ** The caveat here is that custom variants need to account for |
| ** exporting any necessary symbols (e.g. sqlite3_activate_see()). We |
| ** cannot export them from here using SQLITE_WASM_EXPORT because that |
| ** attribute (apparently) has to be part of the function definition. |
| */ |
| #ifndef SQLITE_C |
| # define SQLITE_C sqlite3.c /* yes, .c instead of .h. */ |
| #endif |
| #define INC__STRINGIFY_(f) #f |
| #define INC__STRINGIFY(f) INC__STRINGIFY_(f) |
| #include INC__STRINGIFY(SQLITE_C) |
| #undef INC__STRINGIFY_ |
| #undef INC__STRINGIFY |
| #undef SQLITE_C |
| |
| #if defined(__EMSCRIPTEN__) |
| # include <emscripten/console.h> |
| #endif |
| |
| #if 0 |
| /* |
| ** An EXPERIMENT in implementing a stack-based allocator analog to |
| ** Emscripten's stackSave(), stackAlloc(), stackRestore(). |
| ** Unfortunately, this cannot work together with Emscripten because |
| ** Emscripten defines its own native one and we'd stomp on each |
| ** other's memory. Other than that complication, basic tests show it |
| ** to work just fine. |
| ** |
| ** Another option is to malloc() a chunk of our own and call that our |
| ** "stack". |
| */ |
| SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_end(void){ |
| extern void __heap_base |
| /* see https://stackoverflow.com/questions/10038964 */; |
| return &__heap_base; |
| } |
| SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_begin(void){ |
| extern void __data_end; |
| return &__data_end; |
| } |
| static void * pWasmStackPtr = 0; |
| SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_ptr(void){ |
| if(!pWasmStackPtr) pWasmStackPtr = sqlite3_wasm_stack_end(); |
| return pWasmStackPtr; |
| } |
| SQLITE_WASM_EXPORT void sqlite3_wasm_stack_restore(void * p){ |
| pWasmStackPtr = p; |
| } |
| SQLITE_WASM_EXPORT void * sqlite3_wasm_stack_alloc(int n){ |
| if(n<=0) return 0; |
| n = (n + 7) & ~7 /* align to 8-byte boundary */; |
| unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr(); |
| unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin(); |
| if(b + n >= p || b + n < b/*overflow*/) return 0; |
| return pWasmStackPtr = p - n; |
| } |
| #endif /* stack allocator experiment */ |
| |
| /* |
| ** State for the "pseudo-stack" allocator implemented in |
| ** sqlite3_wasm_pstack_xyz(). In order to avoid colliding with |
| ** Emscripten-controled stack space, it carves out a bit of stack |
| ** memory to use for that purpose. This memory ends up in the |
| ** WASM-managed memory, such that routines which manipulate the wasm |
| ** heap can also be used to manipulate this memory. |
| ** |
| ** This particular allocator is intended for small allocations such as |
| ** storage for output pointers. We cannot reasonably size it large |
| ** enough for general-purpose string conversions because some of our |
| ** tests use input files (strings) of 16MB+. |
| */ |
| static unsigned char PStack_mem[512 * 8] = {0}; |
| static struct { |
| unsigned const char * const pBegin;/* Start (inclusive) of memory */ |
| unsigned const char * const pEnd; /* One-after-the-end of memory */ |
| unsigned char * pPos; /* Current stack pointer */ |
| } PStack = { |
| &PStack_mem[0], |
| &PStack_mem[0] + sizeof(PStack_mem), |
| &PStack_mem[0] + sizeof(PStack_mem) |
| }; |
| /* |
| ** Returns the current pstack position. |
| */ |
| SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_ptr(void){ |
| return PStack.pPos; |
| } |
| /* |
| ** Sets the pstack position poitner to p. Results are undefined if the |
| ** given value did not come from sqlite3_wasm_pstack_ptr(). |
| */ |
| SQLITE_WASM_EXPORT void sqlite3_wasm_pstack_restore(unsigned char * p){ |
| assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos); |
| assert(0==((unsigned long long)p & 0x7)); |
| if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){ |
| PStack.pPos = p; |
| } |
| } |
| /* |
| ** Allocate and zero out n bytes from the pstack. Returns a pointer to |
| ** the memory on success, 0 on error (including a negative n value). n |
| ** is always adjusted to be a multiple of 8 and returned memory is |
| ** always zeroed out before returning (because this keeps the client |
| ** JS code from having to do so, and most uses of the pstack will |
| ** call for doing so). |
| */ |
| SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_alloc(int n){ |
| if( n<=0 ) return 0; |
| //if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */; |
| n = (n + 7) & ~7 /* align to 8-byte boundary */; |
| if( PStack.pBegin + n > PStack.pPos /*not enough space left*/ |
| || PStack.pBegin + n <= PStack.pBegin /*overflow*/ ) return 0; |
| memset((PStack.pPos = PStack.pPos - n), 0, (unsigned int)n); |
| return PStack.pPos; |
| } |
| /* |
| ** Return the number of bytes left which can be |
| ** sqlite3_wasm_pstack_alloc()'d. |
| */ |
| SQLITE_WASM_EXPORT int sqlite3_wasm_pstack_remaining(void){ |
| assert(PStack.pPos >= PStack.pBegin); |
| assert(PStack.pPos <= PStack.pEnd); |
| return (int)(PStack.pPos - PStack.pBegin); |
| } |
| |
| /* |
| ** Return the total number of bytes available in the pstack, including |
| ** any space which is currently allocated. This value is a |
| ** compile-time constant. |
| */ |
| SQLITE_WASM_EXPORT int sqlite3_wasm_pstack_quota(void){ |
| return (int)(PStack.pEnd - PStack.pBegin); |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** For purposes of certain hand-crafted C/Wasm function bindings, we |
| ** need a way of reporting errors which is consistent with the rest of |
| ** the C API, as opposed to throwing JS exceptions. To that end, this |
| ** internal-use-only function is a thin proxy around |
| ** sqlite3ErrorWithMessage(). The intent is that it only be used from |
| ** Wasm bindings such as sqlite3_prepare_v2/v3(), and definitely not |
| ** from client code. |
| ** |
| ** Returns err_code. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){ |
| if( db!=0 ){ |
| if( 0!=zMsg ){ |
| const int nMsg = sqlite3Strlen30(zMsg); |
| sqlite3_mutex_enter(sqlite3_db_mutex(db)); |
| sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg); |
| sqlite3_mutex_leave(sqlite3_db_mutex(db)); |
| }else{ |
| sqlite3ErrorWithMsg(db, err_code, NULL); |
| } |
| } |
| return err_code; |
| } |
| |
| #if SQLITE_WASM_TESTS |
| struct WasmTestStruct { |
| int v4; |
| void * ppV; |
| const char * cstr; |
| int64_t v8; |
| void (*xFunc)(void*); |
| }; |
| typedef struct WasmTestStruct WasmTestStruct; |
| SQLITE_WASM_EXPORT |
| void sqlite3_wasm_test_struct(WasmTestStruct * s){ |
| if(s){ |
| s->v4 *= 2; |
| s->v8 = s->v4 * 2; |
| s->ppV = s; |
| s->cstr = __FILE__; |
| if(s->xFunc) s->xFunc(s); |
| } |
| return; |
| } |
| #endif /* SQLITE_WASM_TESTS */ |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. Unlike the |
| ** rest of the sqlite3 API, this part requires C99 for snprintf() and |
| ** variadic macros. |
| ** |
| ** Returns a string containing a JSON-format "enum" of C-level |
| ** constants and struct-related metadata intended to be imported into |
| ** the JS environment. The JSON is initialized the first time this |
| ** function is called and that result is reused for all future calls. |
| ** |
| ** If this function returns NULL then it means that the internal |
| ** buffer is not large enough for the generated JSON and needs to be |
| ** increased. In debug builds that will trigger an assert(). |
| */ |
| SQLITE_WASM_EXPORT |
| const char * sqlite3_wasm_enum_json(void){ |
| static char aBuffer[1024 * 20] = {0} /* where the JSON goes */; |
| int n = 0, nChildren = 0, nStruct = 0 |
| /* output counters for figuring out where commas go */; |
| char * zPos = &aBuffer[1] /* skip first byte for now to help protect |
| ** against a small race condition */; |
| char const * const zEnd = &aBuffer[0] + sizeof(aBuffer) /* one-past-the-end */; |
| if(aBuffer[0]) return aBuffer; |
| /* Leave aBuffer[0] at 0 until the end to help guard against a tiny |
| ** race condition. If this is called twice concurrently, they might |
| ** end up both writing to aBuffer, but they'll both write the same |
| ** thing, so that's okay. If we set byte 0 up front then the 2nd |
| ** instance might return and use the string before the 1st instance |
| ** is done filling it. */ |
| |
| /* Core output macros... */ |
| #define lenCheck assert(zPos < zEnd - 128 \ |
| && "sqlite3_wasm_enum_json() buffer is too small."); \ |
| if( zPos >= zEnd - 128 ) return 0 |
| #define outf(format,...) \ |
| zPos += snprintf(zPos, ((size_t)(zEnd - zPos)), format, __VA_ARGS__); \ |
| lenCheck |
| #define out(TXT) outf("%s",TXT) |
| #define CloseBrace(LEVEL) \ |
| assert(LEVEL<5); memset(zPos, '}', LEVEL); zPos+=LEVEL; lenCheck |
| |
| /* Macros for emitting maps of integer- and string-type macros to |
| ** their values. */ |
| #define DefGroup(KEY) n = 0; \ |
| outf("%s\"" #KEY "\": {",(nChildren++ ? "," : "")); |
| #define DefInt(KEY) \ |
| outf("%s\"%s\": %d", (n++ ? ", " : ""), #KEY, (int)KEY) |
| #define DefStr(KEY) \ |
| outf("%s\"%s\": \"%s\"", (n++ ? ", " : ""), #KEY, KEY) |
| #define _DefGroup CloseBrace(1) |
| |
| /* The following groups are sorted alphabetic by group name. */ |
| DefGroup(access){ |
| DefInt(SQLITE_ACCESS_EXISTS); |
| DefInt(SQLITE_ACCESS_READWRITE); |
| DefInt(SQLITE_ACCESS_READ)/*docs say this is unused*/; |
| } _DefGroup; |
| |
| DefGroup(authorizer){ |
| DefInt(SQLITE_DENY); |
| DefInt(SQLITE_IGNORE); |
| DefInt(SQLITE_CREATE_INDEX); |
| DefInt(SQLITE_CREATE_TABLE); |
| DefInt(SQLITE_CREATE_TEMP_INDEX); |
| DefInt(SQLITE_CREATE_TEMP_TABLE); |
| DefInt(SQLITE_CREATE_TEMP_TRIGGER); |
| DefInt(SQLITE_CREATE_TEMP_VIEW); |
| DefInt(SQLITE_CREATE_TRIGGER); |
| DefInt(SQLITE_CREATE_VIEW); |
| DefInt(SQLITE_DELETE); |
| DefInt(SQLITE_DROP_INDEX); |
| DefInt(SQLITE_DROP_TABLE); |
| DefInt(SQLITE_DROP_TEMP_INDEX); |
| DefInt(SQLITE_DROP_TEMP_TABLE); |
| DefInt(SQLITE_DROP_TEMP_TRIGGER); |
| DefInt(SQLITE_DROP_TEMP_VIEW); |
| DefInt(SQLITE_DROP_TRIGGER); |
| DefInt(SQLITE_DROP_VIEW); |
| DefInt(SQLITE_INSERT); |
| DefInt(SQLITE_PRAGMA); |
| DefInt(SQLITE_READ); |
| DefInt(SQLITE_SELECT); |
| DefInt(SQLITE_TRANSACTION); |
| DefInt(SQLITE_UPDATE); |
| DefInt(SQLITE_ATTACH); |
| DefInt(SQLITE_DETACH); |
| DefInt(SQLITE_ALTER_TABLE); |
| DefInt(SQLITE_REINDEX); |
| DefInt(SQLITE_ANALYZE); |
| DefInt(SQLITE_CREATE_VTABLE); |
| DefInt(SQLITE_DROP_VTABLE); |
| DefInt(SQLITE_FUNCTION); |
| DefInt(SQLITE_SAVEPOINT); |
| //DefInt(SQLITE_COPY) /* No longer used */; |
| DefInt(SQLITE_RECURSIVE); |
| } _DefGroup; |
| |
| DefGroup(blobFinalizers) { |
| /* SQLITE_STATIC/TRANSIENT need to be handled explicitly as |
| ** integers to avoid casting-related warnings. */ |
| out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1"); |
| outf(",\"SQLITE_WASM_DEALLOC\": %lld", |
| (sqlite3_int64)(sqlite3_free)); |
| } _DefGroup; |
| |
| DefGroup(changeset){ |
| DefInt(SQLITE_CHANGESETSTART_INVERT); |
| DefInt(SQLITE_CHANGESETAPPLY_NOSAVEPOINT); |
| DefInt(SQLITE_CHANGESETAPPLY_INVERT); |
| DefInt(SQLITE_CHANGESETAPPLY_IGNORENOOP); |
| |
| DefInt(SQLITE_CHANGESET_DATA); |
| DefInt(SQLITE_CHANGESET_NOTFOUND); |
| DefInt(SQLITE_CHANGESET_CONFLICT); |
| DefInt(SQLITE_CHANGESET_CONSTRAINT); |
| DefInt(SQLITE_CHANGESET_FOREIGN_KEY); |
| |
| DefInt(SQLITE_CHANGESET_OMIT); |
| DefInt(SQLITE_CHANGESET_REPLACE); |
| DefInt(SQLITE_CHANGESET_ABORT); |
| } _DefGroup; |
| |
| DefGroup(config){ |
| DefInt(SQLITE_CONFIG_SINGLETHREAD); |
| DefInt(SQLITE_CONFIG_MULTITHREAD); |
| DefInt(SQLITE_CONFIG_SERIALIZED); |
| DefInt(SQLITE_CONFIG_MALLOC); |
| DefInt(SQLITE_CONFIG_GETMALLOC); |
| DefInt(SQLITE_CONFIG_SCRATCH); |
| DefInt(SQLITE_CONFIG_PAGECACHE); |
| DefInt(SQLITE_CONFIG_HEAP); |
| DefInt(SQLITE_CONFIG_MEMSTATUS); |
| DefInt(SQLITE_CONFIG_MUTEX); |
| DefInt(SQLITE_CONFIG_GETMUTEX); |
| /* previously SQLITE_CONFIG_CHUNKALLOC 12 which is now unused. */ |
| DefInt(SQLITE_CONFIG_LOOKASIDE); |
| DefInt(SQLITE_CONFIG_PCACHE); |
| DefInt(SQLITE_CONFIG_GETPCACHE); |
| DefInt(SQLITE_CONFIG_LOG); |
| DefInt(SQLITE_CONFIG_URI); |
| DefInt(SQLITE_CONFIG_PCACHE2); |
| DefInt(SQLITE_CONFIG_GETPCACHE2); |
| DefInt(SQLITE_CONFIG_COVERING_INDEX_SCAN); |
| DefInt(SQLITE_CONFIG_SQLLOG); |
| DefInt(SQLITE_CONFIG_MMAP_SIZE); |
| DefInt(SQLITE_CONFIG_WIN32_HEAPSIZE); |
| DefInt(SQLITE_CONFIG_PCACHE_HDRSZ); |
| DefInt(SQLITE_CONFIG_PMASZ); |
| DefInt(SQLITE_CONFIG_STMTJRNL_SPILL); |
| DefInt(SQLITE_CONFIG_SMALL_MALLOC); |
| DefInt(SQLITE_CONFIG_SORTERREF_SIZE); |
| DefInt(SQLITE_CONFIG_MEMDB_MAXSIZE); |
| } _DefGroup; |
| |
| DefGroup(dataTypes) { |
| DefInt(SQLITE_INTEGER); |
| DefInt(SQLITE_FLOAT); |
| DefInt(SQLITE_TEXT); |
| DefInt(SQLITE_BLOB); |
| DefInt(SQLITE_NULL); |
| } _DefGroup; |
| |
| DefGroup(dbConfig){ |
| DefInt(SQLITE_DBCONFIG_MAINDBNAME); |
| DefInt(SQLITE_DBCONFIG_LOOKASIDE); |
| DefInt(SQLITE_DBCONFIG_ENABLE_FKEY); |
| DefInt(SQLITE_DBCONFIG_ENABLE_TRIGGER); |
| DefInt(SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER); |
| DefInt(SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION); |
| DefInt(SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE); |
| DefInt(SQLITE_DBCONFIG_ENABLE_QPSG); |
| DefInt(SQLITE_DBCONFIG_TRIGGER_EQP); |
| DefInt(SQLITE_DBCONFIG_RESET_DATABASE); |
| DefInt(SQLITE_DBCONFIG_DEFENSIVE); |
| DefInt(SQLITE_DBCONFIG_WRITABLE_SCHEMA); |
| DefInt(SQLITE_DBCONFIG_LEGACY_ALTER_TABLE); |
| DefInt(SQLITE_DBCONFIG_DQS_DML); |
| DefInt(SQLITE_DBCONFIG_DQS_DDL); |
| DefInt(SQLITE_DBCONFIG_ENABLE_VIEW); |
| DefInt(SQLITE_DBCONFIG_LEGACY_FILE_FORMAT); |
| DefInt(SQLITE_DBCONFIG_TRUSTED_SCHEMA); |
| DefInt(SQLITE_DBCONFIG_STMT_SCANSTATUS); |
| DefInt(SQLITE_DBCONFIG_REVERSE_SCANORDER); |
| DefInt(SQLITE_DBCONFIG_MAX); |
| } _DefGroup; |
| |
| DefGroup(dbStatus){ |
| DefInt(SQLITE_DBSTATUS_LOOKASIDE_USED); |
| DefInt(SQLITE_DBSTATUS_CACHE_USED); |
| DefInt(SQLITE_DBSTATUS_SCHEMA_USED); |
| DefInt(SQLITE_DBSTATUS_STMT_USED); |
| DefInt(SQLITE_DBSTATUS_LOOKASIDE_HIT); |
| DefInt(SQLITE_DBSTATUS_LOOKASIDE_MISS_SIZE); |
| DefInt(SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL); |
| DefInt(SQLITE_DBSTATUS_CACHE_HIT); |
| DefInt(SQLITE_DBSTATUS_CACHE_MISS); |
| DefInt(SQLITE_DBSTATUS_CACHE_WRITE); |
| DefInt(SQLITE_DBSTATUS_DEFERRED_FKS); |
| DefInt(SQLITE_DBSTATUS_CACHE_USED_SHARED); |
| DefInt(SQLITE_DBSTATUS_CACHE_SPILL); |
| DefInt(SQLITE_DBSTATUS_MAX); |
| } _DefGroup; |
| |
| DefGroup(encodings) { |
| /* Noting that the wasm binding only aims to support UTF-8. */ |
| DefInt(SQLITE_UTF8); |
| DefInt(SQLITE_UTF16LE); |
| DefInt(SQLITE_UTF16BE); |
| DefInt(SQLITE_UTF16); |
| /*deprecated DefInt(SQLITE_ANY); */ |
| DefInt(SQLITE_UTF16_ALIGNED); |
| } _DefGroup; |
| |
| DefGroup(fcntl) { |
| DefInt(SQLITE_FCNTL_LOCKSTATE); |
| DefInt(SQLITE_FCNTL_GET_LOCKPROXYFILE); |
| DefInt(SQLITE_FCNTL_SET_LOCKPROXYFILE); |
| DefInt(SQLITE_FCNTL_LAST_ERRNO); |
| DefInt(SQLITE_FCNTL_SIZE_HINT); |
| DefInt(SQLITE_FCNTL_CHUNK_SIZE); |
| DefInt(SQLITE_FCNTL_FILE_POINTER); |
| DefInt(SQLITE_FCNTL_SYNC_OMITTED); |
| DefInt(SQLITE_FCNTL_WIN32_AV_RETRY); |
| DefInt(SQLITE_FCNTL_PERSIST_WAL); |
| DefInt(SQLITE_FCNTL_OVERWRITE); |
| DefInt(SQLITE_FCNTL_VFSNAME); |
| DefInt(SQLITE_FCNTL_POWERSAFE_OVERWRITE); |
| DefInt(SQLITE_FCNTL_PRAGMA); |
| DefInt(SQLITE_FCNTL_BUSYHANDLER); |
| DefInt(SQLITE_FCNTL_TEMPFILENAME); |
| DefInt(SQLITE_FCNTL_MMAP_SIZE); |
| DefInt(SQLITE_FCNTL_TRACE); |
| DefInt(SQLITE_FCNTL_HAS_MOVED); |
| DefInt(SQLITE_FCNTL_SYNC); |
| DefInt(SQLITE_FCNTL_COMMIT_PHASETWO); |
| DefInt(SQLITE_FCNTL_WIN32_SET_HANDLE); |
| DefInt(SQLITE_FCNTL_WAL_BLOCK); |
| DefInt(SQLITE_FCNTL_ZIPVFS); |
| DefInt(SQLITE_FCNTL_RBU); |
| DefInt(SQLITE_FCNTL_VFS_POINTER); |
| DefInt(SQLITE_FCNTL_JOURNAL_POINTER); |
| DefInt(SQLITE_FCNTL_WIN32_GET_HANDLE); |
| DefInt(SQLITE_FCNTL_PDB); |
| DefInt(SQLITE_FCNTL_BEGIN_ATOMIC_WRITE); |
| DefInt(SQLITE_FCNTL_COMMIT_ATOMIC_WRITE); |
| DefInt(SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE); |
| DefInt(SQLITE_FCNTL_LOCK_TIMEOUT); |
| DefInt(SQLITE_FCNTL_DATA_VERSION); |
| DefInt(SQLITE_FCNTL_SIZE_LIMIT); |
| DefInt(SQLITE_FCNTL_CKPT_DONE); |
| DefInt(SQLITE_FCNTL_RESERVE_BYTES); |
| DefInt(SQLITE_FCNTL_CKPT_START); |
| DefInt(SQLITE_FCNTL_EXTERNAL_READER); |
| DefInt(SQLITE_FCNTL_CKSM_FILE); |
| DefInt(SQLITE_FCNTL_RESET_CACHE); |
| } _DefGroup; |
| |
| DefGroup(flock) { |
| DefInt(SQLITE_LOCK_NONE); |
| DefInt(SQLITE_LOCK_SHARED); |
| DefInt(SQLITE_LOCK_RESERVED); |
| DefInt(SQLITE_LOCK_PENDING); |
| DefInt(SQLITE_LOCK_EXCLUSIVE); |
| } _DefGroup; |
| |
| DefGroup(ioCap) { |
| DefInt(SQLITE_IOCAP_ATOMIC); |
| DefInt(SQLITE_IOCAP_ATOMIC512); |
| DefInt(SQLITE_IOCAP_ATOMIC1K); |
| DefInt(SQLITE_IOCAP_ATOMIC2K); |
| DefInt(SQLITE_IOCAP_ATOMIC4K); |
| DefInt(SQLITE_IOCAP_ATOMIC8K); |
| DefInt(SQLITE_IOCAP_ATOMIC16K); |
| DefInt(SQLITE_IOCAP_ATOMIC32K); |
| DefInt(SQLITE_IOCAP_ATOMIC64K); |
| DefInt(SQLITE_IOCAP_SAFE_APPEND); |
| DefInt(SQLITE_IOCAP_SEQUENTIAL); |
| DefInt(SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN); |
| DefInt(SQLITE_IOCAP_POWERSAFE_OVERWRITE); |
| DefInt(SQLITE_IOCAP_IMMUTABLE); |
| DefInt(SQLITE_IOCAP_BATCH_ATOMIC); |
| } _DefGroup; |
| |
| DefGroup(limits) { |
| DefInt(SQLITE_MAX_ALLOCATION_SIZE); |
| DefInt(SQLITE_LIMIT_LENGTH); |
| DefInt(SQLITE_MAX_LENGTH); |
| DefInt(SQLITE_LIMIT_SQL_LENGTH); |
| DefInt(SQLITE_MAX_SQL_LENGTH); |
| DefInt(SQLITE_LIMIT_COLUMN); |
| DefInt(SQLITE_MAX_COLUMN); |
| DefInt(SQLITE_LIMIT_EXPR_DEPTH); |
| DefInt(SQLITE_MAX_EXPR_DEPTH); |
| DefInt(SQLITE_LIMIT_COMPOUND_SELECT); |
| DefInt(SQLITE_MAX_COMPOUND_SELECT); |
| DefInt(SQLITE_LIMIT_VDBE_OP); |
| DefInt(SQLITE_MAX_VDBE_OP); |
| DefInt(SQLITE_LIMIT_FUNCTION_ARG); |
| DefInt(SQLITE_MAX_FUNCTION_ARG); |
| DefInt(SQLITE_LIMIT_ATTACHED); |
| DefInt(SQLITE_MAX_ATTACHED); |
| DefInt(SQLITE_LIMIT_LIKE_PATTERN_LENGTH); |
| DefInt(SQLITE_MAX_LIKE_PATTERN_LENGTH); |
| DefInt(SQLITE_LIMIT_VARIABLE_NUMBER); |
| DefInt(SQLITE_MAX_VARIABLE_NUMBER); |
| DefInt(SQLITE_LIMIT_TRIGGER_DEPTH); |
| DefInt(SQLITE_MAX_TRIGGER_DEPTH); |
| DefInt(SQLITE_LIMIT_WORKER_THREADS); |
| DefInt(SQLITE_MAX_WORKER_THREADS); |
| } _DefGroup; |
| |
| DefGroup(openFlags) { |
| /* Noting that not all of these will have any effect in |
| ** WASM-space. */ |
| DefInt(SQLITE_OPEN_READONLY); |
| DefInt(SQLITE_OPEN_READWRITE); |
| DefInt(SQLITE_OPEN_CREATE); |
| DefInt(SQLITE_OPEN_URI); |
| DefInt(SQLITE_OPEN_MEMORY); |
| DefInt(SQLITE_OPEN_NOMUTEX); |
| DefInt(SQLITE_OPEN_FULLMUTEX); |
| DefInt(SQLITE_OPEN_SHAREDCACHE); |
| DefInt(SQLITE_OPEN_PRIVATECACHE); |
| DefInt(SQLITE_OPEN_EXRESCODE); |
| DefInt(SQLITE_OPEN_NOFOLLOW); |
| /* OPEN flags for use with VFSes... */ |
| DefInt(SQLITE_OPEN_MAIN_DB); |
| DefInt(SQLITE_OPEN_MAIN_JOURNAL); |
| DefInt(SQLITE_OPEN_TEMP_DB); |
| DefInt(SQLITE_OPEN_TEMP_JOURNAL); |
| DefInt(SQLITE_OPEN_TRANSIENT_DB); |
| DefInt(SQLITE_OPEN_SUBJOURNAL); |
| DefInt(SQLITE_OPEN_SUPER_JOURNAL); |
| DefInt(SQLITE_OPEN_WAL); |
| DefInt(SQLITE_OPEN_DELETEONCLOSE); |
| DefInt(SQLITE_OPEN_EXCLUSIVE); |
| } _DefGroup; |
| |
| DefGroup(prepareFlags) { |
| DefInt(SQLITE_PREPARE_PERSISTENT); |
| DefInt(SQLITE_PREPARE_NORMALIZE); |
| DefInt(SQLITE_PREPARE_NO_VTAB); |
| } _DefGroup; |
| |
| DefGroup(resultCodes) { |
| DefInt(SQLITE_OK); |
| DefInt(SQLITE_ERROR); |
| DefInt(SQLITE_INTERNAL); |
| DefInt(SQLITE_PERM); |
| DefInt(SQLITE_ABORT); |
| DefInt(SQLITE_BUSY); |
| DefInt(SQLITE_LOCKED); |
| DefInt(SQLITE_NOMEM); |
| DefInt(SQLITE_READONLY); |
| DefInt(SQLITE_INTERRUPT); |
| DefInt(SQLITE_IOERR); |
| DefInt(SQLITE_CORRUPT); |
| DefInt(SQLITE_NOTFOUND); |
| DefInt(SQLITE_FULL); |
| DefInt(SQLITE_CANTOPEN); |
| DefInt(SQLITE_PROTOCOL); |
| DefInt(SQLITE_EMPTY); |
| DefInt(SQLITE_SCHEMA); |
| DefInt(SQLITE_TOOBIG); |
| DefInt(SQLITE_CONSTRAINT); |
| DefInt(SQLITE_MISMATCH); |
| DefInt(SQLITE_MISUSE); |
| DefInt(SQLITE_NOLFS); |
| DefInt(SQLITE_AUTH); |
| DefInt(SQLITE_FORMAT); |
| DefInt(SQLITE_RANGE); |
| DefInt(SQLITE_NOTADB); |
| DefInt(SQLITE_NOTICE); |
| DefInt(SQLITE_WARNING); |
| DefInt(SQLITE_ROW); |
| DefInt(SQLITE_DONE); |
| // Extended Result Codes |
| DefInt(SQLITE_ERROR_MISSING_COLLSEQ); |
| DefInt(SQLITE_ERROR_RETRY); |
| DefInt(SQLITE_ERROR_SNAPSHOT); |
| DefInt(SQLITE_IOERR_READ); |
| DefInt(SQLITE_IOERR_SHORT_READ); |
| DefInt(SQLITE_IOERR_WRITE); |
| DefInt(SQLITE_IOERR_FSYNC); |
| DefInt(SQLITE_IOERR_DIR_FSYNC); |
| DefInt(SQLITE_IOERR_TRUNCATE); |
| DefInt(SQLITE_IOERR_FSTAT); |
| DefInt(SQLITE_IOERR_UNLOCK); |
| DefInt(SQLITE_IOERR_RDLOCK); |
| DefInt(SQLITE_IOERR_DELETE); |
| DefInt(SQLITE_IOERR_BLOCKED); |
| DefInt(SQLITE_IOERR_NOMEM); |
| DefInt(SQLITE_IOERR_ACCESS); |
| DefInt(SQLITE_IOERR_CHECKRESERVEDLOCK); |
| DefInt(SQLITE_IOERR_LOCK); |
| DefInt(SQLITE_IOERR_CLOSE); |
| DefInt(SQLITE_IOERR_DIR_CLOSE); |
| DefInt(SQLITE_IOERR_SHMOPEN); |
| DefInt(SQLITE_IOERR_SHMSIZE); |
| DefInt(SQLITE_IOERR_SHMLOCK); |
| DefInt(SQLITE_IOERR_SHMMAP); |
| DefInt(SQLITE_IOERR_SEEK); |
| DefInt(SQLITE_IOERR_DELETE_NOENT); |
| DefInt(SQLITE_IOERR_MMAP); |
| DefInt(SQLITE_IOERR_GETTEMPPATH); |
| DefInt(SQLITE_IOERR_CONVPATH); |
| DefInt(SQLITE_IOERR_VNODE); |
| DefInt(SQLITE_IOERR_AUTH); |
| DefInt(SQLITE_IOERR_BEGIN_ATOMIC); |
| DefInt(SQLITE_IOERR_COMMIT_ATOMIC); |
| DefInt(SQLITE_IOERR_ROLLBACK_ATOMIC); |
| DefInt(SQLITE_IOERR_DATA); |
| DefInt(SQLITE_IOERR_CORRUPTFS); |
| DefInt(SQLITE_LOCKED_SHAREDCACHE); |
| DefInt(SQLITE_LOCKED_VTAB); |
| DefInt(SQLITE_BUSY_RECOVERY); |
| DefInt(SQLITE_BUSY_SNAPSHOT); |
| DefInt(SQLITE_BUSY_TIMEOUT); |
| DefInt(SQLITE_CANTOPEN_NOTEMPDIR); |
| DefInt(SQLITE_CANTOPEN_ISDIR); |
| DefInt(SQLITE_CANTOPEN_FULLPATH); |
| DefInt(SQLITE_CANTOPEN_CONVPATH); |
| //DefInt(SQLITE_CANTOPEN_DIRTYWAL)/*docs say not used*/; |
| DefInt(SQLITE_CANTOPEN_SYMLINK); |
| DefInt(SQLITE_CORRUPT_VTAB); |
| DefInt(SQLITE_CORRUPT_SEQUENCE); |
| DefInt(SQLITE_CORRUPT_INDEX); |
| DefInt(SQLITE_READONLY_RECOVERY); |
| DefInt(SQLITE_READONLY_CANTLOCK); |
| DefInt(SQLITE_READONLY_ROLLBACK); |
| DefInt(SQLITE_READONLY_DBMOVED); |
| DefInt(SQLITE_READONLY_CANTINIT); |
| DefInt(SQLITE_READONLY_DIRECTORY); |
| DefInt(SQLITE_ABORT_ROLLBACK); |
| DefInt(SQLITE_CONSTRAINT_CHECK); |
| DefInt(SQLITE_CONSTRAINT_COMMITHOOK); |
| DefInt(SQLITE_CONSTRAINT_FOREIGNKEY); |
| DefInt(SQLITE_CONSTRAINT_FUNCTION); |
| DefInt(SQLITE_CONSTRAINT_NOTNULL); |
| DefInt(SQLITE_CONSTRAINT_PRIMARYKEY); |
| DefInt(SQLITE_CONSTRAINT_TRIGGER); |
| DefInt(SQLITE_CONSTRAINT_UNIQUE); |
| DefInt(SQLITE_CONSTRAINT_VTAB); |
| DefInt(SQLITE_CONSTRAINT_ROWID); |
| DefInt(SQLITE_CONSTRAINT_PINNED); |
| DefInt(SQLITE_CONSTRAINT_DATATYPE); |
| DefInt(SQLITE_NOTICE_RECOVER_WAL); |
| DefInt(SQLITE_NOTICE_RECOVER_ROLLBACK); |
| DefInt(SQLITE_WARNING_AUTOINDEX); |
| DefInt(SQLITE_AUTH_USER); |
| DefInt(SQLITE_OK_LOAD_PERMANENTLY); |
| //DefInt(SQLITE_OK_SYMLINK) /* internal use only */; |
| } _DefGroup; |
| |
| DefGroup(serialize){ |
| DefInt(SQLITE_SERIALIZE_NOCOPY); |
| DefInt(SQLITE_DESERIALIZE_FREEONCLOSE); |
| DefInt(SQLITE_DESERIALIZE_READONLY); |
| DefInt(SQLITE_DESERIALIZE_RESIZEABLE); |
| } _DefGroup; |
| |
| DefGroup(session){ |
| DefInt(SQLITE_SESSION_CONFIG_STRMSIZE); |
| DefInt(SQLITE_SESSION_OBJCONFIG_SIZE); |
| } _DefGroup; |
| |
| DefGroup(sqlite3Status){ |
| DefInt(SQLITE_STATUS_MEMORY_USED); |
| DefInt(SQLITE_STATUS_PAGECACHE_USED); |
| DefInt(SQLITE_STATUS_PAGECACHE_OVERFLOW); |
| //DefInt(SQLITE_STATUS_SCRATCH_USED) /* NOT USED */; |
| //DefInt(SQLITE_STATUS_SCRATCH_OVERFLOW) /* NOT USED */; |
| DefInt(SQLITE_STATUS_MALLOC_SIZE); |
| DefInt(SQLITE_STATUS_PARSER_STACK); |
| DefInt(SQLITE_STATUS_PAGECACHE_SIZE); |
| //DefInt(SQLITE_STATUS_SCRATCH_SIZE) /* NOT USED */; |
| DefInt(SQLITE_STATUS_MALLOC_COUNT); |
| } _DefGroup; |
| |
| DefGroup(stmtStatus){ |
| DefInt(SQLITE_STMTSTATUS_FULLSCAN_STEP); |
| DefInt(SQLITE_STMTSTATUS_SORT); |
| DefInt(SQLITE_STMTSTATUS_AUTOINDEX); |
| DefInt(SQLITE_STMTSTATUS_VM_STEP); |
| DefInt(SQLITE_STMTSTATUS_REPREPARE); |
| DefInt(SQLITE_STMTSTATUS_RUN); |
| DefInt(SQLITE_STMTSTATUS_FILTER_MISS); |
| DefInt(SQLITE_STMTSTATUS_FILTER_HIT); |
| DefInt(SQLITE_STMTSTATUS_MEMUSED); |
| } _DefGroup; |
| |
| DefGroup(syncFlags) { |
| DefInt(SQLITE_SYNC_NORMAL); |
| DefInt(SQLITE_SYNC_FULL); |
| DefInt(SQLITE_SYNC_DATAONLY); |
| } _DefGroup; |
| |
| DefGroup(trace) { |
| DefInt(SQLITE_TRACE_STMT); |
| DefInt(SQLITE_TRACE_PROFILE); |
| DefInt(SQLITE_TRACE_ROW); |
| DefInt(SQLITE_TRACE_CLOSE); |
| } _DefGroup; |
| |
| DefGroup(txnState){ |
| DefInt(SQLITE_TXN_NONE); |
| DefInt(SQLITE_TXN_READ); |
| DefInt(SQLITE_TXN_WRITE); |
| } _DefGroup; |
| |
| DefGroup(udfFlags) { |
| DefInt(SQLITE_DETERMINISTIC); |
| DefInt(SQLITE_DIRECTONLY); |
| DefInt(SQLITE_INNOCUOUS); |
| DefInt(SQLITE_SUBTYPE); |
| DefInt(SQLITE_RESULT_SUBTYPE); |
| } _DefGroup; |
| |
| DefGroup(version) { |
| DefInt(SQLITE_VERSION_NUMBER); |
| DefStr(SQLITE_VERSION); |
| DefStr(SQLITE_SOURCE_ID); |
| } _DefGroup; |
| |
| DefGroup(vtab) { |
| DefInt(SQLITE_INDEX_SCAN_UNIQUE); |
| DefInt(SQLITE_INDEX_CONSTRAINT_EQ); |
| DefInt(SQLITE_INDEX_CONSTRAINT_GT); |
| DefInt(SQLITE_INDEX_CONSTRAINT_LE); |
| DefInt(SQLITE_INDEX_CONSTRAINT_LT); |
| DefInt(SQLITE_INDEX_CONSTRAINT_GE); |
| DefInt(SQLITE_INDEX_CONSTRAINT_MATCH); |
| DefInt(SQLITE_INDEX_CONSTRAINT_LIKE); |
| DefInt(SQLITE_INDEX_CONSTRAINT_GLOB); |
| DefInt(SQLITE_INDEX_CONSTRAINT_REGEXP); |
| DefInt(SQLITE_INDEX_CONSTRAINT_NE); |
| DefInt(SQLITE_INDEX_CONSTRAINT_ISNOT); |
| DefInt(SQLITE_INDEX_CONSTRAINT_ISNOTNULL); |
| DefInt(SQLITE_INDEX_CONSTRAINT_ISNULL); |
| DefInt(SQLITE_INDEX_CONSTRAINT_IS); |
| DefInt(SQLITE_INDEX_CONSTRAINT_LIMIT); |
| DefInt(SQLITE_INDEX_CONSTRAINT_OFFSET); |
| DefInt(SQLITE_INDEX_CONSTRAINT_FUNCTION); |
| DefInt(SQLITE_VTAB_CONSTRAINT_SUPPORT); |
| DefInt(SQLITE_VTAB_INNOCUOUS); |
| DefInt(SQLITE_VTAB_DIRECTONLY); |
| DefInt(SQLITE_VTAB_USES_ALL_SCHEMAS); |
| DefInt(SQLITE_ROLLBACK); |
| //DefInt(SQLITE_IGNORE); // Also used by sqlite3_authorizer() callback |
| DefInt(SQLITE_FAIL); |
| //DefInt(SQLITE_ABORT); // Also an error code |
| DefInt(SQLITE_REPLACE); |
| } _DefGroup; |
| |
| #undef DefGroup |
| #undef DefStr |
| #undef DefInt |
| #undef _DefGroup |
| |
| /* |
| ** Emit an array of "StructBinder" struct descripions, which look |
| ** like: |
| ** |
| ** { |
| ** "name": "MyStruct", |
| ** "sizeof": 16, |
| ** "members": { |
| ** "member1": {"offset": 0,"sizeof": 4,"signature": "i"}, |
| ** "member2": {"offset": 4,"sizeof": 4,"signature": "p"}, |
| ** "member3": {"offset": 8,"sizeof": 8,"signature": "j"} |
| ** } |
| ** } |
| ** |
| ** Detailed documentation for those bits are in the docs for the |
| ** Jaccwabyt JS-side component. |
| */ |
| |
| /** Macros for emitting StructBinder description. */ |
| #define StructBinder__(TYPE) \ |
| n = 0; \ |
| outf("%s{", (nStruct++ ? ", " : "")); \ |
| out("\"name\": \"" # TYPE "\","); \ |
| outf("\"sizeof\": %d", (int)sizeof(TYPE)); \ |
| out(",\"members\": {"); |
| #define StructBinder_(T) StructBinder__(T) |
| /** ^^^ indirection needed to expand CurrentStruct */ |
| #define StructBinder StructBinder_(CurrentStruct) |
| #define _StructBinder CloseBrace(2) |
| #define M(MEMBER,SIG) \ |
| outf("%s\"%s\": " \ |
| "{\"offset\":%d,\"sizeof\": %d,\"signature\":\"%s\"}", \ |
| (n++ ? ", " : ""), #MEMBER, \ |
| (int)offsetof(CurrentStruct,MEMBER), \ |
| (int)sizeof(((CurrentStruct*)0)->MEMBER), \ |
| SIG) |
| |
| nStruct = 0; |
| out(", \"structs\": ["); { |
| |
| #define CurrentStruct sqlite3_vfs |
| StructBinder { |
| M(iVersion, "i"); |
| M(szOsFile, "i"); |
| M(mxPathname, "i"); |
| M(pNext, "p"); |
| M(zName, "s"); |
| M(pAppData, "p"); |
| M(xOpen, "i(pppip)"); |
| M(xDelete, "i(ppi)"); |
| M(xAccess, "i(ppip)"); |
| M(xFullPathname, "i(ppip)"); |
| M(xDlOpen, "p(pp)"); |
| M(xDlError, "p(pip)"); |
| M(xDlSym, "p()"); |
| M(xDlClose, "v(pp)"); |
| M(xRandomness, "i(pip)"); |
| M(xSleep, "i(pi)"); |
| M(xCurrentTime, "i(pp)"); |
| M(xGetLastError, "i(pip)"); |
| M(xCurrentTimeInt64, "i(pp)"); |
| M(xSetSystemCall, "i(ppp)"); |
| M(xGetSystemCall, "p(pp)"); |
| M(xNextSystemCall, "p(pp)"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_io_methods |
| StructBinder { |
| M(iVersion, "i"); |
| M(xClose, "i(p)"); |
| M(xRead, "i(ppij)"); |
| M(xWrite, "i(ppij)"); |
| M(xTruncate, "i(pj)"); |
| M(xSync, "i(pi)"); |
| M(xFileSize, "i(pp)"); |
| M(xLock, "i(pi)"); |
| M(xUnlock, "i(pi)"); |
| M(xCheckReservedLock, "i(pp)"); |
| M(xFileControl, "i(pip)"); |
| M(xSectorSize, "i(p)"); |
| M(xDeviceCharacteristics, "i(p)"); |
| M(xShmMap, "i(piiip)"); |
| M(xShmLock, "i(piii)"); |
| M(xShmBarrier, "v(p)"); |
| M(xShmUnmap, "i(pi)"); |
| M(xFetch, "i(pjip)"); |
| M(xUnfetch, "i(pjp)"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_file |
| StructBinder { |
| M(pMethods, "p"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_kvvfs_methods |
| StructBinder { |
| M(xRead, "i(sspi)"); |
| M(xWrite, "i(sss)"); |
| M(xDelete, "i(ss)"); |
| M(nKeySize, "i"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| |
| #define CurrentStruct sqlite3_vtab |
| StructBinder { |
| M(pModule, "p"); |
| M(nRef, "i"); |
| M(zErrMsg, "p"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_vtab_cursor |
| StructBinder { |
| M(pVtab, "p"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_module |
| StructBinder { |
| M(iVersion, "i"); |
| M(xCreate, "i(ppippp)"); |
| M(xConnect, "i(ppippp)"); |
| M(xBestIndex, "i(pp)"); |
| M(xDisconnect, "i(p)"); |
| M(xDestroy, "i(p)"); |
| M(xOpen, "i(pp)"); |
| M(xClose, "i(p)"); |
| M(xFilter, "i(pisip)"); |
| M(xNext, "i(p)"); |
| M(xEof, "i(p)"); |
| M(xColumn, "i(ppi)"); |
| M(xRowid, "i(pp)"); |
| M(xUpdate, "i(pipp)"); |
| M(xBegin, "i(p)"); |
| M(xSync, "i(p)"); |
| M(xCommit, "i(p)"); |
| M(xRollback, "i(p)"); |
| M(xFindFunction, "i(pispp)"); |
| M(xRename, "i(ps)"); |
| // ^^^ v1. v2+ follows... |
| M(xSavepoint, "i(pi)"); |
| M(xRelease, "i(pi)"); |
| M(xRollbackTo, "i(pi)"); |
| // ^^^ v2. v3+ follows... |
| M(xShadowName, "i(s)"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| /** |
| ** Workaround: in order to map the various inner structs from |
| ** sqlite3_index_info, we have to uplift those into constructs we |
| ** can access by type name. These structs _must_ match their |
| ** in-sqlite3_index_info counterparts byte for byte. |
| */ |
| typedef struct { |
| int iColumn; |
| unsigned char op; |
| unsigned char usable; |
| int iTermOffset; |
| } sqlite3_index_constraint; |
| typedef struct { |
| int iColumn; |
| unsigned char desc; |
| } sqlite3_index_orderby; |
| typedef struct { |
| int argvIndex; |
| unsigned char omit; |
| } sqlite3_index_constraint_usage; |
| { /* Validate that the above struct sizeof()s match |
| ** expectations. We could improve upon this by |
| ** checking the offsetof() for each member. */ |
| const sqlite3_index_info siiCheck; |
| #define IndexSzCheck(T,M) \ |
| (sizeof(T) == sizeof(*siiCheck.M)) |
| if(!IndexSzCheck(sqlite3_index_constraint,aConstraint) |
| || !IndexSzCheck(sqlite3_index_orderby,aOrderBy) |
| || !IndexSzCheck(sqlite3_index_constraint_usage,aConstraintUsage)){ |
| assert(!"sizeof mismatch in sqlite3_index_... struct(s)"); |
| return 0; |
| } |
| #undef IndexSzCheck |
| } |
| |
| #define CurrentStruct sqlite3_index_constraint |
| StructBinder { |
| M(iColumn, "i"); |
| M(op, "C"); |
| M(usable, "C"); |
| M(iTermOffset, "i"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_index_orderby |
| StructBinder { |
| M(iColumn, "i"); |
| M(desc, "C"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_index_constraint_usage |
| StructBinder { |
| M(argvIndex, "i"); |
| M(omit, "C"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #define CurrentStruct sqlite3_index_info |
| StructBinder { |
| M(nConstraint, "i"); |
| M(aConstraint, "p"); |
| M(nOrderBy, "i"); |
| M(aOrderBy, "p"); |
| M(aConstraintUsage, "p"); |
| M(idxNum, "i"); |
| M(idxStr, "p"); |
| M(needToFreeIdxStr, "i"); |
| M(orderByConsumed, "i"); |
| M(estimatedCost, "d"); |
| M(estimatedRows, "j"); |
| M(idxFlags, "i"); |
| M(colUsed, "j"); |
| } _StructBinder; |
| #undef CurrentStruct |
| |
| #if SQLITE_WASM_TESTS |
| #define CurrentStruct WasmTestStruct |
| StructBinder { |
| M(v4, "i"); |
| M(cstr, "s"); |
| M(ppV, "p"); |
| M(v8, "j"); |
| M(xFunc, "v(p)"); |
| } _StructBinder; |
| #undef CurrentStruct |
| #endif |
| |
| } out( "]"/*structs*/); |
| |
| out("}"/*top-level object*/); |
| *zPos = 0; |
| aBuffer[0] = '{'/*end of the race-condition workaround*/; |
| return aBuffer; |
| #undef StructBinder |
| #undef StructBinder_ |
| #undef StructBinder__ |
| #undef M |
| #undef _StructBinder |
| #undef CloseBrace |
| #undef out |
| #undef outf |
| #undef lenCheck |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** This function invokes the xDelete method of the given VFS (or the |
| ** default VFS if pVfs is NULL), passing on the given filename. If |
| ** zName is NULL, no default VFS is found, or it has no xDelete |
| ** method, SQLITE_MISUSE is returned, else the result of the xDelete() |
| ** call is returned. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_vfs_unlink(sqlite3_vfs *pVfs, const char *zName){ |
| int rc = SQLITE_MISUSE /* ??? */; |
| if( 0==pVfs && 0!=zName ) pVfs = sqlite3_vfs_find(0); |
| if( zName && pVfs && pVfs->xDelete ){ |
| rc = pVfs->xDelete(pVfs, zName, 1); |
| } |
| return rc; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Returns a pointer to the given DB's VFS for the given DB name, |
| ** defaulting to "main" if zDbName is 0. Returns 0 if no db with the |
| ** given name is open. |
| */ |
| SQLITE_WASM_EXPORT |
| sqlite3_vfs * sqlite3_wasm_db_vfs(sqlite3 *pDb, const char *zDbName){ |
| sqlite3_vfs * pVfs = 0; |
| sqlite3_file_control(pDb, zDbName ? zDbName : "main", |
| SQLITE_FCNTL_VFS_POINTER, &pVfs); |
| return pVfs; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** This function resets the given db pointer's database as described at |
| ** |
| ** https://sqlite.org/c3ref/c_dbconfig_defensive.html#sqlitedbconfigresetdatabase |
| ** |
| ** But beware: virtual tables destroyed that way do not have their |
| ** xDestroy() called, so will leak if they require that function for |
| ** proper cleanup. |
| ** |
| ** Returns 0 on success, an SQLITE_xxx code on error. Returns |
| ** SQLITE_MISUSE if pDb is NULL. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_reset(sqlite3 *pDb){ |
| int rc = SQLITE_MISUSE; |
| if( pDb ){ |
| sqlite3_table_column_metadata(pDb, "main", 0, 0, 0, 0, 0, 0, 0); |
| rc = sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); |
| if( 0==rc ){ |
| rc = sqlite3_exec(pDb, "VACUUM", 0, 0, 0); |
| sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0); |
| } |
| } |
| return rc; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Uses the given database's VFS xRead to stream the db file's |
| ** contents out to the given callback. The callback gets a single |
| ** chunk of size n (its 2nd argument) on each call and must return 0 |
| ** on success, non-0 on error. This function returns 0 on success, |
| ** SQLITE_NOTFOUND if no db is open, or propagates any other non-0 |
| ** code from the callback. Note that this is not thread-friendly: it |
| ** expects that it will be the only thread reading the db file and |
| ** takes no measures to ensure that is the case. |
| ** |
| ** This implementation appears to work fine, but |
| ** sqlite3_wasm_db_serialize() is arguably the better way to achieve |
| ** this. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_export_chunked( sqlite3* pDb, |
| int (*xCallback)(unsigned const char *zOut, int n) ){ |
| sqlite3_int64 nSize = 0; |
| sqlite3_int64 nPos = 0; |
| sqlite3_file * pFile = 0; |
| unsigned char buf[1024 * 8]; |
| int nBuf = (int)sizeof(buf); |
| int rc = pDb |
| ? sqlite3_file_control(pDb, "main", |
| SQLITE_FCNTL_FILE_POINTER, &pFile) |
| : SQLITE_NOTFOUND; |
| if( rc ) return rc; |
| rc = pFile->pMethods->xFileSize(pFile, &nSize); |
| if( rc ) return rc; |
| if(nSize % nBuf){ |
| /* DB size is not an even multiple of the buffer size. Reduce |
| ** buffer size so that we do not unduly inflate the db size |
| ** with zero-padding when exporting. */ |
| if(0 == nSize % 4096) nBuf = 4096; |
| else if(0 == nSize % 2048) nBuf = 2048; |
| else if(0 == nSize % 1024) nBuf = 1024; |
| else nBuf = 512; |
| } |
| for( ; 0==rc && nPos<nSize; nPos += nBuf ){ |
| rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos); |
| if( SQLITE_IOERR_SHORT_READ == rc ){ |
| rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/; |
| } |
| if( 0==rc ) rc = xCallback(buf, nBuf); |
| } |
| return rc; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** A proxy for sqlite3_serialize() which serializes the schema zSchema |
| ** of pDb, placing the serialized output in pOut and nOut. nOut may be |
| ** NULL. If zSchema is NULL then "main" is assumed. If pDb or pOut are |
| ** NULL then SQLITE_MISUSE is returned. If allocation of the |
| ** serialized copy fails, SQLITE_NOMEM is returned. On success, 0 is |
| ** returned and `*pOut` will contain a pointer to the memory unless |
| ** mFlags includes SQLITE_SERIALIZE_NOCOPY and the database has no |
| ** contiguous memory representation, in which case `*pOut` will be |
| ** NULL but 0 will be returned. |
| ** |
| ** If `*pOut` is not NULL, the caller is responsible for passing it to |
| ** sqlite3_free() to free it. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema, |
| unsigned char **pOut, |
| sqlite3_int64 *nOut, unsigned int mFlags ){ |
| unsigned char * z; |
| if( !pDb || !pOut ) return SQLITE_MISUSE; |
| if( nOut ) *nOut = 0; |
| z = sqlite3_serialize(pDb, zSchema ? zSchema : "main", nOut, mFlags); |
| if( z || (SQLITE_SERIALIZE_NOCOPY & mFlags) ){ |
| *pOut = z; |
| return 0; |
| }else{ |
| return SQLITE_NOMEM; |
| } |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** ACHTUNG: it was discovered on 2023-08-11 that, with SQLITE_DEBUG, |
| ** this function's out-of-scope use of the sqlite3_vfs/file/io_methods |
| ** APIs leads to triggering of assertions in the core library. Its use |
| ** is now deprecated and VFS-specific APIs for importing files need to |
| ** be found to replace it. sqlite3_wasm_posix_create_file() is |
| ** suitable for the "unix" family of VFSes. |
| ** |
| ** Creates a new file using the I/O API of the given VFS, containing |
| ** the given number of bytes of the given data. If the file exists, it |
| ** is truncated to the given length and populated with the given |
| ** data. |
| ** |
| ** This function exists so that we can implement the equivalent of |
| ** Emscripten's FS.createDataFile() in a VFS-agnostic way. This |
| ** functionality is intended for use in uploading database files. |
| ** |
| ** Not all VFSes support this functionality, e.g. the "kvvfs" does |
| ** not. |
| ** |
| ** If pVfs is NULL, sqlite3_vfs_find(0) is used. |
| ** |
| ** If zFile is NULL, pVfs is NULL (and sqlite3_vfs_find(0) returns |
| ** NULL), or nData is negative, SQLITE_MISUSE are returned. |
| ** |
| ** On success, it creates a new file with the given name, populated |
| ** with the fist nData bytes of pData. If pData is NULL, the file is |
| ** created and/or truncated to nData bytes. |
| ** |
| ** Whether or not directory components of zFilename are created |
| ** automatically or not is unspecified: that detail is left to the |
| ** VFS. The "opfs" VFS, for example, creates them. |
| ** |
| ** If an error happens while populating or truncating the file, the |
| ** target file will be deleted (if needed) if this function created |
| ** it. If this function did not create it, it is not deleted but may |
| ** be left in an undefined state. |
| ** |
| ** Returns 0 on success. On error, it returns a code described above |
| ** or propagates a code from one of the I/O methods. |
| ** |
| ** Design note: nData is an integer, instead of int64, for WASM |
| ** portability, so that the API can still work in builds where BigInt |
| ** support is disabled or unavailable. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs, |
| const char *zFilename, |
| const unsigned char * pData, |
| int nData ){ |
| int rc; |
| sqlite3_file *pFile = 0; |
| sqlite3_io_methods const *pIo; |
| const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
| #if 0 && defined(SQLITE_DEBUG) |
| | SQLITE_OPEN_MAIN_JOURNAL |
| /* ^^^^ This is for testing a horrible workaround to avoid |
| triggering a specific assert() in os_unix.c:unixOpen(). Please |
| do not enable this in real builds. */ |
| #endif |
| ; |
| int flagsOut = 0; |
| int fileExisted = 0; |
| int doUnlock = 0; |
| const unsigned char *pPos = pData; |
| const int blockSize = 512 |
| /* Because we are using pFile->pMethods->xWrite() for writing, and |
| ** it may have a buffer limit related to sqlite3's pager size, we |
| ** conservatively write in 512-byte blocks (smallest page |
| ** size). */; |
| //fprintf(stderr, "pVfs=%p, zFilename=%s, nData=%d\n", pVfs, zFilename, nData); |
| if( !pVfs ) pVfs = sqlite3_vfs_find(0); |
| if( !pVfs || !zFilename || nData<0 ) return SQLITE_MISUSE; |
| pVfs->xAccess(pVfs, zFilename, SQLITE_ACCESS_EXISTS, &fileExisted); |
| rc = sqlite3OsOpenMalloc(pVfs, zFilename, &pFile, openFlags, &flagsOut); |
| #if 0 |
| # define RC fprintf(stderr,"create_file(%s,%s) @%d rc=%d\n", \ |
| pVfs->zName, zFilename, __LINE__, rc); |
| #else |
| # define RC |
| #endif |
| RC; |
| if(rc) return rc; |
| pIo = pFile->pMethods; |
| if( pIo->xLock ) { |
| /* We need xLock() in order to accommodate the OPFS VFS, as it |
| ** obtains a writeable handle via the lock operation and releases |
| ** it in xUnlock(). If we don't do those here, we have to add code |
| ** to the VFS to account check whether it was locked before |
| ** xFileSize(), xTruncate(), and the like, and release the lock |
| ** only if it was unlocked when the op was started. */ |
| rc = pIo->xLock(pFile, SQLITE_LOCK_EXCLUSIVE); |
| RC; |
| doUnlock = 0==rc; |
| } |
| if( 0==rc ){ |
| rc = pIo->xTruncate(pFile, nData); |
| RC; |
| } |
| if( 0==rc && 0!=pData && nData>0 ){ |
| while( 0==rc && nData>0 ){ |
| const int n = nData>=blockSize ? blockSize : nData; |
| rc = pIo->xWrite(pFile, pPos, n, (sqlite3_int64)(pPos - pData)); |
| RC; |
| nData -= n; |
| pPos += n; |
| } |
| if( 0==rc && nData>0 ){ |
| assert( nData<blockSize ); |
| rc = pIo->xWrite(pFile, pPos, nData, |
| (sqlite3_int64)(pPos - pData)); |
| RC; |
| } |
| } |
| if( pIo->xUnlock && doUnlock!=0 ){ |
| pIo->xUnlock(pFile, SQLITE_LOCK_NONE); |
| } |
| pIo->xClose(pFile); |
| if( rc!=0 && 0==fileExisted ){ |
| pVfs->xDelete(pVfs, zFilename, 1); |
| } |
| RC; |
| #undef RC |
| return rc; |
| } |
| |
| /** |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Creates or overwrites a file using the POSIX file API, |
| ** i.e. Emscripten's virtual filesystem. Creates or truncates |
| ** zFilename, appends pData bytes to it, and returns 0 on success or |
| ** SQLITE_IOERR on error. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_posix_create_file( const char *zFilename, |
| const unsigned char * pData, |
| int nData ){ |
| int rc; |
| FILE * pFile = 0; |
| int fileExisted = 0; |
| size_t nWrote = 1; |
| |
| if( !zFilename || nData<0 || (pData==0 && nData>0) ) return SQLITE_MISUSE; |
| pFile = fopen(zFilename, "w"); |
| if( 0==pFile ) return SQLITE_IOERR; |
| if( nData>0 ){ |
| nWrote = fwrite(pData, (size_t)nData, 1, pFile); |
| } |
| fclose(pFile); |
| return 1==nWrote ? 0 : SQLITE_IOERR; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Allocates sqlite3KvvfsMethods.nKeySize bytes from |
| ** sqlite3_wasm_pstack_alloc() and returns 0 if that allocation fails, |
| ** else it passes that string to kvstorageMakeKey() and returns a |
| ** NUL-terminated pointer to that string. It is up to the caller to |
| ** use sqlite3_wasm_pstack_restore() to free the returned pointer. |
| */ |
| SQLITE_WASM_EXPORT |
| char * sqlite3_wasm_kvvfsMakeKeyOnPstack(const char *zClass, |
| const char *zKeyIn){ |
| assert(sqlite3KvvfsMethods.nKeySize>24); |
| char *zKeyOut = |
| (char *)sqlite3_wasm_pstack_alloc(sqlite3KvvfsMethods.nKeySize); |
| if(zKeyOut){ |
| kvstorageMakeKey(zClass, zKeyIn, zKeyOut); |
| } |
| return zKeyOut; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Returns the pointer to the singleton object which holds the kvvfs |
| ** I/O methods and associated state. |
| */ |
| SQLITE_WASM_EXPORT |
| sqlite3_kvvfs_methods * sqlite3_wasm_kvvfs_methods(void){ |
| return &sqlite3KvvfsMethods; |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** This is a proxy for the variadic sqlite3_vtab_config() which passes |
| ** its argument on, or not, to sqlite3_vtab_config(), depending on the |
| ** value of its 2nd argument. Returns the result of |
| ** sqlite3_vtab_config(), or SQLITE_MISUSE if the 2nd arg is not a |
| ** valid value. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_vtab_config(sqlite3 *pDb, int op, int arg){ |
| switch(op){ |
| case SQLITE_VTAB_DIRECTONLY: |
| case SQLITE_VTAB_INNOCUOUS: |
| return sqlite3_vtab_config(pDb, op); |
| case SQLITE_VTAB_CONSTRAINT_SUPPORT: |
| return sqlite3_vtab_config(pDb, op, arg); |
| default: |
| return SQLITE_MISUSE; |
| } |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Wrapper for the variants of sqlite3_db_config() which take |
| ** (int,int*) variadic args. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){ |
| switch(op){ |
| case SQLITE_DBCONFIG_ENABLE_FKEY: |
| case SQLITE_DBCONFIG_ENABLE_TRIGGER: |
| case SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: |
| case SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: |
| case SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: |
| case SQLITE_DBCONFIG_ENABLE_QPSG: |
| case SQLITE_DBCONFIG_TRIGGER_EQP: |
| case SQLITE_DBCONFIG_RESET_DATABASE: |
| case SQLITE_DBCONFIG_DEFENSIVE: |
| case SQLITE_DBCONFIG_WRITABLE_SCHEMA: |
| case SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: |
| case SQLITE_DBCONFIG_DQS_DML: |
| case SQLITE_DBCONFIG_DQS_DDL: |
| case SQLITE_DBCONFIG_ENABLE_VIEW: |
| case SQLITE_DBCONFIG_LEGACY_FILE_FORMAT: |
| case SQLITE_DBCONFIG_TRUSTED_SCHEMA: |
| case SQLITE_DBCONFIG_STMT_SCANSTATUS: |
| case SQLITE_DBCONFIG_REVERSE_SCANORDER: |
| return sqlite3_db_config(pDb, op, arg1, pArg2); |
| default: return SQLITE_MISUSE; |
| } |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Wrapper for the variants of sqlite3_db_config() which take |
| ** (void*,int,int) variadic args. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_config_pii(sqlite3 *pDb, int op, void * pArg1, int arg2, int arg3){ |
| switch(op){ |
| case SQLITE_DBCONFIG_LOOKASIDE: |
| return sqlite3_db_config(pDb, op, pArg1, arg2, arg3); |
| default: return SQLITE_MISUSE; |
| } |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Wrapper for the variants of sqlite3_db_config() which take |
| ** (const char *) variadic args. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_db_config_s(sqlite3 *pDb, int op, const char *zArg){ |
| switch(op){ |
| case SQLITE_DBCONFIG_MAINDBNAME: |
| return sqlite3_db_config(pDb, op, zArg); |
| default: return SQLITE_MISUSE; |
| } |
| } |
| |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Binding for combinations of sqlite3_config() arguments which take |
| ** a single integer argument. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_config_i(int op, int arg){ |
| return sqlite3_config(op, arg); |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Binding for combinations of sqlite3_config() arguments which take |
| ** two int arguments. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_config_ii(int op, int arg1, int arg2){ |
| return sqlite3_config(op, arg1, arg2); |
| } |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Binding for combinations of sqlite3_config() arguments which take |
| ** a single i64 argument. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_config_j(int op, sqlite3_int64 arg){ |
| return sqlite3_config(op, arg); |
| } |
| |
| #if 0 |
| // Pending removal after verification of a workaround discussed in the |
| // forum post linked to below. |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings. |
| ** |
| ** Returns a pointer to sqlite3_free(). In compliant browsers the |
| ** return value, when passed to sqlite3.wasm.exports.functionEntry(), |
| ** must resolve to the same function as |
| ** sqlite3.wasm.exports.sqlite3_free. i.e. from a dev console where |
| ** sqlite3 is exported globally, the following must be true: |
| ** |
| ** ``` |
| ** sqlite3.wasm.functionEntry( |
| ** sqlite3.wasm.exports.sqlite3_wasm_ptr_to_sqlite3_free() |
| ** ) === sqlite3.wasm.exports.sqlite3_free |
| ** ``` |
| ** |
| ** Using a function to return this pointer, as opposed to exporting it |
| ** via sqlite3_wasm_enum_json(), is an attempt to work around a |
| ** Safari-specific quirk covered at |
| ** https://sqlite.org/forum/info/e5b20e1feb37a19a. |
| **/ |
| SQLITE_WASM_EXPORT |
| void * sqlite3_wasm_ptr_to_sqlite3_free(void){ |
| return (void*)sqlite3_free; |
| } |
| #endif |
| |
| #if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS) |
| #include <emscripten/wasmfs.h> |
| |
| /* |
| ** This function is NOT part of the sqlite3 public API. It is strictly |
| ** for use by the sqlite project's own JS/WASM bindings, specifically |
| ** only when building with Emscripten's WASMFS support. |
| ** |
| ** This function should only be called if the JS side detects the |
| ** existence of the Origin-Private FileSystem (OPFS) APIs in the |
| ** client. The first time it is called, this function instantiates a |
| ** WASMFS backend impl for OPFS. On success, subsequent calls are |
| ** no-ops. |
| ** |
| ** This function may be passed a "mount point" name, which must have a |
| ** leading "/" and is currently restricted to a single path component, |
| ** e.g. "/foo" is legal but "/foo/" and "/foo/bar" are not. If it is |
| ** NULL or empty, it defaults to "/opfs". |
| ** |
| ** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend |
| ** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in |
| ** the virtual FS fails. In builds compiled without SQLITE_ENABLE_WASMFS |
| ** defined, SQLITE_NOTFOUND is returned without side effects. |
| */ |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_init_wasmfs(const char *zMountPoint){ |
| static backend_t pOpfs = 0; |
| if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs"; |
| if( !pOpfs ){ |
| pOpfs = wasmfs_create_opfs_backend(); |
| } |
| /** It's not enough to instantiate the backend. We have to create a |
| mountpoint in the VFS and attach the backend to it. */ |
| if( pOpfs && 0!=access(zMountPoint, F_OK) ){ |
| /* Note that this check and is not robust but it will |
| hypothetically suffice for the transient wasm-based virtual |
| filesystem we're currently running in. */ |
| const int rc = wasmfs_create_directory(zMountPoint, 0777, pOpfs); |
| /*emscripten_console_logf("OPFS mkdir(%s) rc=%d", zMountPoint, rc);*/ |
| if(rc) return SQLITE_IOERR; |
| } |
| return pOpfs ? 0 : SQLITE_NOMEM; |
| } |
| #else |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_init_wasmfs(const char *zUnused){ |
| //emscripten_console_warn("WASMFS OPFS is not compiled in."); |
| if(zUnused){/*unused*/} |
| return SQLITE_NOTFOUND; |
| } |
| #endif /* __EMSCRIPTEN__ && SQLITE_ENABLE_WASMFS */ |
| |
| #if SQLITE_WASM_TESTS |
| |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_test_intptr(int * p){ |
| return *p = *p * 2; |
| } |
| |
| SQLITE_WASM_EXPORT |
| void * sqlite3_wasm_test_voidptr(void * p){ |
| return p; |
| } |
| |
| SQLITE_WASM_EXPORT |
| int64_t sqlite3_wasm_test_int64_max(void){ |
| return (int64_t)0x7fffffffffffffff; |
| } |
| |
| SQLITE_WASM_EXPORT |
| int64_t sqlite3_wasm_test_int64_min(void){ |
| return ~sqlite3_wasm_test_int64_max(); |
| } |
| |
| SQLITE_WASM_EXPORT |
| int64_t sqlite3_wasm_test_int64_times2(int64_t x){ |
| return x * 2; |
| } |
| |
| SQLITE_WASM_EXPORT |
| void sqlite3_wasm_test_int64_minmax(int64_t * min, int64_t *max){ |
| *max = sqlite3_wasm_test_int64_max(); |
| *min = sqlite3_wasm_test_int64_min(); |
| /*printf("minmax: min=%lld, max=%lld\n", *min, *max);*/ |
| } |
| |
| SQLITE_WASM_EXPORT |
| int64_t sqlite3_wasm_test_int64ptr(int64_t * p){ |
| /*printf("sqlite3_wasm_test_int64ptr( @%lld = 0x%llx )\n", (int64_t)p, *p);*/ |
| return *p = *p * 2; |
| } |
| |
| SQLITE_WASM_EXPORT |
| void sqlite3_wasm_test_stack_overflow(int recurse){ |
| if(recurse) sqlite3_wasm_test_stack_overflow(recurse); |
| } |
| |
| /* For testing the 'string:dealloc' whwasmutil.xWrap() conversion. */ |
| SQLITE_WASM_EXPORT |
| char * sqlite3_wasm_test_str_hello(int fail){ |
| char * s = fail ? 0 : (char *)sqlite3_malloc(6); |
| if(s){ |
| memcpy(s, "hello", 5); |
| s[5] = 0; |
| } |
| return s; |
| } |
| |
| /* |
| ** For testing using SQLTester scripts. |
| ** |
| ** Return non-zero if string z matches glob pattern zGlob and zero if the |
| ** pattern does not match. |
| ** |
| ** To repeat: |
| ** |
| ** zero == no match |
| ** non-zero == match |
| ** |
| ** Globbing rules: |
| ** |
| ** '*' Matches any sequence of zero or more characters. |
| ** |
| ** '?' Matches exactly one character. |
| ** |
| ** [...] Matches one character from the enclosed list of |
| ** characters. |
| ** |
| ** [^...] Matches one character not in the enclosed list. |
| ** |
| ** '#' Matches any sequence of one or more digits with an |
| ** optional + or - sign in front, or a hexadecimal |
| ** literal of the form 0x... |
| */ |
| static int sqlite3_wasm_SQLTester_strnotglob(const char *zGlob, const char *z){ |
| int c, c2; |
| int invert; |
| int seen; |
| typedef int (*recurse_f)(const char *,const char *); |
| static const recurse_f recurse = sqlite3_wasm_SQLTester_strnotglob; |
| |
| while( (c = (*(zGlob++)))!=0 ){ |
| if( c=='*' ){ |
| while( (c=(*(zGlob++))) == '*' || c=='?' ){ |
| if( c=='?' && (*(z++))==0 ) return 0; |
| } |
| if( c==0 ){ |
| return 1; |
| }else if( c=='[' ){ |
| while( *z && recurse(zGlob-1,z)==0 ){ |
| z++; |
| } |
| return (*z)!=0; |
| } |
| while( (c2 = (*(z++)))!=0 ){ |
| while( c2!=c ){ |
| c2 = *(z++); |
| if( c2==0 ) return 0; |
| } |
| if( recurse(zGlob,z) ) return 1; |
| } |
| return 0; |
| }else if( c=='?' ){ |
| if( (*(z++))==0 ) return 0; |
| }else if( c=='[' ){ |
| int prior_c = 0; |
| seen = 0; |
| invert = 0; |
| c = *(z++); |
| if( c==0 ) return 0; |
| c2 = *(zGlob++); |
| if( c2=='^' ){ |
| invert = 1; |
| c2 = *(zGlob++); |
| } |
| if( c2==']' ){ |
| if( c==']' ) seen = 1; |
| c2 = *(zGlob++); |
| } |
| while( c2 && c2!=']' ){ |
| if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){ |
| c2 = *(zGlob++); |
| if( c>=prior_c && c<=c2 ) seen = 1; |
| prior_c = 0; |
| }else{ |
| if( c==c2 ){ |
| seen = 1; |
| } |
| prior_c = c2; |
| } |
| c2 = *(zGlob++); |
| } |
| if( c2==0 || (seen ^ invert)==0 ) return 0; |
| }else if( c=='#' ){ |
| if( z[0]=='0' |
| && (z[1]=='x' || z[1]=='X') |
| && sqlite3Isxdigit(z[2]) |
| ){ |
| z += 3; |
| while( sqlite3Isxdigit(z[0]) ){ z++; } |
| }else{ |
| if( (z[0]=='-' || z[0]=='+') && sqlite3Isdigit(z[1]) ) z++; |
| if( !sqlite3Isdigit(z[0]) ) return 0; |
| z++; |
| while( sqlite3Isdigit(z[0]) ){ z++; } |
| } |
| }else{ |
| if( c!=(*(z++)) ) return 0; |
| } |
| } |
| return *z==0; |
| } |
| |
| SQLITE_WASM_EXPORT |
| int sqlite3_wasm_SQLTester_strglob(const char *zGlob, const char *z){ |
| return !sqlite3_wasm_SQLTester_strnotglob(zGlob, z); |
| } |
| |
| |
| #endif /* SQLITE_WASM_TESTS */ |
| |
| #undef SQLITE_WASM_EXPORT |