1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Remove some unused sqlite3_status() codes from the JS API. Add custom JS wrappers for sqlite3_create_collation/_v2() which accept JS functions (plus tests). Expand the argument options for sqlite3_wasm_db_error() to enable it to translate exception objects to C-level errors.

FossilOrigin-Name: 073a2f1eb006230ae0995a5ea6c789407bcaa819ec15b5064c66d8973ed4671a
This commit is contained in:
stephan
2022-12-09 12:12:49 +00:00
parent 81a3683174
commit 3ec44736b5
6 changed files with 125 additions and 17 deletions

View File

@ -158,9 +158,35 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
delete wasm.bindingSignatures;
if(wasm.exports.sqlite3_wasm_db_error){
util.sqlite3_wasm_db_error = wasm.xWrap(
const __db_err = wasm.xWrap(
'sqlite3_wasm_db_error', 'int', 'sqlite3*', 'int', 'string'
);
/**
Sets the given db's error state. Accepts:
- (sqlite3*, int code, string msg)
- (sqlite3*, Error [,string msg])
If passed a WasmAllocError, the message is ingored and the
result code is SQLITE_NOMEM. If passed any other Error type,
the result code defaults to SQLITE_ERROR unless the Error
object has a resultCode property, in which case that is used
(e.g. SQLite3Error has that). If passed a non-WasmAllocError
exception, the message string defaults to theError.message.
Returns the resulting code. Pass (pDb,0,0) to clear the error
state.
*/
util.sqlite3_wasm_db_error = function(pDb, resultCode, message){
if(resultCode instanceof sqlite3.WasmAllocError){
resultCode = capi.SQLITE_NOMEM;
message = 0 /*avoid allocating message string*/;
}else if(resultCode instanceof Error){
message = message || resultCode.message;
resultCode = (resultCode.resultCode || capi.SQLITE_ERROR);
}
return __db_err(pDb, resultCode, message);
};
}else{
util.sqlite3_wasm_db_error = function(pDb,errCode,msg){
console.warn("sqlite3_wasm_db_error() is not exported.",arguments);
@ -180,6 +206,61 @@ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
(1===n?"":'s')+".");
};
if(1){/* Bindings for sqlite3_create_collation() */
const __ccv2 = wasm.xWrap(
'sqlite3_create_collation_v2', 'int',
'sqlite3*','string','int','*','*','*'
/* int(*xCompare)(void*,int,const void*,int,const void*) */
/* void(*xDestroy(void*) */);
/**
Works exactly like C's sqlite3_create_collation_v2() except that:
1) It permits its two function arguments to be JS functions,
for which it will install WASM-bound proxies.
2) It returns capi.SQLITE_FORMAT if the 3rd argument is not
capi.SQLITE_UTF8. No other encodings are supported.
Returns 0 on success, non-0 on error, in which case the error
state of pDb (of type `sqlite3*` or argument-convertible to it)
may contain more information.
*/
capi.sqlite3_create_collation_v2 = function(pDb,zName,eTextRep,pArg,xCompare,xDestroy){
if(6!==arguments.length) return __dbArgcMismatch(pDb, 'sqlite3_create_collation_v2', 6);
else if(capi.SQLITE_UTF8!==eTextRep){
return util.sqlite3_wasm_db_error(
pDb, capi.SQLITE_FORMAT, "SQLITE_UTF8 is the only supported encoding."
);
}
let rc, pfCompare, pfDestroy;
try{
if(xCompare instanceof Function){
pfCompare = wasm.installFunction(xCompare, 'i(pipip)');
}
if(xDestroy instanceof Function){
pfDestroy = wasm.installFunction(xDestroy, 'v(p)');
}
rc = __ccv2(pDb, zName, eTextRep, pArg,
pfCompare || xCompare, pfDestroy || xDestroy);
}catch(e){
if(pfCompare) wasm.uninstallFunction(pfCompare);
if(pfDestroy) wasm.uninstallFunction(pfDestroy);
rc = util.sqlite3_wasm_db_error(pDb, e);
}
return rc;
};
capi.sqlite3_create_collation = (pDb,zName,eTextRep,pArg,xCompare)=>{
return (5===arguments.length)
? capi.sqlite3_create_collation_v2(pDb,zName,eTextRep,pArg,xCompare,0)
: __dbArgcMismatch(pDb, 'sqlite3_create_collation', 5);
}
}/*sqlite3_create_collation() and friends*/
if(1){/* Special-case handling of sqlite3_exec() */
const __exec = wasm.xWrap("sqlite3_exec", "int",
["sqlite3*", "string:flexible", "*", "*", "**"]);

View File

@ -936,12 +936,16 @@ self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
/* sqlite3_create_function(), sqlite3_create_function_v2(), and
sqlite3_create_window_function() use hand-written bindings to
simplify handling of their function-type arguments. */
["sqlite3_create_collation", "int",
"sqlite3*", "string", "int"/*SQLITE_UTF8 is the only legal value*/,
/* sqlite3_create_collation() and sqlite3_create_collation_v2()
use hand-written bindings to simplify passing of the callback
function.
["sqlite3_create_collation", "int",
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
"*", "*"],
["sqlite3_create_collation_v2", "int",
"sqlite3*", "string", "int"/*SQLITE_UTF8 is the only legal value*/,
"sqlite3*", "string", "int",//SQLITE_UTF8 is the only legal value
"*", "*", "*"],
*/
["sqlite3_data_count", "int", "sqlite3_stmt*"],
["sqlite3_db_filename", "string", "sqlite3*", "string"],
["sqlite3_db_handle", "sqlite3*", "sqlite3_stmt*"],

View File

@ -706,12 +706,12 @@ const char * sqlite3_wasm_enum_json(void){
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_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_SCRATCH_SIZE) /* NOT USED */;
DefInt(SQLITE_STATUS_MALLOC_COUNT);
} _DefGroup;

View File

@ -2106,6 +2106,29 @@ self.sqlite3InitModule = sqlite3InitModule;
.assert(2000===list[0][1]);
}
})/*custom vtab #2*/
////////////////////////////////////////////////////////////////////////
.t('Custom collation', function(sqlite3){
let myCmp = function(pArg,n1,p1,n2,p2){
//int (*)(void*,int,const void*,int,const void*)
const rc = wasm.exports.sqlite3_strnicmp(p1,p2,(n1<n2?n1:n2));
return rc ? rc : (n1 - n2);
};
let rc = capi.sqlite3_create_collation_v2(this.db, "mycollation", capi.SQLITE_UTF8,
0, myCmp, 0);
this.db.checkRc(rc);
rc = this.db.selectValue("select 'hi' = 'HI' collate mycollation");
T.assert(1===rc);
rc = this.db.selectValue("select 'hii' = 'HI' collate mycollation");
T.assert(0===rc);
rc = this.db.selectValue("select 'hi' = 'HIi' collate mycollation");
T.assert(0===rc);
rc = capi.sqlite3_create_collation(this.db,"hi",capi.SQLITE_UTF8/*not enough args*/);
T.assert(capi.SQLITE_MISUSE === rc);
rc = capi.sqlite3_create_collation_v2(this.db,"hi",0/*wrong encoding*/,0,0,0);
T.assert(capi.SQLITE_FORMAT === rc)
.mustThrowMatching(()=>this.db.checkRc(rc),
/SQLITE_UTF8 is the only supported encoding./);
})
////////////////////////////////////////////////////////////////////////
.t('Close db', function(){