wasm: added bindings for sqlite3_extended_result_codes(), sqlite3_open_v2(), and the SQLITE_OPEN_... flags.

FossilOrigin-Name: ac876ab9913332c9a5e3045824bf92a2501707aecfb13906d5c280302d9878a9
This commit is contained in:
stephan 2022-06-25 19:07:58 +00:00
parent 0702c63bc0
commit f79d277999
6 changed files with 87 additions and 27 deletions

View File

@ -26,6 +26,7 @@ _sqlite3_data_count
_sqlite3_db_filename
_sqlite3_errmsg
_sqlite3_exec
_sqlite3_extended_result_codes
_sqlite3_finalize
_sqlite3_interrupt
_sqlite3_libversion

View File

@ -162,11 +162,43 @@ Module.postRun.push(function(namespace/*the module object, the target for
The main sqlite3 binding API gets installed into this object,
mimicking the C API as closely as we can. The numerous members
names with prefixes 'sqlite3_' and 'SQLITE_' behave, insofar as
possible, identically to the C-native counterparts. A very few
exceptions may require an additional level of proxy function, as
documented in this object.
possible, identically to the C-native counterparts, as documented at:
https://www.sqlite.org/c3ref/intro.html
A very few exceptions require an additional level of proxy
function or may otherwise require special attention in the WASM
environment, and all such cases are document here. Those not
documented here are installed as 1-to-1 proxies for their C-side
counterparts.
*/
const api = {
/**
When using sqlite3_open_v2() it is important to keep the following
in mind:
https://www.sqlite.org/c3ref/open.html
- The flags for use with its 3rd argument are installed in this
object using the C-cide names, e.g. SQLITE_OPEN_CREATE.
- If the combination of flags passed to it are invalid,
behavior is undefined. Thus is is never okay to call this
with fewer than 3 arguments, as JS will default the
missing arguments to `undefined`, which will result in a
flag value of 0. Most of the available SQLITE_OPEN_xxx
flags are meaningless in the WASM build, e.g. the mutext-
and cache-related flags, but they are retained in this
API for consistency's sake.
- The final argument to this function specifies the VFS to
use, which is largely (but not entirely!) meaningless in
the WASM environment. It should always be null or
undefined, and it is safe to elide that argument when
calling this function.
*/
sqlite3_open_v2: function(filename,dbPtrPtr,flags,vfsStr){}/*installed later*/,
/**
The sqlite3_prepare_v2() binding handles two different uses
with differing JS/WASM semantics:
@ -204,11 +236,11 @@ Module.postRun.push(function(namespace/*the module object, the target for
If sql is not a string or supported TypedArray, it must be
a _pointer_ to a string which was allocated via
api.wasm.allocateUTF8OnStack(), api.wasm._malloc(), or
equivalent. In that case,
the final argument may be 0/null/undefined or must be a
pointer to which the "tail" of the compiled SQL is written,
as documented for the C-side sqlite3_prepare_v2(). In case
(2), the underlying C function is called with:
equivalent. In that case, the final argument may be
0/null/undefined or must be a pointer to which the "tail"
of the compiled SQL is written, as documented for the
C-side sqlite3_prepare_v2(). In case (2), the underlying C
function is called with:
(pDb, sqlAsPointer, -1, ppStmt, pzTail)
@ -219,14 +251,14 @@ Module.postRun.push(function(namespace/*the module object, the target for
sqlAsPointer value.
If passed an invalid 2nd argument type, this function will
throw. That behaviour is in strong constrast to all of the
throw. That behavior is in strong constrast to all of the
other C-bound functions (which return a non-0 result code
on error) but is necessary because we have to way to set
the db's error state such that this function could return a
non-0 integer and the client could call sqlite3_errcode()
or sqlite3_errmsg() to fetch it.
*/
sqlite3_prepare_v2: undefined/*installed later*/,
sqlite3_prepare_v2: function(dbPtr, sql, sqlByteLen, stmtPtrPtr, strPtrPtr){}/*installed later*/,
/**
Holds state which are specific to the WASM-related
@ -345,12 +377,12 @@ Module.postRun.push(function(namespace/*the module object, the target for
["sqlite3_db_filename", "string", ["number", "string"]],
["sqlite3_errmsg", "string", ["number"]],
["sqlite3_exec", "number", ["number", "string", "number", "number", "number"]],
["sqlite3_extended_result_codes", "number", ["number", "number"]],
["sqlite3_finalize", "number", ["number"]],
["sqlite3_interrupt", "void", ["number"]],
["sqlite3_libversion", "string", []],
["sqlite3_open", "number", ["string", "number"]],
//["sqlite3_open_v2", "number", ["string", "number", "number", "string"]],
//^^^^ TODO: add the flags needed for the 3rd arg
["sqlite3_open_v2", "number", ["string", "number", "number", "string"]],
/* sqlite3_prepare_v2() is handled separately due to us requiring two
different sets of semantics for that function. */
["sqlite3_reset", "number", ["number"]],
@ -406,8 +438,9 @@ Module.postRun.push(function(namespace/*the module object, the target for
/* Import C-level constants... */
//console.log("wasmEnum=",SQM.ccall('sqlite3_wasm_enum_json', 'string', []));
const wasmEnum = JSON.parse(SQM.ccall('sqlite3_wasm_enum_json', 'string', []));
['resultCodes','dataTypes','udfFlags',
'encodings','blobFinalizers'].forEach(function(t){
['blobFinalizers', 'dataTypes','encodings',
'openFlags', 'resultCodes','udfFlags'
].forEach(function(t){
Object.keys(wasmEnum[t]).forEach(function(k){
api[k] = wasmEnum[t][k];
});
@ -493,6 +526,12 @@ Module.postRun.push(function(namespace/*the module object, the target for
class, ":memory:" DBs are not supported (until/unless we can
find a way to export those as well). The naming semantics will
certainly evolve as this API does.
The db is opened with a fixed set of flags:
(SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
SQLITE_OPEN_EXRESCODE). This API may change in the future
permit the caller to provide those flags via an additional
argument.
*/
const DB = function(arg){
let buffer, fn;
@ -526,7 +565,11 @@ Module.postRun.push(function(namespace/*the module object, the target for
const stack = api.wasm.stackSave();
const ppDb = api.wasm.stackAlloc(4) /* output (sqlite3**) arg */;
api.wasm.setValue(ppDb, 0, "i32");
try {this.checkRc(api.sqlite3_open(fn, ppDb));}
try {
this.checkRc(api.sqlite3_open_v2(fn, ppDb, api.SQLITE_OPEN_READWRITE
| api.SQLITE_OPEN_CREATE
| api.SQLITE_OPEN_EXRESCODE, null));
}
finally{api.wasm.stackRestore(stack);}
this._pDb = api.wasm.getValue(ppDb, "i32");
this.filename = fn;

View File

@ -27,7 +27,8 @@
const test1 = function(db,sqlite3){
const api = sqlite3.api;
log("Basic sanity tests...");
T.assert(db._pDb);
T.assert(db._pDb).
assert(0===api.sqlite3_extended_result_codes(db._pDb,1));
let st = db.prepare(
new TextEncoder('utf-8').encode("select 3 as a")
/* Testing handling of Uint8Array input */
@ -200,7 +201,8 @@
log("wasmEnum",JSON.parse(Module.ccall('sqlite3_wasm_enum_json', 'string', [])));
[ /* Spot-check a handful of constants to make sure they got installed... */
'SQLITE_SCHEMA','SQLITE_NULL','SQLITE_UTF8',
'SQLITE_STATIC', 'SQLITE_DIRECTONLY'
'SQLITE_STATIC', 'SQLITE_DIRECTONLY',
'SQLITE_OPEN_CREATE'
].forEach(function(k){
T.assert('number' === typeof api[k]);
});

View File

@ -103,6 +103,20 @@ const char * sqlite3_wasm_enum_json(void){
SD(SQLITE_DIRECTONLY);
SDFinal(SQLITE_INNOCUOUS);
sqlite3_str_appendall(s,",\"openFlags\": {");
/* Noting that not all of these will have any effect in WASM-space. */
SD(SQLITE_OPEN_READONLY);
SD(SQLITE_OPEN_READWRITE);
SD(SQLITE_OPEN_CREATE);
SD(SQLITE_OPEN_URI);
SD(SQLITE_OPEN_MEMORY);
SD(SQLITE_OPEN_NOMUTEX);
SD(SQLITE_OPEN_FULLMUTEX);
SD(SQLITE_OPEN_SHAREDCACHE);
SD(SQLITE_OPEN_PRIVATECACHE);
SD(SQLITE_OPEN_EXRESCODE);
SDFinal(SQLITE_OPEN_NOFOLLOW);
#undef SD_
#undef SD
#undef SDFinal

View File

@ -1,5 +1,5 @@
C wasm:\slots\sof\sdoc\sadditions\sand\srefactoring.\sRefactored\sthe\sWASM\smemory\sheap\susage\sto\shopefully\seventually\saccount\sfor\sa\sruntime-growable\sheap.\sDifferentiate\sbetween\ssupported\sTypedArray\stypes\sfor\sinput\sSQL\sstrings\svs\sbinding/fetching\sblobs.\sMight\s(untested)\shave\simplemented\sthe\sability\sto\sbind\sUtfNNArray\svalues\sas\sblobs,\swhere\sNN\sis\sone\sof\s16\sor\s32.
D 2022-06-25T18:18:45.580
C wasm:\sadded\sbindings\sfor\ssqlite3_extended_result_codes(),\ssqlite3_open_v2(),\sand\sthe\sSQLITE_OPEN_...\sflags.
D 2022-06-25T19:07:58.321
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -56,7 +56,7 @@ F ext/expert/sqlite3expert.c 6ca30d73b9ed75bd56d6e0d7f2c962d2affaa72c505458619d0
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
F ext/fiddle/EXPORTED_FUNCTIONS.fiddle 7fb73f7150ab79d83bb45a67d257553c905c78cd3d693101699243f36c5ae6c3
F ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api 2ef8a8d58815a96de196d085b8aaf126400b8d13a5b7f724f86dfe9f61d0600d
F ext/fiddle/EXPORTED_FUNCTIONS.sqlite3-api 356c356931b58eccf68367120f304db43ab6c2ef2f62f17f12f5a99737b43c38
F ext/fiddle/EXPORTED_RUNTIME_METHODS a004bd5eeeda6d3b28d16779b7f1a80305bfe009dfc7f0721b042967f0d39d02
F ext/fiddle/Makefile e25d34a0e1324f771d64c09c592601b97219282011587e6ce410fa8acdedb913
F ext/fiddle/SqliteTestUtil.js 2e87d424b12674476bdf8139934dcacc3ff8a7a5f5ff4392ba5e5a8d8cee9fbd
@ -65,14 +65,14 @@ F ext/fiddle/fiddle-worker.js 88bc2193a6cb6a3f04d8911bed50a4401fe6f277de7a71ba83
F ext/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
F ext/fiddle/fiddle.js 812f9954cc7c4b191884ad171f36fcf2d0112d0a7ecfdf6087896833a0c079a8
F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
F ext/fiddle/sqlite3-api.js 690921c0daabde10f7eea1fd1d2d4b034ef0d66d68292931403be0b8e6fccf6a
F ext/fiddle/sqlite3-api.js add7b016798bc77de39573e4d9f65a35d4a4e1dce0abe6a15da70d99c0c6994a
F ext/fiddle/sqlite3-worker.js 50b7a9ce14c8fae0af965e35605fe12cafb79c1e01e99216d8110d8b02fbf4b5
F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a
F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a
F ext/fiddle/testing1.js b7e34d83d6cb2f640311654266cbbe85f4144ef31fda7615d6e91c6486d3890f
F ext/fiddle/testing1.js fbeac92a5ac22668a54fd358ffc75c275d83e505e770aa484045614cb2a6cf44
F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4
F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee
F ext/fiddle/wasm_util.c dc9f6e8882b0777037b01d2c8ef2dd9360306a37980f6908cfa3909bf6c25da7
F ext/fiddle/wasm_util.c 5944e38a93d3a436a47dd7c69059844697b6a5e44499656baa6da0ffe7fe23d5
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
F ext/fts1/ft_hash.c 3927bd880e65329bdc6f506555b228b28924921b
F ext/fts1/ft_hash.h 06df7bba40dadd19597aa400a875dbc2fed705ea
@ -1979,8 +1979,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 778062e3b415dca5104eee398950741b6dbb9d4bdf7c998eef18371a42669946
R 7173ecb48dc9d037c18c86459c1a9792
P e10d57dfbaa672a3a4cbfd9a9209552c3bde15cc75af838690ca412fd182066a
R 43f4d6e17f529d8fb5204f439ce0ffd6
U stephan
Z d57bc6484b99c6c0083ee3c3d006ea5c
Z d6d33ac3906437150708dfba4da65152
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
e10d57dfbaa672a3a4cbfd9a9209552c3bde15cc75af838690ca412fd182066a
ac876ab9913332c9a5e3045824bf92a2501707aecfb13906d5c280302d9878a9