173079dbaSstephan /* 273079dbaSstephan ** This file requires access to sqlite3.c static state in order to 36110a5d0Sstephan ** implement certain WASM-specific features, and thus directly 46110a5d0Sstephan ** includes that file. Unlike the rest of sqlite3.c, this file 56110a5d0Sstephan ** requires compiling with -std=c99 (or equivalent, or a later C 66110a5d0Sstephan ** version) because it makes use of features not available in C89. 76110a5d0Sstephan ** 86110a5d0Sstephan ** At it's simplest, to build sqlite3.wasm either place this file 96110a5d0Sstephan ** in the same directory as sqlite3.c/h before compilation or use the 106110a5d0Sstephan ** -I/path flag to tell the compiler where to find both of those 116110a5d0Sstephan ** files, then compile this file. For example: 126110a5d0Sstephan ** 136110a5d0Sstephan ** emcc -o sqlite3.wasm ... -I/path/to/sqlite3-c-and-h sqlite3-wasm.c 1473079dbaSstephan */ 156110a5d0Sstephan 1653d4e01dSstephan /* 1753d4e01dSstephan ** Threading and file locking: JS is single-threaded. Each Worker 1853d4e01dSstephan ** thread is a separate instance of the JS engine so can never access 1953d4e01dSstephan ** the same db handle as another thread, thus multi-threading support 2053d4e01dSstephan ** is unnecessary in the library. Because the filesystems are virtual 2153d4e01dSstephan ** and local to a given wasm runtime instance, two Workers can never 2253d4e01dSstephan ** access the same db file at once, with the exception of OPFS. As of 2353d4e01dSstephan ** this writing (2022-09-30), OPFS exclusively locks a file when 2453d4e01dSstephan ** opening it, so two Workers can never open the same OPFS-backed file 2553d4e01dSstephan ** at once. That situation will change if and when lower-level locking 2653d4e01dSstephan ** features are added to OPFS (as is currently planned, per folks 2753d4e01dSstephan ** involved with its development). 2853d4e01dSstephan ** 2953d4e01dSstephan ** Summary: except for the case of future OPFS, which supports 3053d4e01dSstephan ** locking, and any similar future filesystems, threading and file 3153d4e01dSstephan ** locking support are unnecessary in the wasm build. 3253d4e01dSstephan */ 3353d4e01dSstephan #undef SQLITE_OMIT_DESERIALIZE 346110a5d0Sstephan #ifndef SQLITE_DEFAULT_UNIX_VFS 356110a5d0Sstephan # define SQLITE_DEFAULT_UNIX_VFS "unix-none" 366110a5d0Sstephan #endif 376110a5d0Sstephan #ifndef SQLITE_OMIT_DEPRECATED 386110a5d0Sstephan # define SQLITE_OMIT_DEPRECATED 396110a5d0Sstephan #endif 406110a5d0Sstephan #ifndef SQLITE_OMIT_LOAD_EXTENSION 416110a5d0Sstephan # define SQLITE_OMIT_LOAD_EXTENSION 426110a5d0Sstephan #endif 436110a5d0Sstephan #ifndef SQLITE_OMIT_SHARED_CACHE 446110a5d0Sstephan # define SQLITE_OMIT_SHARED_CACHE 456110a5d0Sstephan #endif 466110a5d0Sstephan #ifndef SQLITE_OMIT_UTF16 476110a5d0Sstephan # define SQLITE_OMIT_UTF16 486110a5d0Sstephan #endif 496110a5d0Sstephan #ifndef SQLITE_OS_KV_OPTIONAL 506110a5d0Sstephan # define SQLITE_OS_KV_OPTIONAL 1 516110a5d0Sstephan #endif 526110a5d0Sstephan #ifndef SQLITE_TEMP_STORE 536110a5d0Sstephan # define SQLITE_TEMP_STORE 3 546110a5d0Sstephan #endif 556110a5d0Sstephan #ifndef SQLITE_THREADSAFE 566110a5d0Sstephan # define SQLITE_THREADSAFE 0 576110a5d0Sstephan #endif 586110a5d0Sstephan 593afad4d4Sstephan #include <assert.h> 606110a5d0Sstephan #include "sqlite3.c" /* yes, .c instead of .h. */ 613961b263Sstephan 6263e9ec2fSstephan #if defined(__EMSCRIPTEN__) 6363e9ec2fSstephan # include <emscripten/console.h> 6463e9ec2fSstephan #endif 6563e9ec2fSstephan 663961b263Sstephan /* 6773079dbaSstephan ** WASM_KEEP is identical to EMSCRIPTEN_KEEPALIVE but is not 6872ab400dSstephan ** Emscripten-specific. It explicitly marks functions for export into 6972ab400dSstephan ** the target wasm file without requiring explicit listing of those 7072ab400dSstephan ** functions in Emscripten's -sEXPORTED_FUNCTIONS=... list (or 7172ab400dSstephan ** equivalent in other build platforms). Any function with neither 7273079dbaSstephan ** this attribute nor which is listed as an explicit export will not 7373079dbaSstephan ** be exported from the wasm file (but may still be used internally 7473079dbaSstephan ** within the wasm file). 7573079dbaSstephan ** 7673079dbaSstephan ** The functions in this file (sqlite3-wasm.c) which require exporting 7773079dbaSstephan ** are marked with this flag. They may also be added to any explicit 7873079dbaSstephan ** build-time export list but need not be. All of these APIs are 7973079dbaSstephan ** intended for use only within the project's own JS/WASM code, and 8073079dbaSstephan ** not by client code, so an argument can be made for reducing their 8173079dbaSstephan ** visibility by not including them in any build-time export lists. 8273079dbaSstephan ** 8373079dbaSstephan ** 2022-09-11: it's not yet _proven_ that this approach works in 8473079dbaSstephan ** non-Emscripten builds. If not, such builds will need to export 8573079dbaSstephan ** those using the --export=... wasm-ld flag (or equivalent). As of 8673079dbaSstephan ** this writing we are tied to Emscripten for various reasons 8773079dbaSstephan ** and cannot test the library with other build environments. 8873079dbaSstephan */ 8973079dbaSstephan #define WASM_KEEP __attribute__((used,visibility("default"))) 9073079dbaSstephan // See also: 9173079dbaSstephan //__attribute__((export_name("theExportedName"), used, visibility("default"))) 9273079dbaSstephan 933afad4d4Sstephan 943afad4d4Sstephan #if 0 953afad4d4Sstephan /* 963afad4d4Sstephan ** An EXPERIMENT in implementing a stack-based allocator analog to 973afad4d4Sstephan ** Emscripten's stackSave(), stackAlloc(), stackRestore(). 983afad4d4Sstephan ** Unfortunately, this cannot work together with Emscripten because 993afad4d4Sstephan ** Emscripten defines its own native one and we'd stomp on each 1003afad4d4Sstephan ** other's memory. Other than that complication, basic tests show it 1013afad4d4Sstephan ** to work just fine. 1023afad4d4Sstephan ** 1033afad4d4Sstephan ** Another option is to malloc() a chunk of our own and call that our 1043afad4d4Sstephan ** "stack". 1053afad4d4Sstephan */ 1063afad4d4Sstephan WASM_KEEP void * sqlite3_wasm_stack_end(void){ 1073afad4d4Sstephan extern void __heap_base 1083afad4d4Sstephan /* see https://stackoverflow.com/questions/10038964 */; 1093afad4d4Sstephan return &__heap_base; 1103afad4d4Sstephan } 1113afad4d4Sstephan WASM_KEEP void * sqlite3_wasm_stack_begin(void){ 1123afad4d4Sstephan extern void __data_end; 1133afad4d4Sstephan return &__data_end; 1143afad4d4Sstephan } 1153afad4d4Sstephan static void * sq3StackPtr = 0; 1163afad4d4Sstephan WASM_KEEP void * sqlite3_wasm_stack_ptr(void){ 1173afad4d4Sstephan if(!sq3StackPtr) sq3StackPtr = sqlite3_wasm_stack_end(); 1183afad4d4Sstephan return sq3StackPtr; 1193afad4d4Sstephan } 1203afad4d4Sstephan WASM_KEEP void sqlite3_wasm_stack_restore(void * p){ 1213afad4d4Sstephan sq3StackPtr = p; 1223afad4d4Sstephan } 1233afad4d4Sstephan WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){ 1243afad4d4Sstephan if(n<=0) return 0; 1253afad4d4Sstephan n = (n + 7) & ~7 /* align to 8-byte boundary */; 1263afad4d4Sstephan unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr(); 1273afad4d4Sstephan unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin(); 1283afad4d4Sstephan if(b + n >= p || b + n < b/*overflow*/) return 0; 1293afad4d4Sstephan return sq3StackPtr = p - n; 1303afad4d4Sstephan } 1313afad4d4Sstephan #endif /* stack allocator experiment */ 1323afad4d4Sstephan 1333afad4d4Sstephan /* 1343afad4d4Sstephan ** State for the "pseudo-stack" allocator implemented in 1353afad4d4Sstephan ** sqlite3_wasm_pstack_xyz(). In order to avoid colliding with 1363afad4d4Sstephan ** Emscripten-controled stack space, it carves out a bit of stack 1373afad4d4Sstephan ** memory to use for that purpose. This memory ends up in the 1383afad4d4Sstephan ** WASM-managed memory, such that routines which manipulate the wasm 1393afad4d4Sstephan ** heap can also be used to manipulate this memory. 1403afad4d4Sstephan */ 1413afad4d4Sstephan static unsigned char PStack_mem[512 * 8] = {0}; 1423afad4d4Sstephan static struct { 143f446af57Sstephan unsigned const char * const pBegin;/* Start (inclusive) of memory */ 144f446af57Sstephan unsigned const char * const pEnd; /* One-after-the-end of memory */ 145f446af57Sstephan unsigned char * pPos; /* Current stack pointer */ 1463afad4d4Sstephan } PStack = { 1473afad4d4Sstephan &PStack_mem[0], 1483afad4d4Sstephan &PStack_mem[0] + sizeof(PStack_mem), 1493afad4d4Sstephan &PStack_mem[0] + sizeof(PStack_mem) 1503afad4d4Sstephan }; 1513afad4d4Sstephan /* 1523afad4d4Sstephan ** Returns the current pstack position. 1533afad4d4Sstephan */ 1543afad4d4Sstephan WASM_KEEP void * sqlite3_wasm_pstack_ptr(void){ 1553afad4d4Sstephan return PStack.pPos; 1563afad4d4Sstephan } 1573afad4d4Sstephan /* 1583afad4d4Sstephan ** Sets the pstack position poitner to p. Results are undefined if the 1593afad4d4Sstephan ** given value did not come from sqlite3_wasm_pstack_ptr(). 1603afad4d4Sstephan */ 1613afad4d4Sstephan WASM_KEEP void sqlite3_wasm_pstack_restore(unsigned char * p){ 1623afad4d4Sstephan assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos); 1633afad4d4Sstephan assert(0==(p & 0x7)); 1643afad4d4Sstephan if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){ 1653afad4d4Sstephan PStack.pPos = p; 1663afad4d4Sstephan } 1673afad4d4Sstephan } 1683afad4d4Sstephan /* 1693afad4d4Sstephan ** Allocate and zero out n bytes from the pstack. Returns a pointer to 1703afad4d4Sstephan ** the memory on success, 0 on error (including a negative n value). n 1713afad4d4Sstephan ** is always adjusted to be a multiple of 8 and returned memory is 1723afad4d4Sstephan ** always zeroed out before returning (because this keeps the client 1733afad4d4Sstephan ** JS code from having to do so, and most uses of the pstack will 1743afad4d4Sstephan ** call for doing so). 1753afad4d4Sstephan */ 1763afad4d4Sstephan WASM_KEEP void * sqlite3_wasm_pstack_alloc(int n){ 1773afad4d4Sstephan if( n<=0 ) return 0; 1783afad4d4Sstephan //if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */; 1793afad4d4Sstephan n = (n + 7) & ~7 /* align to 8-byte boundary */; 1803afad4d4Sstephan unsigned char * const p = PStack.pPos; 1813afad4d4Sstephan unsigned const char * const b = PStack.pBegin; 1823afad4d4Sstephan if( b + n > p || b + n <= b/*overflow*/ ) return 0; 1833afad4d4Sstephan memset((PStack.pPos = p - n), 0, (unsigned int)n); 1843afad4d4Sstephan return PStack.pPos; 1853afad4d4Sstephan } 1863afad4d4Sstephan /* 1873afad4d4Sstephan ** Return the number of bytes left which can be 1883afad4d4Sstephan ** sqlite3_wasm_pstack_alloc()'d. 1893afad4d4Sstephan */ 1903afad4d4Sstephan WASM_KEEP int sqlite3_wasm_pstack_remaining(void){ 1913afad4d4Sstephan assert(PStack.pPos >= PStack.pBegin); 1923afad4d4Sstephan assert(PStack.pPos <= PStack.pEnd); 1933afad4d4Sstephan return (int)(PStack.pPos - PStack.pBegin); 1943afad4d4Sstephan } 1953afad4d4Sstephan 1963afad4d4Sstephan 19773079dbaSstephan /* 1983961b263Sstephan ** This function is NOT part of the sqlite3 public API. It is strictly 1993961b263Sstephan ** for use by the sqlite project's own JS/WASM bindings. 2003961b263Sstephan ** 2013961b263Sstephan ** For purposes of certain hand-crafted C/Wasm function bindings, we 2023961b263Sstephan ** need a way of reporting errors which is consistent with the rest of 203e1c34624Sstephan ** the C API, as opposed to throwing JS exceptions. To that end, this 204e1c34624Sstephan ** internal-use-only function is a thin proxy around 205e1c34624Sstephan ** sqlite3ErrorWithMessage(). The intent is that it only be used from 206e1c34624Sstephan ** Wasm bindings such as sqlite3_prepare_v2/v3(), and definitely not 207e1c34624Sstephan ** from client code. 2083961b263Sstephan ** 2093961b263Sstephan ** Returns err_code. 2103961b263Sstephan */ 21173079dbaSstephan WASM_KEEP 21273079dbaSstephan int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){ 2133961b263Sstephan if(0!=zMsg){ 2143961b263Sstephan const int nMsg = sqlite3Strlen30(zMsg); 2153961b263Sstephan sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg); 2163961b263Sstephan }else{ 2173961b263Sstephan sqlite3ErrorWithMsg(db, err_code, NULL); 2183961b263Sstephan } 2193961b263Sstephan return err_code; 2203961b263Sstephan } 2213961b263Sstephan 2223961b263Sstephan /* 2233961b263Sstephan ** This function is NOT part of the sqlite3 public API. It is strictly 2243961b263Sstephan ** for use by the sqlite project's own JS/WASM bindings. Unlike the 2253961b263Sstephan ** rest of the sqlite3 API, this part requires C99 for snprintf() and 2263961b263Sstephan ** variadic macros. 2273961b263Sstephan ** 2283961b263Sstephan ** Returns a string containing a JSON-format "enum" of C-level 2293961b263Sstephan ** constants intended to be imported into the JS environment. The JSON 2303961b263Sstephan ** is initialized the first time this function is called and that 2313961b263Sstephan ** result is reused for all future calls. 2323961b263Sstephan ** 2333961b263Sstephan ** If this function returns NULL then it means that the internal 2343961b263Sstephan ** buffer is not large enough for the generated JSON. In debug builds 2353961b263Sstephan ** that will trigger an assert(). 2363961b263Sstephan */ 23773079dbaSstephan WASM_KEEP 2383961b263Sstephan const char * sqlite3_wasm_enum_json(void){ 2395b915007Sstephan static char strBuf[1024 * 12] = {0} /* where the JSON goes */; 2403961b263Sstephan int n = 0, childCount = 0, structCount = 0 2413961b263Sstephan /* output counters for figuring out where commas go */; 2423961b263Sstephan char * pos = &strBuf[1] /* skip first byte for now to help protect 2433961b263Sstephan ** against a small race condition */; 2443961b263Sstephan char const * const zEnd = pos + sizeof(strBuf) /* one-past-the-end */; 2453961b263Sstephan if(strBuf[0]) return strBuf; 2463961b263Sstephan /* Leave strBuf[0] at 0 until the end to help guard against a tiny 2473961b263Sstephan ** race condition. If this is called twice concurrently, they might 2483961b263Sstephan ** end up both writing to strBuf, but they'll both write the same 2493961b263Sstephan ** thing, so that's okay. If we set byte 0 up front then the 2nd 2503961b263Sstephan ** instance might return and use the string before the 1st instance 2513961b263Sstephan ** is done filling it. */ 2523961b263Sstephan 2533961b263Sstephan /* Core output macros... */ 2543961b263Sstephan #define lenCheck assert(pos < zEnd - 128 \ 2553961b263Sstephan && "sqlite3_wasm_enum_json() buffer is too small."); \ 2563961b263Sstephan if(pos >= zEnd - 128) return 0 2573961b263Sstephan #define outf(format,...) \ 2583961b263Sstephan pos += snprintf(pos, ((size_t)(zEnd - pos)), format, __VA_ARGS__); \ 2593961b263Sstephan lenCheck 2603961b263Sstephan #define out(TXT) outf("%s",TXT) 2613961b263Sstephan #define CloseBrace(LEVEL) \ 2623961b263Sstephan assert(LEVEL<5); memset(pos, '}', LEVEL); pos+=LEVEL; lenCheck 2633961b263Sstephan 2643961b263Sstephan /* Macros for emitting maps of integer- and string-type macros to 2653961b263Sstephan ** their values. */ 2663961b263Sstephan #define DefGroup(KEY) n = 0; \ 2673961b263Sstephan outf("%s\"" #KEY "\": {",(childCount++ ? "," : "")); 2683961b263Sstephan #define DefInt(KEY) \ 2693961b263Sstephan outf("%s\"%s\": %d", (n++ ? ", " : ""), #KEY, (int)KEY) 2703961b263Sstephan #define DefStr(KEY) \ 2713961b263Sstephan outf("%s\"%s\": \"%s\"", (n++ ? ", " : ""), #KEY, KEY) 2723961b263Sstephan #define _DefGroup CloseBrace(1) 2733961b263Sstephan 27453d4e01dSstephan /* The following groups are sorted alphabetic by group name. */ 27553d4e01dSstephan DefGroup(access){ 27653d4e01dSstephan DefInt(SQLITE_ACCESS_EXISTS); 27753d4e01dSstephan DefInt(SQLITE_ACCESS_READWRITE); 27853d4e01dSstephan DefInt(SQLITE_ACCESS_READ)/*docs say this is unused*/; 27953d4e01dSstephan } _DefGroup; 28053d4e01dSstephan 28153d4e01dSstephan DefGroup(blobFinalizers) { 28253d4e01dSstephan /* SQLITE_STATIC/TRANSIENT need to be handled explicitly as 28353d4e01dSstephan ** integers to avoid casting-related warnings. */ 28453d4e01dSstephan out("\"SQLITE_STATIC\":0, \"SQLITE_TRANSIENT\":-1"); 28553d4e01dSstephan } _DefGroup; 28653d4e01dSstephan 28753d4e01dSstephan DefGroup(dataTypes) { 28853d4e01dSstephan DefInt(SQLITE_INTEGER); 28953d4e01dSstephan DefInt(SQLITE_FLOAT); 29053d4e01dSstephan DefInt(SQLITE_TEXT); 29153d4e01dSstephan DefInt(SQLITE_BLOB); 29253d4e01dSstephan DefInt(SQLITE_NULL); 29353d4e01dSstephan } _DefGroup; 29453d4e01dSstephan 29553d4e01dSstephan DefGroup(encodings) { 29653d4e01dSstephan /* Noting that the wasm binding only aims to support UTF-8. */ 29753d4e01dSstephan DefInt(SQLITE_UTF8); 29853d4e01dSstephan DefInt(SQLITE_UTF16LE); 29953d4e01dSstephan DefInt(SQLITE_UTF16BE); 30053d4e01dSstephan DefInt(SQLITE_UTF16); 30153d4e01dSstephan /*deprecated DefInt(SQLITE_ANY); */ 30253d4e01dSstephan DefInt(SQLITE_UTF16_ALIGNED); 30353d4e01dSstephan } _DefGroup; 30453d4e01dSstephan 30553d4e01dSstephan DefGroup(fcntl) { 30653d4e01dSstephan DefInt(SQLITE_FCNTL_LOCKSTATE); 30753d4e01dSstephan DefInt(SQLITE_FCNTL_GET_LOCKPROXYFILE); 30853d4e01dSstephan DefInt(SQLITE_FCNTL_SET_LOCKPROXYFILE); 30953d4e01dSstephan DefInt(SQLITE_FCNTL_LAST_ERRNO); 31053d4e01dSstephan DefInt(SQLITE_FCNTL_SIZE_HINT); 31153d4e01dSstephan DefInt(SQLITE_FCNTL_CHUNK_SIZE); 31253d4e01dSstephan DefInt(SQLITE_FCNTL_FILE_POINTER); 31353d4e01dSstephan DefInt(SQLITE_FCNTL_SYNC_OMITTED); 31453d4e01dSstephan DefInt(SQLITE_FCNTL_WIN32_AV_RETRY); 31553d4e01dSstephan DefInt(SQLITE_FCNTL_PERSIST_WAL); 31653d4e01dSstephan DefInt(SQLITE_FCNTL_OVERWRITE); 31753d4e01dSstephan DefInt(SQLITE_FCNTL_VFSNAME); 31853d4e01dSstephan DefInt(SQLITE_FCNTL_POWERSAFE_OVERWRITE); 31953d4e01dSstephan DefInt(SQLITE_FCNTL_PRAGMA); 32053d4e01dSstephan DefInt(SQLITE_FCNTL_BUSYHANDLER); 32153d4e01dSstephan DefInt(SQLITE_FCNTL_TEMPFILENAME); 32253d4e01dSstephan DefInt(SQLITE_FCNTL_MMAP_SIZE); 32353d4e01dSstephan DefInt(SQLITE_FCNTL_TRACE); 32453d4e01dSstephan DefInt(SQLITE_FCNTL_HAS_MOVED); 32553d4e01dSstephan DefInt(SQLITE_FCNTL_SYNC); 32653d4e01dSstephan DefInt(SQLITE_FCNTL_COMMIT_PHASETWO); 32753d4e01dSstephan DefInt(SQLITE_FCNTL_WIN32_SET_HANDLE); 32853d4e01dSstephan DefInt(SQLITE_FCNTL_WAL_BLOCK); 32953d4e01dSstephan DefInt(SQLITE_FCNTL_ZIPVFS); 33053d4e01dSstephan DefInt(SQLITE_FCNTL_RBU); 33153d4e01dSstephan DefInt(SQLITE_FCNTL_VFS_POINTER); 33253d4e01dSstephan DefInt(SQLITE_FCNTL_JOURNAL_POINTER); 33353d4e01dSstephan DefInt(SQLITE_FCNTL_WIN32_GET_HANDLE); 33453d4e01dSstephan DefInt(SQLITE_FCNTL_PDB); 33553d4e01dSstephan DefInt(SQLITE_FCNTL_BEGIN_ATOMIC_WRITE); 33653d4e01dSstephan DefInt(SQLITE_FCNTL_COMMIT_ATOMIC_WRITE); 33753d4e01dSstephan DefInt(SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE); 33853d4e01dSstephan DefInt(SQLITE_FCNTL_LOCK_TIMEOUT); 33953d4e01dSstephan DefInt(SQLITE_FCNTL_DATA_VERSION); 34053d4e01dSstephan DefInt(SQLITE_FCNTL_SIZE_LIMIT); 34153d4e01dSstephan DefInt(SQLITE_FCNTL_CKPT_DONE); 34253d4e01dSstephan DefInt(SQLITE_FCNTL_RESERVE_BYTES); 34353d4e01dSstephan DefInt(SQLITE_FCNTL_CKPT_START); 34453d4e01dSstephan DefInt(SQLITE_FCNTL_EXTERNAL_READER); 34553d4e01dSstephan DefInt(SQLITE_FCNTL_CKSM_FILE); 34653d4e01dSstephan } _DefGroup; 34753d4e01dSstephan 34853d4e01dSstephan DefGroup(flock) { 34953d4e01dSstephan DefInt(SQLITE_LOCK_NONE); 35053d4e01dSstephan DefInt(SQLITE_LOCK_SHARED); 35153d4e01dSstephan DefInt(SQLITE_LOCK_RESERVED); 35253d4e01dSstephan DefInt(SQLITE_LOCK_PENDING); 35353d4e01dSstephan DefInt(SQLITE_LOCK_EXCLUSIVE); 35453d4e01dSstephan } _DefGroup; 35553d4e01dSstephan 35653d4e01dSstephan DefGroup(ioCap) { 35753d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC); 35853d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC512); 35953d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC1K); 36053d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC2K); 36153d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC4K); 36253d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC8K); 36353d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC16K); 36453d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC32K); 36553d4e01dSstephan DefInt(SQLITE_IOCAP_ATOMIC64K); 36653d4e01dSstephan DefInt(SQLITE_IOCAP_SAFE_APPEND); 36753d4e01dSstephan DefInt(SQLITE_IOCAP_SEQUENTIAL); 36853d4e01dSstephan DefInt(SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN); 36953d4e01dSstephan DefInt(SQLITE_IOCAP_POWERSAFE_OVERWRITE); 37053d4e01dSstephan DefInt(SQLITE_IOCAP_IMMUTABLE); 37153d4e01dSstephan DefInt(SQLITE_IOCAP_BATCH_ATOMIC); 37253d4e01dSstephan } _DefGroup; 37353d4e01dSstephan 37453d4e01dSstephan DefGroup(openFlags) { 37553d4e01dSstephan /* Noting that not all of these will have any effect in 37653d4e01dSstephan ** WASM-space. */ 37753d4e01dSstephan DefInt(SQLITE_OPEN_READONLY); 37853d4e01dSstephan DefInt(SQLITE_OPEN_READWRITE); 37953d4e01dSstephan DefInt(SQLITE_OPEN_CREATE); 38053d4e01dSstephan DefInt(SQLITE_OPEN_URI); 38153d4e01dSstephan DefInt(SQLITE_OPEN_MEMORY); 38253d4e01dSstephan DefInt(SQLITE_OPEN_NOMUTEX); 38353d4e01dSstephan DefInt(SQLITE_OPEN_FULLMUTEX); 38453d4e01dSstephan DefInt(SQLITE_OPEN_SHAREDCACHE); 38553d4e01dSstephan DefInt(SQLITE_OPEN_PRIVATECACHE); 38653d4e01dSstephan DefInt(SQLITE_OPEN_EXRESCODE); 38753d4e01dSstephan DefInt(SQLITE_OPEN_NOFOLLOW); 38853d4e01dSstephan /* OPEN flags for use with VFSes... */ 38953d4e01dSstephan DefInt(SQLITE_OPEN_MAIN_DB); 39053d4e01dSstephan DefInt(SQLITE_OPEN_MAIN_JOURNAL); 39153d4e01dSstephan DefInt(SQLITE_OPEN_TEMP_DB); 39253d4e01dSstephan DefInt(SQLITE_OPEN_TEMP_JOURNAL); 39353d4e01dSstephan DefInt(SQLITE_OPEN_TRANSIENT_DB); 39453d4e01dSstephan DefInt(SQLITE_OPEN_SUBJOURNAL); 39553d4e01dSstephan DefInt(SQLITE_OPEN_SUPER_JOURNAL); 39653d4e01dSstephan DefInt(SQLITE_OPEN_WAL); 39753d4e01dSstephan DefInt(SQLITE_OPEN_DELETEONCLOSE); 39853d4e01dSstephan DefInt(SQLITE_OPEN_EXCLUSIVE); 39953d4e01dSstephan } _DefGroup; 40053d4e01dSstephan 40153d4e01dSstephan DefGroup(prepareFlags) { 40253d4e01dSstephan DefInt(SQLITE_PREPARE_PERSISTENT); 40353d4e01dSstephan DefInt(SQLITE_PREPARE_NORMALIZE); 40453d4e01dSstephan DefInt(SQLITE_PREPARE_NO_VTAB); 4053961b263Sstephan } _DefGroup; 4063961b263Sstephan 4073961b263Sstephan DefGroup(resultCodes) { 4083961b263Sstephan DefInt(SQLITE_OK); 4093961b263Sstephan DefInt(SQLITE_ERROR); 4103961b263Sstephan DefInt(SQLITE_INTERNAL); 4113961b263Sstephan DefInt(SQLITE_PERM); 4123961b263Sstephan DefInt(SQLITE_ABORT); 4133961b263Sstephan DefInt(SQLITE_BUSY); 4143961b263Sstephan DefInt(SQLITE_LOCKED); 4153961b263Sstephan DefInt(SQLITE_NOMEM); 4163961b263Sstephan DefInt(SQLITE_READONLY); 4173961b263Sstephan DefInt(SQLITE_INTERRUPT); 4183961b263Sstephan DefInt(SQLITE_IOERR); 4193961b263Sstephan DefInt(SQLITE_CORRUPT); 4203961b263Sstephan DefInt(SQLITE_NOTFOUND); 4213961b263Sstephan DefInt(SQLITE_FULL); 4223961b263Sstephan DefInt(SQLITE_CANTOPEN); 4233961b263Sstephan DefInt(SQLITE_PROTOCOL); 4243961b263Sstephan DefInt(SQLITE_EMPTY); 4253961b263Sstephan DefInt(SQLITE_SCHEMA); 4263961b263Sstephan DefInt(SQLITE_TOOBIG); 4273961b263Sstephan DefInt(SQLITE_CONSTRAINT); 4283961b263Sstephan DefInt(SQLITE_MISMATCH); 4293961b263Sstephan DefInt(SQLITE_MISUSE); 4303961b263Sstephan DefInt(SQLITE_NOLFS); 4313961b263Sstephan DefInt(SQLITE_AUTH); 4323961b263Sstephan DefInt(SQLITE_FORMAT); 4333961b263Sstephan DefInt(SQLITE_RANGE); 4343961b263Sstephan DefInt(SQLITE_NOTADB); 4353961b263Sstephan DefInt(SQLITE_NOTICE); 4363961b263Sstephan DefInt(SQLITE_WARNING); 4373961b263Sstephan DefInt(SQLITE_ROW); 4383961b263Sstephan DefInt(SQLITE_DONE); 4393961b263Sstephan // Extended Result Codes 4403961b263Sstephan DefInt(SQLITE_ERROR_MISSING_COLLSEQ); 4413961b263Sstephan DefInt(SQLITE_ERROR_RETRY); 4423961b263Sstephan DefInt(SQLITE_ERROR_SNAPSHOT); 4433961b263Sstephan DefInt(SQLITE_IOERR_READ); 4443961b263Sstephan DefInt(SQLITE_IOERR_SHORT_READ); 4453961b263Sstephan DefInt(SQLITE_IOERR_WRITE); 4463961b263Sstephan DefInt(SQLITE_IOERR_FSYNC); 4473961b263Sstephan DefInt(SQLITE_IOERR_DIR_FSYNC); 4483961b263Sstephan DefInt(SQLITE_IOERR_TRUNCATE); 4493961b263Sstephan DefInt(SQLITE_IOERR_FSTAT); 4503961b263Sstephan DefInt(SQLITE_IOERR_UNLOCK); 4513961b263Sstephan DefInt(SQLITE_IOERR_RDLOCK); 4523961b263Sstephan DefInt(SQLITE_IOERR_DELETE); 4533961b263Sstephan DefInt(SQLITE_IOERR_BLOCKED); 4543961b263Sstephan DefInt(SQLITE_IOERR_NOMEM); 4553961b263Sstephan DefInt(SQLITE_IOERR_ACCESS); 4563961b263Sstephan DefInt(SQLITE_IOERR_CHECKRESERVEDLOCK); 4573961b263Sstephan DefInt(SQLITE_IOERR_LOCK); 4583961b263Sstephan DefInt(SQLITE_IOERR_CLOSE); 4593961b263Sstephan DefInt(SQLITE_IOERR_DIR_CLOSE); 4603961b263Sstephan DefInt(SQLITE_IOERR_SHMOPEN); 4613961b263Sstephan DefInt(SQLITE_IOERR_SHMSIZE); 4623961b263Sstephan DefInt(SQLITE_IOERR_SHMLOCK); 4633961b263Sstephan DefInt(SQLITE_IOERR_SHMMAP); 4643961b263Sstephan DefInt(SQLITE_IOERR_SEEK); 4653961b263Sstephan DefInt(SQLITE_IOERR_DELETE_NOENT); 4663961b263Sstephan DefInt(SQLITE_IOERR_MMAP); 4673961b263Sstephan DefInt(SQLITE_IOERR_GETTEMPPATH); 4683961b263Sstephan DefInt(SQLITE_IOERR_CONVPATH); 4693961b263Sstephan DefInt(SQLITE_IOERR_VNODE); 4703961b263Sstephan DefInt(SQLITE_IOERR_AUTH); 4713961b263Sstephan DefInt(SQLITE_IOERR_BEGIN_ATOMIC); 4723961b263Sstephan DefInt(SQLITE_IOERR_COMMIT_ATOMIC); 4733961b263Sstephan DefInt(SQLITE_IOERR_ROLLBACK_ATOMIC); 4743961b263Sstephan DefInt(SQLITE_IOERR_DATA); 4753961b263Sstephan DefInt(SQLITE_IOERR_CORRUPTFS); 4763961b263Sstephan DefInt(SQLITE_LOCKED_SHAREDCACHE); 4773961b263Sstephan DefInt(SQLITE_LOCKED_VTAB); 4783961b263Sstephan DefInt(SQLITE_BUSY_RECOVERY); 4793961b263Sstephan DefInt(SQLITE_BUSY_SNAPSHOT); 4803961b263Sstephan DefInt(SQLITE_BUSY_TIMEOUT); 4813961b263Sstephan DefInt(SQLITE_CANTOPEN_NOTEMPDIR); 4823961b263Sstephan DefInt(SQLITE_CANTOPEN_ISDIR); 4833961b263Sstephan DefInt(SQLITE_CANTOPEN_FULLPATH); 4843961b263Sstephan DefInt(SQLITE_CANTOPEN_CONVPATH); 4853961b263Sstephan //DefInt(SQLITE_CANTOPEN_DIRTYWAL)/*docs say not used*/; 4863961b263Sstephan DefInt(SQLITE_CANTOPEN_SYMLINK); 4873961b263Sstephan DefInt(SQLITE_CORRUPT_VTAB); 4883961b263Sstephan DefInt(SQLITE_CORRUPT_SEQUENCE); 4893961b263Sstephan DefInt(SQLITE_CORRUPT_INDEX); 4903961b263Sstephan DefInt(SQLITE_READONLY_RECOVERY); 4913961b263Sstephan DefInt(SQLITE_READONLY_CANTLOCK); 4923961b263Sstephan DefInt(SQLITE_READONLY_ROLLBACK); 4933961b263Sstephan DefInt(SQLITE_READONLY_DBMOVED); 4943961b263Sstephan DefInt(SQLITE_READONLY_CANTINIT); 4953961b263Sstephan DefInt(SQLITE_READONLY_DIRECTORY); 4963961b263Sstephan DefInt(SQLITE_ABORT_ROLLBACK); 4973961b263Sstephan DefInt(SQLITE_CONSTRAINT_CHECK); 4983961b263Sstephan DefInt(SQLITE_CONSTRAINT_COMMITHOOK); 4993961b263Sstephan DefInt(SQLITE_CONSTRAINT_FOREIGNKEY); 5003961b263Sstephan DefInt(SQLITE_CONSTRAINT_FUNCTION); 5013961b263Sstephan DefInt(SQLITE_CONSTRAINT_NOTNULL); 5023961b263Sstephan DefInt(SQLITE_CONSTRAINT_PRIMARYKEY); 5033961b263Sstephan DefInt(SQLITE_CONSTRAINT_TRIGGER); 5043961b263Sstephan DefInt(SQLITE_CONSTRAINT_UNIQUE); 5053961b263Sstephan DefInt(SQLITE_CONSTRAINT_VTAB); 5063961b263Sstephan DefInt(SQLITE_CONSTRAINT_ROWID); 5073961b263Sstephan DefInt(SQLITE_CONSTRAINT_PINNED); 5083961b263Sstephan DefInt(SQLITE_CONSTRAINT_DATATYPE); 5093961b263Sstephan DefInt(SQLITE_NOTICE_RECOVER_WAL); 5103961b263Sstephan DefInt(SQLITE_NOTICE_RECOVER_ROLLBACK); 5113961b263Sstephan DefInt(SQLITE_WARNING_AUTOINDEX); 5123961b263Sstephan DefInt(SQLITE_AUTH_USER); 5133961b263Sstephan DefInt(SQLITE_OK_LOAD_PERMANENTLY); 5143961b263Sstephan //DefInt(SQLITE_OK_SYMLINK) /* internal use only */; 5153961b263Sstephan } _DefGroup; 5163961b263Sstephan 51753d4e01dSstephan DefGroup(serialize){ 51832781427Sstephan DefInt(SQLITE_SERIALIZE_NOCOPY); 51953d4e01dSstephan DefInt(SQLITE_DESERIALIZE_FREEONCLOSE); 52053d4e01dSstephan DefInt(SQLITE_DESERIALIZE_READONLY); 52153d4e01dSstephan DefInt(SQLITE_DESERIALIZE_RESIZEABLE); 5223961b263Sstephan } _DefGroup; 5233961b263Sstephan 5243961b263Sstephan DefGroup(syncFlags) { 5253961b263Sstephan DefInt(SQLITE_SYNC_NORMAL); 5263961b263Sstephan DefInt(SQLITE_SYNC_FULL); 5273961b263Sstephan DefInt(SQLITE_SYNC_DATAONLY); 5283961b263Sstephan } _DefGroup; 5293961b263Sstephan 53053d4e01dSstephan DefGroup(udfFlags) { 53153d4e01dSstephan DefInt(SQLITE_DETERMINISTIC); 53253d4e01dSstephan DefInt(SQLITE_DIRECTONLY); 53353d4e01dSstephan DefInt(SQLITE_INNOCUOUS); 5343961b263Sstephan } _DefGroup; 5353961b263Sstephan 53653d4e01dSstephan DefGroup(version) { 53753d4e01dSstephan DefInt(SQLITE_VERSION_NUMBER); 53853d4e01dSstephan DefStr(SQLITE_VERSION); 53953d4e01dSstephan DefStr(SQLITE_SOURCE_ID); 5403961b263Sstephan } _DefGroup; 5413961b263Sstephan 5423961b263Sstephan #undef DefGroup 5433961b263Sstephan #undef DefStr 5443961b263Sstephan #undef DefInt 5453961b263Sstephan #undef _DefGroup 5463961b263Sstephan 5473961b263Sstephan /* 5483961b263Sstephan ** Emit an array of "StructBinder" struct descripions, which look 5493961b263Sstephan ** like: 5503961b263Sstephan ** 5513961b263Sstephan ** { 5523961b263Sstephan ** "name": "MyStruct", 5533961b263Sstephan ** "sizeof": 16, 5543961b263Sstephan ** "members": { 5553961b263Sstephan ** "member1": {"offset": 0,"sizeof": 4,"signature": "i"}, 5563961b263Sstephan ** "member2": {"offset": 4,"sizeof": 4,"signature": "p"}, 5573961b263Sstephan ** "member3": {"offset": 8,"sizeof": 8,"signature": "j"} 5583961b263Sstephan ** } 5593961b263Sstephan ** } 5603961b263Sstephan ** 5612315e834Sstephan ** Detailed documentation for those bits are in the docs for the 5622315e834Sstephan ** Jaccwabyt JS-side component. 5633961b263Sstephan */ 5643961b263Sstephan 5653961b263Sstephan /** Macros for emitting StructBinder description. */ 5663961b263Sstephan #define StructBinder__(TYPE) \ 5673961b263Sstephan n = 0; \ 5683961b263Sstephan outf("%s{", (structCount++ ? ", " : "")); \ 5693961b263Sstephan out("\"name\": \"" # TYPE "\","); \ 5703961b263Sstephan outf("\"sizeof\": %d", (int)sizeof(TYPE)); \ 5713961b263Sstephan out(",\"members\": {"); 5723961b263Sstephan #define StructBinder_(T) StructBinder__(T) 5733961b263Sstephan /** ^^^ indirection needed to expand CurrentStruct */ 5743961b263Sstephan #define StructBinder StructBinder_(CurrentStruct) 5753961b263Sstephan #define _StructBinder CloseBrace(2) 5763961b263Sstephan #define M(MEMBER,SIG) \ 5773961b263Sstephan outf("%s\"%s\": " \ 5783961b263Sstephan "{\"offset\":%d,\"sizeof\": %d,\"signature\":\"%s\"}", \ 5793961b263Sstephan (n++ ? ", " : ""), #MEMBER, \ 5803961b263Sstephan (int)offsetof(CurrentStruct,MEMBER), \ 5813961b263Sstephan (int)sizeof(((CurrentStruct*)0)->MEMBER), \ 5823961b263Sstephan SIG) 5833961b263Sstephan 5843961b263Sstephan structCount = 0; 5853961b263Sstephan out(", \"structs\": ["); { 5863961b263Sstephan 5873961b263Sstephan #define CurrentStruct sqlite3_vfs 5883961b263Sstephan StructBinder { 5893961b263Sstephan M(iVersion,"i"); 5903961b263Sstephan M(szOsFile,"i"); 5913961b263Sstephan M(mxPathname,"i"); 5923961b263Sstephan M(pNext,"p"); 5933961b263Sstephan M(zName,"s"); 5943961b263Sstephan M(pAppData,"p"); 5953961b263Sstephan M(xOpen,"i(pppip)"); 5963961b263Sstephan M(xDelete,"i(ppi)"); 5973961b263Sstephan M(xAccess,"i(ppip)"); 5983961b263Sstephan M(xFullPathname,"i(ppip)"); 5993961b263Sstephan M(xDlOpen,"p(pp)"); 6003961b263Sstephan M(xDlError,"p(pip)"); 6013961b263Sstephan M(xDlSym,"p()"); 6023961b263Sstephan M(xDlClose,"v(pp)"); 6033961b263Sstephan M(xRandomness,"i(pip)"); 6043961b263Sstephan M(xSleep,"i(pi)"); 6053961b263Sstephan M(xCurrentTime,"i(pp)"); 6063961b263Sstephan M(xGetLastError,"i(pip)"); 6073961b263Sstephan M(xCurrentTimeInt64,"i(pp)"); 6083961b263Sstephan M(xSetSystemCall,"i(ppp)"); 6093961b263Sstephan M(xGetSystemCall,"p(pp)"); 6103961b263Sstephan M(xNextSystemCall,"p(pp)"); 6113961b263Sstephan } _StructBinder; 6123961b263Sstephan #undef CurrentStruct 6133961b263Sstephan 6143961b263Sstephan #define CurrentStruct sqlite3_io_methods 6153961b263Sstephan StructBinder { 6163961b263Sstephan M(iVersion,"i"); 6173961b263Sstephan M(xClose,"i(p)"); 618*bdfd7ea0Sstephan M(xRead,"i(ppij)"); 619*bdfd7ea0Sstephan M(xWrite,"i(ppij)"); 620*bdfd7ea0Sstephan M(xTruncate,"i(pj)"); 6213961b263Sstephan M(xSync,"i(pi)"); 6223961b263Sstephan M(xFileSize,"i(pp)"); 6233961b263Sstephan M(xLock,"i(pi)"); 6243961b263Sstephan M(xUnlock,"i(pi)"); 6253961b263Sstephan M(xCheckReservedLock,"i(pp)"); 6263961b263Sstephan M(xFileControl,"i(pip)"); 6273961b263Sstephan M(xSectorSize,"i(p)"); 6283961b263Sstephan M(xDeviceCharacteristics,"i(p)"); 6293961b263Sstephan M(xShmMap,"i(piiip)"); 6303961b263Sstephan M(xShmLock,"i(piii)"); 6313961b263Sstephan M(xShmBarrier,"v(p)"); 6323961b263Sstephan M(xShmUnmap,"i(pi)"); 633*bdfd7ea0Sstephan M(xFetch,"i(pjip)"); 634*bdfd7ea0Sstephan M(xUnfetch,"i(pjp)"); 6353961b263Sstephan } _StructBinder; 6363961b263Sstephan #undef CurrentStruct 6373961b263Sstephan 6383961b263Sstephan #define CurrentStruct sqlite3_file 6393961b263Sstephan StructBinder { 6406a643e4bSstephan M(pMethods,"p"); 6413961b263Sstephan } _StructBinder; 6423961b263Sstephan #undef CurrentStruct 6433961b263Sstephan 6443961b263Sstephan } out( "]"/*structs*/); 6453961b263Sstephan 6463961b263Sstephan out("}"/*top-level object*/); 6473961b263Sstephan *pos = 0; 6483961b263Sstephan strBuf[0] = '{'/*end of the race-condition workaround*/; 6493961b263Sstephan return strBuf; 6503961b263Sstephan #undef StructBinder 6513961b263Sstephan #undef StructBinder_ 6523961b263Sstephan #undef StructBinder__ 6533961b263Sstephan #undef M 6543961b263Sstephan #undef _StructBinder 6553961b263Sstephan #undef CloseBrace 6563961b263Sstephan #undef out 6573961b263Sstephan #undef outf 6583961b263Sstephan #undef lenCheck 6593961b263Sstephan } 660a579f440Sstephan 661a579f440Sstephan /* 662a579f440Sstephan ** This function is NOT part of the sqlite3 public API. It is strictly 663a579f440Sstephan ** for use by the sqlite project's own JS/WASM bindings. 664a579f440Sstephan ** 665a579f440Sstephan ** This function invokes the xDelete method of the default VFS, 666a579f440Sstephan ** passing on the given filename. If zName is NULL, no default VFS is 667a579f440Sstephan ** found, or it has no xDelete method, SQLITE_MISUSE is returned, else 668a579f440Sstephan ** the result of the xDelete() call is returned. 669a579f440Sstephan */ 67073079dbaSstephan WASM_KEEP 671a579f440Sstephan int sqlite3_wasm_vfs_unlink(const char * zName){ 672a579f440Sstephan int rc = SQLITE_MISUSE /* ??? */; 673a579f440Sstephan sqlite3_vfs * const pVfs = sqlite3_vfs_find(0); 67463e9ec2fSstephan #if defined(__EMSCRIPTEN__) 67563e9ec2fSstephan emscripten_console_warn("sqlite3_wasm_vfs_unlink() will be removed."); 67663e9ec2fSstephan #endif 677a579f440Sstephan if( zName && pVfs && pVfs->xDelete ){ 678a579f440Sstephan rc = pVfs->xDelete(pVfs, zName, 1); 679a579f440Sstephan } 680a579f440Sstephan return rc; 681a579f440Sstephan } 682a579f440Sstephan 68332781427Sstephan /* 68432781427Sstephan ** Uses the current database's VFS xRead to stream the db file's 68532781427Sstephan ** contents out to the given callback. The callback gets a single 68632781427Sstephan ** chunk of size n (its 2nd argument) on each call and must return 0 68732781427Sstephan ** on success, non-0 on error. This function returns 0 on success, 68832781427Sstephan ** SQLITE_NOTFOUND if no db is open, or propagates any other non-0 68932781427Sstephan ** code from the callback. Note that this is not thread-friendly: it 69032781427Sstephan ** expects that it will be the only thread reading the db file and 69132781427Sstephan ** takes no measures to ensure that is the case. 69232781427Sstephan ** 69332781427Sstephan ** This implementation appears to work fine, but 69432781427Sstephan ** sqlite3_wasm_db_serialize() is arguably the better way to achieve 69532781427Sstephan ** this. 69632781427Sstephan */ 69732781427Sstephan WASM_KEEP 69832781427Sstephan int sqlite3_wasm_db_export_chunked( sqlite3* pDb, 69932781427Sstephan int (*xCallback)(unsigned const char *zOut, int n) ){ 70032781427Sstephan sqlite3_int64 nSize = 0; 70132781427Sstephan sqlite3_int64 nPos = 0; 70232781427Sstephan sqlite3_file * pFile = 0; 70332781427Sstephan unsigned char buf[1024 * 8]; 70432781427Sstephan int nBuf = (int)sizeof(buf); 70532781427Sstephan int rc = pDb 70632781427Sstephan ? sqlite3_file_control(pDb, "main", 70732781427Sstephan SQLITE_FCNTL_FILE_POINTER, &pFile) 70832781427Sstephan : SQLITE_NOTFOUND; 70932781427Sstephan if( rc ) return rc; 71032781427Sstephan rc = pFile->pMethods->xFileSize(pFile, &nSize); 71132781427Sstephan if( rc ) return rc; 71232781427Sstephan if(nSize % nBuf){ 71332781427Sstephan /* DB size is not an even multiple of the buffer size. Reduce 71432781427Sstephan ** buffer size so that we do not unduly inflate the db size 71532781427Sstephan ** with zero-padding when exporting. */ 71632781427Sstephan if(0 == nSize % 4096) nBuf = 4096; 71732781427Sstephan else if(0 == nSize % 2048) nBuf = 2048; 71832781427Sstephan else if(0 == nSize % 1024) nBuf = 1024; 71932781427Sstephan else nBuf = 512; 72032781427Sstephan } 72132781427Sstephan for( ; 0==rc && nPos<nSize; nPos += nBuf ){ 72232781427Sstephan rc = pFile->pMethods->xRead(pFile, buf, nBuf, nPos); 72332781427Sstephan if(SQLITE_IOERR_SHORT_READ == rc){ 72432781427Sstephan rc = (nPos + nBuf) < nSize ? rc : 0/*assume EOF*/; 72532781427Sstephan } 72632781427Sstephan if( 0==rc ) rc = xCallback(buf, nBuf); 72732781427Sstephan } 72832781427Sstephan return rc; 72932781427Sstephan } 73032781427Sstephan 73132781427Sstephan /* 73232781427Sstephan ** A proxy for sqlite3_serialize() which serializes the "main" schema 73332781427Sstephan ** of pDb, placing the serialized output in pOut and nOut. nOut may be 73432781427Sstephan ** NULL. If pDb or pOut are NULL then SQLITE_MISUSE is returned. If 73532781427Sstephan ** allocation of the serialized copy fails, SQLITE_NOMEM is returned. 73632781427Sstephan ** On success, 0 is returned and `*pOut` will contain a pointer to the 73732781427Sstephan ** memory unless mFlags includes SQLITE_SERIALIZE_NOCOPY and the 73832781427Sstephan ** database has no contiguous memory representation, in which case 73932781427Sstephan ** `*pOut` will be NULL but 0 will be returned. 74032781427Sstephan ** 74132781427Sstephan ** If `*pOut` is not NULL, the caller is responsible for passing it to 74232781427Sstephan ** sqlite3_free() to free it. 74332781427Sstephan */ 74432781427Sstephan WASM_KEEP 74532781427Sstephan int sqlite3_wasm_db_serialize( sqlite3* pDb, unsigned char **pOut, sqlite3_int64 * nOut, 74632781427Sstephan unsigned int mFlags ){ 74732781427Sstephan unsigned char * z; 74832781427Sstephan if( !pDb || !pOut ) return SQLITE_MISUSE; 74932781427Sstephan if(nOut) *nOut = 0; 75032781427Sstephan z = sqlite3_serialize(pDb, "main", nOut, mFlags); 75132781427Sstephan if( z || (SQLITE_SERIALIZE_NOCOPY & mFlags) ){ 75232781427Sstephan *pOut = z; 75332781427Sstephan return 0; 75432781427Sstephan }else{ 75532781427Sstephan return SQLITE_NOMEM; 75632781427Sstephan } 75732781427Sstephan } 75832781427Sstephan 75932781427Sstephan 76063e9ec2fSstephan #if defined(__EMSCRIPTEN__) && defined(SQLITE_WASM_WASMFS) 7615b9973d8Sstephan #include <emscripten/wasmfs.h> 76273079dbaSstephan 763a579f440Sstephan /* 764a579f440Sstephan ** This function is NOT part of the sqlite3 public API. It is strictly 765e3cd6760Sstephan ** for use by the sqlite project's own JS/WASM bindings, specifically 766e3cd6760Sstephan ** only when building with Emscripten's WASMFS support. 767a579f440Sstephan ** 768a579f440Sstephan ** This function should only be called if the JS side detects the 769a579f440Sstephan ** existence of the Origin-Private FileSystem (OPFS) APIs in the 770a579f440Sstephan ** client. The first time it is called, this function instantiates a 771a579f440Sstephan ** WASMFS backend impl for OPFS. On success, subsequent calls are 772a579f440Sstephan ** no-ops. 773a579f440Sstephan ** 774e3cd6760Sstephan ** This function may be passed a "mount point" name, which must have a 775e3cd6760Sstephan ** leading "/" and is currently restricted to a single path component, 776e3cd6760Sstephan ** e.g. "/foo" is legal but "/foo/" and "/foo/bar" are not. If it is 777e3cd6760Sstephan ** NULL or empty, it defaults to "/persistent". 778e3cd6760Sstephan ** 7799a4c63b0Sstephan ** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend 780e3cd6760Sstephan ** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in 78128ef9bddSstephan ** the virtual FS fails. In builds compiled without SQLITE_WASM_WASMFS 7829a4c63b0Sstephan ** defined, SQLITE_NOTFOUND is returned without side effects. 783a579f440Sstephan */ 78473079dbaSstephan WASM_KEEP 78528ef9bddSstephan int sqlite3_wasm_init_wasmfs(const char *zMountPoint){ 786a579f440Sstephan static backend_t pOpfs = 0; 7873d645484Sstephan if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs"; 788a579f440Sstephan if( !pOpfs ){ 789a579f440Sstephan pOpfs = wasmfs_create_opfs_backend(); 790a579f440Sstephan if( pOpfs ){ 7919a4c63b0Sstephan emscripten_console_log("Created WASMFS OPFS backend."); 792a579f440Sstephan } 793a579f440Sstephan } 7949a4c63b0Sstephan /** It's not enough to instantiate the backend. We have to create a 7959a4c63b0Sstephan mountpoint in the VFS and attach the backend to it. */ 796e3cd6760Sstephan if( pOpfs && 0!=access(zMountPoint, F_OK) ){ 7979a4c63b0Sstephan /* mkdir() simply hangs when called from fiddle app. Cause is 7989a4c63b0Sstephan not yet determined but the hypothesis is an init-order 7999a4c63b0Sstephan issue. */ 800e3cd6760Sstephan /* Note that this check and is not robust but it will 801e3cd6760Sstephan hypothetically suffice for the transient wasm-based virtual 802e3cd6760Sstephan filesystem we're currently running in. */ 803e3cd6760Sstephan const int rc = wasmfs_create_directory(zMountPoint, 0777, pOpfs); 8048fc8b5b3Sstephan emscripten_console_logf("OPFS mkdir(%s) rc=%d", zMountPoint, rc); 8059a4c63b0Sstephan if(rc) return SQLITE_IOERR; 8069a4c63b0Sstephan } 807a579f440Sstephan return pOpfs ? 0 : SQLITE_NOMEM; 808a579f440Sstephan } 8099a4c63b0Sstephan #else 81073079dbaSstephan WASM_KEEP 8113d645484Sstephan int sqlite3_wasm_init_wasmfs(const char *zUnused){ 8125b9973d8Sstephan emscripten_console_warn("WASMFS OPFS is not compiled in."); 8133d645484Sstephan if(zUnused){/*unused*/} 8149a4c63b0Sstephan return SQLITE_NOTFOUND; 8159a4c63b0Sstephan } 81628ef9bddSstephan #endif /* __EMSCRIPTEN__ && SQLITE_WASM_WASMFS */ 817d1582296Sstephan 81873079dbaSstephan #undef WASM_KEEP 819