mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Add a JS implementation of Java's SQLTester.
FossilOrigin-Name: b530792a514d95c4e8f93cf2170d9fc4de367055fa1704fc171551c946024fa9
This commit is contained in:
@ -181,7 +181,7 @@ public class SQLTester {
|
|||||||
private int nTestFile = 0;
|
private int nTestFile = 0;
|
||||||
//! Number of scripts which were aborted.
|
//! Number of scripts which were aborted.
|
||||||
private int nAbortedScript = 0;
|
private int nAbortedScript = 0;
|
||||||
//! Per-script test counter.
|
//! Incremented by test case handlers
|
||||||
private int nTest = 0;
|
private int nTest = 0;
|
||||||
//! True to enable column name output from execSql()
|
//! True to enable column name output from execSql()
|
||||||
private boolean emitColNames;
|
private boolean emitColNames;
|
||||||
@ -270,7 +270,6 @@ public class SQLTester {
|
|||||||
final long timeEnd = System.currentTimeMillis();
|
final long timeEnd = System.currentTimeMillis();
|
||||||
outln("🏁",(threw ? "❌" : "✅")," ",nTest," test(s) in ",
|
outln("🏁",(threw ? "❌" : "✅")," ",nTest," test(s) in ",
|
||||||
(timeEnd-timeStart),"ms.");
|
(timeEnd-timeStart),"ms.");
|
||||||
//ts.getFilename());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
final long tEnd = System.currentTimeMillis();
|
final long tEnd = System.currentTimeMillis();
|
||||||
@ -336,7 +335,9 @@ public class SQLTester {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqlite3 setCurrentDb(int n) throws Exception{
|
sqlite3 setCurrentDb(int n) throws Exception{
|
||||||
return affirmDbId(n).aDb[n];
|
affirmDbId(n);
|
||||||
|
iCurrentDb = n;
|
||||||
|
return this.aDb[n];
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3 getCurrentDb(){ return aDb[iCurrentDb]; }
|
sqlite3 getCurrentDb(){ return aDb[iCurrentDb]; }
|
||||||
@ -399,7 +400,7 @@ public class SQLTester {
|
|||||||
nullView = "nil";
|
nullView = "nil";
|
||||||
emitColNames = false;
|
emitColNames = false;
|
||||||
iCurrentDb = 0;
|
iCurrentDb = 0;
|
||||||
dbInitSql.append("SELECT 1;");
|
//dbInitSql.append("SELECT 1;");
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNullValue(String v){nullView = v;}
|
void setNullValue(String v){nullView = v;}
|
||||||
@ -580,6 +581,10 @@ public class SQLTester {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}finally{
|
}finally{
|
||||||
|
sqlite3_reset(stmt
|
||||||
|
/* In order to trigger an exception in the
|
||||||
|
INSERT...RETURNING locking scenario:
|
||||||
|
https://sqlite.org/forum/forumpost/36f7a2e7494897df */);
|
||||||
sqlite3_finalize(stmt);
|
sqlite3_finalize(stmt);
|
||||||
}
|
}
|
||||||
if( 0!=rc && throwOnError ){
|
if( 0!=rc && throwOnError ){
|
||||||
@ -924,7 +929,7 @@ class RunCommand extends Command {
|
|||||||
final sqlite3 db = (1==argv.length)
|
final sqlite3 db = (1==argv.length)
|
||||||
? t.getCurrentDb() : t.getDbById( Integer.parseInt(argv[1]) );
|
? t.getCurrentDb() : t.getDbById( Integer.parseInt(argv[1]) );
|
||||||
final String sql = t.takeInputBuffer();
|
final String sql = t.takeInputBuffer();
|
||||||
int rc = t.execSql(db, false, ResultBufferMode.NONE,
|
final int rc = t.execSql(db, false, ResultBufferMode.NONE,
|
||||||
ResultRowMode.ONELINE, sql);
|
ResultRowMode.ONELINE, sql);
|
||||||
if( 0!=rc && t.isVerbose() ){
|
if( 0!=rc && t.isVerbose() ){
|
||||||
String msg = sqlite3_errmsg(db);
|
String msg = sqlite3_errmsg(db);
|
||||||
@ -948,8 +953,7 @@ class TableResultCommand extends Command {
|
|||||||
if( !body.endsWith("\n--end") ){
|
if( !body.endsWith("\n--end") ){
|
||||||
ts.toss(argv[0], " must be terminated with --end.");
|
ts.toss(argv[0], " must be terminated with --end.");
|
||||||
}else{
|
}else{
|
||||||
int n = body.length();
|
body = body.substring(0, body.length()-6);
|
||||||
body = body.substring(0, n-6);
|
|
||||||
}
|
}
|
||||||
final String[] globs = body.split("\\s*\\n\\s*");
|
final String[] globs = body.split("\\s*\\n\\s*");
|
||||||
if( globs.length < 1 ){
|
if( globs.length < 1 ){
|
||||||
@ -1238,14 +1242,15 @@ class TestScript {
|
|||||||
final int oldPB = cur.putbackPos;
|
final int oldPB = cur.putbackPos;
|
||||||
final int oldPBL = cur.putbackLineNo;
|
final int oldPBL = cur.putbackLineNo;
|
||||||
final int oldLine = cur.lineNo;
|
final int oldLine = cur.lineNo;
|
||||||
final String rc = getLine();
|
try{ return getLine(); }
|
||||||
|
finally{
|
||||||
cur.peekedPos = cur.pos;
|
cur.peekedPos = cur.pos;
|
||||||
cur.peekedLineNo = cur.lineNo;
|
cur.peekedLineNo = cur.lineNo;
|
||||||
cur.pos = oldPos;
|
cur.pos = oldPos;
|
||||||
cur.lineNo = oldLine;
|
cur.lineNo = oldLine;
|
||||||
cur.putbackPos = oldPB;
|
cur.putbackPos = oldPB;
|
||||||
cur.putbackLineNo = oldPBL;
|
cur.putbackLineNo = oldPBL;
|
||||||
return rc;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1372,11 +1377,10 @@ class TestScript {
|
|||||||
String line;
|
String line;
|
||||||
while( (null != (line = peekLine())) ){
|
while( (null != (line = peekLine())) ){
|
||||||
checkForDirective(tester, line);
|
checkForDirective(tester, line);
|
||||||
if( !isCommandLine(line, true) ){
|
if( isCommandLine(line, true) ) break;
|
||||||
|
else {
|
||||||
sb.append(line).append("\n");
|
sb.append(line).append("\n");
|
||||||
consumePeeked();
|
consumePeeked();
|
||||||
}else{
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
line = sb.toString();
|
line = sb.toString();
|
||||||
|
55
ext/wasm/SQLTester/GNUmakefile
Normal file
55
ext/wasm/SQLTester/GNUmakefile
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#!/this/is/make
|
||||||
|
#
|
||||||
|
# This makefile compiles SQLTester test files into something
|
||||||
|
# we can readily import into JavaScript.
|
||||||
|
all:
|
||||||
|
|
||||||
|
SHELL := $(shell which bash 2>/dev/null)
|
||||||
|
MAKEFILE := $(lastword $(MAKEFILE_LIST))
|
||||||
|
CLEAN_FILES :=
|
||||||
|
DISTCLEAN_FILES := ./--dummy-- *~
|
||||||
|
|
||||||
|
test-list.mjs := test-list.mjs
|
||||||
|
test-list.mjs.gz := $(test-list.mjs).gz
|
||||||
|
CLEAN_FILES += $(test-list.mjs)
|
||||||
|
|
||||||
|
tests.dir := $(firstword $(wildcard tests ../../jni/src/tests))
|
||||||
|
$(info test script dir=$(tests.dir))
|
||||||
|
|
||||||
|
tests.all := $(wildcard $(tests.dir)/*.test)
|
||||||
|
|
||||||
|
bin.touint8array := ./touint8array
|
||||||
|
$(bin.touint8array): $(bin.touint8array).c $(MAKEFILE)
|
||||||
|
$(CC) -o $@ $<
|
||||||
|
CLEAN_FILES += $(bin.touint8array)
|
||||||
|
|
||||||
|
ifneq (,$(tests.all))
|
||||||
|
$(test-list.mjs): $(bin.touint8array) $(tests.all) $(MAKEFILE)
|
||||||
|
@{\
|
||||||
|
echo 'export default ['; \
|
||||||
|
sep=''; \
|
||||||
|
for f in $(sort $(tests.all)); do \
|
||||||
|
echo -en $$sep'{"name": "'$${f##*/}'", "content":'; \
|
||||||
|
$(bin.touint8array) < $$f; \
|
||||||
|
echo -n '}'; \
|
||||||
|
sep=',\n'; \
|
||||||
|
done; \
|
||||||
|
echo '];'; \
|
||||||
|
} > $@
|
||||||
|
@echo "Created $@"
|
||||||
|
$(test-list.mjs.gz): $(test-list.mjs)
|
||||||
|
gzip -c $< > $@
|
||||||
|
CLEAN_FILES += $(test-list.mjs.gz)
|
||||||
|
all: $(test-list.mjs.gz)
|
||||||
|
else
|
||||||
|
@echo "Cannot build $(test-list.mjs) for lack of input test files."; \
|
||||||
|
echo "Symlink ./tests to a directory containing SQLTester-format "; \
|
||||||
|
echo "test scripts named *.test, then try again"; \
|
||||||
|
exit 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: clean distclean
|
||||||
|
clean:
|
||||||
|
-rm -f $(CLEAN_FILES)
|
||||||
|
distclean: clean
|
||||||
|
-rm -f $(DISTCLEAN_FILES)
|
1296
ext/wasm/SQLTester/SQLTester.mjs
Normal file
1296
ext/wasm/SQLTester/SQLTester.mjs
Normal file
File diff suppressed because it is too large
Load Diff
145
ext/wasm/SQLTester/SQLTester.run.mjs
Normal file
145
ext/wasm/SQLTester/SQLTester.run.mjs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-29
|
||||||
|
**
|
||||||
|
** The author disclaims copyright to this source code. In place of
|
||||||
|
** a legal notice, here is a blessing:
|
||||||
|
**
|
||||||
|
** May you do good and not evil.
|
||||||
|
** May you find forgiveness for yourself and forgive others.
|
||||||
|
** May you share freely, never taking more than you give.
|
||||||
|
**
|
||||||
|
*************************************************************************
|
||||||
|
** This file contains a test application for SQLTester.js.
|
||||||
|
*/
|
||||||
|
import {default as ns} from './SQLTester.mjs';
|
||||||
|
import {default as allTests} from './test-list.mjs';
|
||||||
|
|
||||||
|
globalThis.sqlite3 = ns.sqlite3;
|
||||||
|
const log = function f(...args){
|
||||||
|
console.log('SQLTester.run:',...args);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
|
||||||
|
const out = function f(...args){ return f.outer.out(...args) };
|
||||||
|
out.outer = new ns.Outer();
|
||||||
|
out.outer.getOutputPrefix = ()=>'SQLTester.run: ';
|
||||||
|
const outln = (...args)=>{ return out.outer.outln(...args) };
|
||||||
|
|
||||||
|
const affirm = function(expr, msg){
|
||||||
|
if( !expr ){
|
||||||
|
throw new Error(arguments[1]
|
||||||
|
? ("Assertion failed: "+arguments[1])
|
||||||
|
: "Assertion failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ts = new ns.TestScript('/foo.test',`
|
||||||
|
/*
|
||||||
|
** This is a comment. There are many like it but this one is mine.
|
||||||
|
**
|
||||||
|
** SCRIPT_MODULE_NAME: sanity-check-0
|
||||||
|
** xMIXED_MODULE_NAME: mixed-module
|
||||||
|
** xMODULE_NAME: module-name
|
||||||
|
** xREQUIRED_PROPERTIES: small fast reliable
|
||||||
|
** xREQUIRED_PROPERTIES: RECURSIVE_TRIGGERS
|
||||||
|
** xREQUIRED_PROPERTIES: TEMPSTORE_MEM TEMPSTORE_FILE
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
/* --verbosity 3 */
|
||||||
|
/* ---must-fail */
|
||||||
|
/* # must fail */
|
||||||
|
/* --verbosity 0 */
|
||||||
|
--print Hello, world.
|
||||||
|
--close all
|
||||||
|
--oom
|
||||||
|
--db 0
|
||||||
|
--new my.db
|
||||||
|
--null zilch
|
||||||
|
--testcase 1.0
|
||||||
|
SELECT 1, null;
|
||||||
|
--result 1 zilch
|
||||||
|
--glob *zil*
|
||||||
|
--notglob *ZIL*
|
||||||
|
SELECT 1, 2;
|
||||||
|
intentional error;
|
||||||
|
--run
|
||||||
|
--testcase json-1
|
||||||
|
SELECT json_array(1,2,3)
|
||||||
|
--json [1,2,3]
|
||||||
|
--testcase tableresult-1
|
||||||
|
select 1, 'a';
|
||||||
|
select 2, 'b';
|
||||||
|
--tableresult
|
||||||
|
# [a-z]
|
||||||
|
2 b
|
||||||
|
--end
|
||||||
|
--testcase json-block-1
|
||||||
|
select json_array(1,2,3);
|
||||||
|
select json_object('a',1,'b',2);
|
||||||
|
--json-block
|
||||||
|
[1,2,3]
|
||||||
|
{"a":1,"b":2}
|
||||||
|
--end
|
||||||
|
--testcase col-names-on
|
||||||
|
--column-names 1
|
||||||
|
select 1 as 'a', 2 as 'b';
|
||||||
|
--result a 1 b 2
|
||||||
|
--testcase col-names-off
|
||||||
|
--column-names 0
|
||||||
|
select 1 as 'a', 2 as 'b';
|
||||||
|
--result 1 2
|
||||||
|
--close
|
||||||
|
--print Until next time
|
||||||
|
`);
|
||||||
|
|
||||||
|
const sqt = new ns.SQLTester()
|
||||||
|
.setLogger(console.log.bind(console))
|
||||||
|
.verbosity(1)
|
||||||
|
.addTestScript(ts);
|
||||||
|
|
||||||
|
const runTests = function(){
|
||||||
|
try{
|
||||||
|
if( 0 ){
|
||||||
|
affirm( !sqt.getCurrentDb(), 'sqt.getCurrentDb()' );
|
||||||
|
sqt.openDb('/foo.db', true);
|
||||||
|
affirm( !!sqt.getCurrentDb(),'sqt.getCurrentDb()' );
|
||||||
|
affirm( 'zilch' !== sqt.nullValue() );
|
||||||
|
ts.run(sqt);
|
||||||
|
affirm( 'zilch' === sqt.nullValue() );
|
||||||
|
sqt.addTestScript(ts);
|
||||||
|
sqt.runTests();
|
||||||
|
}else{
|
||||||
|
for(const t of allTests){
|
||||||
|
sqt.addTestScript( new ns.TestScript(t) );
|
||||||
|
}
|
||||||
|
allTests.length = 0;
|
||||||
|
sqt.runTests();
|
||||||
|
}
|
||||||
|
}finally{
|
||||||
|
//log( "Metrics:", sqt.metrics );
|
||||||
|
sqt.reset();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if( globalThis.WorkerGlobalScope ){
|
||||||
|
const wPost = (type,payload)=>globalThis.postMessage({type, payload});
|
||||||
|
globalThis.onmessage = function({data}){
|
||||||
|
switch(data.type){
|
||||||
|
case 'run-tests':{
|
||||||
|
try{ runTests(); }
|
||||||
|
finally{ wPost('tests-end'); }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log("unhandled onmessage: ",data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sqt.setLogger((msg)=>{
|
||||||
|
wPost('stdout', {message: msg});
|
||||||
|
});
|
||||||
|
wPost('is-ready');
|
||||||
|
//globalThis.onmessage({data:{type:'run-tests'}});
|
||||||
|
}else{
|
||||||
|
runTests();
|
||||||
|
}
|
116
ext/wasm/SQLTester/index.html
Normal file
116
ext/wasm/SQLTester/index.html
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en-us">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon">
|
||||||
|
<!--link rel="stylesheet" href="../common/emscripten.css"/-->
|
||||||
|
<link rel="stylesheet" href="../common/testing.css"/>
|
||||||
|
<title>SQLTester</title>
|
||||||
|
</head>
|
||||||
|
<style>
|
||||||
|
fieldset {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
fieldset > :not(.legend) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding-right: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<body>
|
||||||
|
<h1>SQLTester for JS/WASM</h1>
|
||||||
|
<p>This app reads in a build-time-defined set of SQLTester test
|
||||||
|
scripts and runs them through the test suite.
|
||||||
|
</p>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Options</legend>
|
||||||
|
<span class='input-wrapper'>
|
||||||
|
<input type='checkbox' id='cb-log-reverse' checked>
|
||||||
|
<label for='cb-log-reverse'>Reverse log order?</label>
|
||||||
|
</span>
|
||||||
|
<input type='button' id='btn-run-tests' value='Run tests'/>
|
||||||
|
</fieldset>
|
||||||
|
<div id='test-output'></div>
|
||||||
|
<!--script src='SQLTester.run.mjs' type='module'></script-->
|
||||||
|
<script>
|
||||||
|
(async function(){
|
||||||
|
const W = new Worker('SQLTester.run.mjs',{
|
||||||
|
type: 'module'
|
||||||
|
});
|
||||||
|
const wPost = (type,payload)=>W.postMessage({type,payload});
|
||||||
|
const mapToString = (v)=>{
|
||||||
|
switch(typeof v){
|
||||||
|
case 'string': return v;
|
||||||
|
case 'number': case 'boolean':
|
||||||
|
case 'undefined': case 'bigint':
|
||||||
|
return ''+v;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
if(null===v) return 'null';
|
||||||
|
if(v instanceof Error){
|
||||||
|
v = {
|
||||||
|
message: v.message,
|
||||||
|
stack: v.stack,
|
||||||
|
errorClass: v.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return JSON.stringify(v,undefined,2);
|
||||||
|
};
|
||||||
|
const normalizeArgs = (args)=>args.map(mapToString);
|
||||||
|
const logTarget = document.querySelector('#test-output');
|
||||||
|
const logClass = function(cssClass,...args){
|
||||||
|
const ln = document.createElement('div');
|
||||||
|
if(cssClass){
|
||||||
|
for(const c of (Array.isArray(cssClass) ? cssClass : [cssClass])){
|
||||||
|
ln.classList.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ln.append(document.createTextNode(normalizeArgs(args).join(' ')));
|
||||||
|
logTarget.append(ln);
|
||||||
|
};
|
||||||
|
{
|
||||||
|
const cbReverse = document.querySelector('#cb-log-reverse');
|
||||||
|
const cbReverseKey = 'SQLTester:cb-log-reverse';
|
||||||
|
const cbReverseIt = ()=>{
|
||||||
|
logTarget.classList[cbReverse.checked ? 'add' : 'remove']('reverse');
|
||||||
|
};
|
||||||
|
cbReverse.addEventListener('change', cbReverseIt, true);
|
||||||
|
cbReverseIt();
|
||||||
|
}
|
||||||
|
|
||||||
|
const btnRun = document.querySelector('#btn-run-tests');
|
||||||
|
const runTests = ()=>{
|
||||||
|
btnRun.setAttribute('disabled','disabled');
|
||||||
|
wPost('run-tests');
|
||||||
|
logTarget.innerText = 'Running tests...';
|
||||||
|
}
|
||||||
|
btnRun.addEventListener('click', runTests);
|
||||||
|
const log2 = function f(...args){
|
||||||
|
logClass('', ...args);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
const log = function f(...args){
|
||||||
|
logClass('','index.html:',...args);
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
W.onmessage = function({data}){
|
||||||
|
switch(data.type){
|
||||||
|
case 'stdout': log2(data.payload.message); break;
|
||||||
|
case 'tests-end': btnRun.removeAttribute('disabled'); break;
|
||||||
|
case 'is-ready':
|
||||||
|
log("SQLTester.run.mjs is ready.");
|
||||||
|
runTests(); break;
|
||||||
|
default:
|
||||||
|
log("unhandled onmessage",data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//runTests()
|
||||||
|
/* Inexplicably, */
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
29
ext/wasm/SQLTester/touint8array.c
Normal file
29
ext/wasm/SQLTester/touint8array.c
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
** 2023-08-29
|
||||||
|
**
|
||||||
|
** The author disclaims copyright to this source code. In place of
|
||||||
|
** a legal notice, here is a blessing:
|
||||||
|
**
|
||||||
|
** May you do good and not evil.
|
||||||
|
** May you find forgiveness for yourself and forgive others.
|
||||||
|
** May you share freely, never taking more than you give.
|
||||||
|
**
|
||||||
|
*************************************************************************
|
||||||
|
** This file contains a tool for writing out the contents of stdin as
|
||||||
|
** a comma-separated list of numbers, one per byte.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
int main(int argc, char const **argv){
|
||||||
|
int i;
|
||||||
|
int rc = 0, colWidth = 30;
|
||||||
|
int ch;
|
||||||
|
printf("[");
|
||||||
|
for( i=0; EOF!=(ch = fgetc(stdin)); ++i ){
|
||||||
|
if( 0!=i ) printf(",");
|
||||||
|
if( i && 0==(i%colWidth) ) puts("");
|
||||||
|
printf("%d",ch);
|
||||||
|
}
|
||||||
|
printf("]");
|
||||||
|
return rc;
|
||||||
|
}
|
@ -1135,7 +1135,23 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
return 1===n
|
return 1===n
|
||||||
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
|
? wasm.pstack.alloc(safePtrSize ? 8 : wasm.ptrSizeof)
|
||||||
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
|
: wasm.pstack.allocChunks(n, safePtrSize ? 8 : wasm.ptrSizeof);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
Records the current pstack position, calls the given function,
|
||||||
|
passing it the sqlite3 object, then restores the pstack
|
||||||
|
regardless of whether the function throws. Returns the result
|
||||||
|
of the call or propagates an exception on error.
|
||||||
|
|
||||||
|
Added in 3.44.
|
||||||
|
*/
|
||||||
|
call: function(f){
|
||||||
|
const stackPos = wasm.pstack.pointer;
|
||||||
|
try{ return f(sqlite3) } finally{
|
||||||
|
wasm.pstack.restore(stackPos);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})/*wasm.pstack*/;
|
})/*wasm.pstack*/;
|
||||||
Object.defineProperties(wasm.pstack, {
|
Object.defineProperties(wasm.pstack, {
|
||||||
/**
|
/**
|
||||||
@ -1543,6 +1559,26 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts SQL input from a variety of convenient formats
|
||||||
|
to plain strings.
|
||||||
|
|
||||||
|
If v is a string, it is returned as-is. If it is-a Array, its
|
||||||
|
join("") result is returned. If is is a Uint8Array, Int8Array,
|
||||||
|
or ArrayBuffer, it is assumed to hold UTF-8-encoded text and is
|
||||||
|
decoded to a string. If it looks like a WASM pointer,
|
||||||
|
wasm.cstrToJs(sql) is returned. Else undefined is returned.
|
||||||
|
|
||||||
|
Added in 3.44
|
||||||
|
*/
|
||||||
|
capi.sqlite3_js_sql_to_string = (sql)=>{
|
||||||
|
if('string' === typeof sql){
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
const x = flexibleString(v);
|
||||||
|
return x===v ? undefined : x;
|
||||||
|
}
|
||||||
|
|
||||||
if( util.isUIThread() ){
|
if( util.isUIThread() ){
|
||||||
/* Features specific to the main window thread... */
|
/* Features specific to the main window thread... */
|
||||||
|
|
||||||
|
@ -1801,6 +1801,118 @@ char * sqlite3_wasm_test_str_hello(int fail){
|
|||||||
}
|
}
|
||||||
return s;
|
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 */
|
#endif /* SQLITE_WASM_TESTS */
|
||||||
|
|
||||||
#undef SQLITE_WASM_EXPORT
|
#undef SQLITE_WASM_EXPORT
|
||||||
|
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
|||||||
C New\sconversion\sletters\sadded\sto\sstrftime():\s%e,\s%k,\s%I,\s%l,\s%R,\s%P,\s%p,\s%T,\s%u.
|
C Add\sa\sJS\simplementation\sof\sJava's\sSQLTester.
|
||||||
D 2023-08-29T18:28:08.008
|
D 2023-08-30T13:07:35.058
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -283,7 +283,7 @@ F ext/jni/src/org/sqlite/jni/sqlite3.java 62b1b81935ccf3393472d17cb883dc5ff39c38
|
|||||||
F ext/jni/src/org/sqlite/jni/sqlite3_context.java 66ca95ce904044263a4aff684abe262d56f73e6b06bca6cf650761d79d7779ad
|
F ext/jni/src/org/sqlite/jni/sqlite3_context.java 66ca95ce904044263a4aff684abe262d56f73e6b06bca6cf650761d79d7779ad
|
||||||
F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc
|
F ext/jni/src/org/sqlite/jni/sqlite3_stmt.java 78e6d1b95ac600a9475e9db4623f69449322b0c93d1bd4e1616e76ed547ed9fc
|
||||||
F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a
|
F ext/jni/src/org/sqlite/jni/sqlite3_value.java 3d1d4903e267bc0bc81d57d21f5e85978eff389a1a6ed46726dbe75f85e6914a
|
||||||
F ext/jni/src/org/sqlite/jni/tester/SQLTester.java bf350903abe04a9bed2d8a2a71692ed4291dbb4eece2d3329ed91d15b0321e6d
|
F ext/jni/src/org/sqlite/jni/tester/SQLTester.java e5a1a4b55ed940e61558be1292aa66563219f360c7c1f9d40d770307e6da3c07
|
||||||
F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md f9f25126127045d051e918fe59004a1485311c50a13edbf18c79a6ff9160030e
|
F ext/jni/src/org/sqlite/jni/tester/test-script-interpreter.md f9f25126127045d051e918fe59004a1485311c50a13edbf18c79a6ff9160030e
|
||||||
F ext/jni/src/tests/000-000-sanity.test cfe6dc1b950751d6096e3f5695becaadcdaa048bfe9567209d6eb676e693366d
|
F ext/jni/src/tests/000-000-sanity.test cfe6dc1b950751d6096e3f5695becaadcdaa048bfe9567209d6eb676e693366d
|
||||||
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
|
F ext/jni/src/tests/000-001-ignored.test e17e874c6ab3c437f1293d88093cf06286083b65bf162317f91bbfd92f961b70
|
||||||
@ -548,6 +548,11 @@ F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34ce
|
|||||||
F ext/wasm/GNUmakefile 0e362f3fc04eab6628cbe4f1e35f4ab4a200881f6b5f753b27fb45eabeddd9d2
|
F ext/wasm/GNUmakefile 0e362f3fc04eab6628cbe4f1e35f4ab4a200881f6b5f753b27fb45eabeddd9d2
|
||||||
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576
|
||||||
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193
|
||||||
|
F ext/wasm/SQLTester/GNUmakefile e0794f676d55819951bbfae45cc5e8d7818dc460492dc317ce7f0d2eca15caff
|
||||||
|
F ext/wasm/SQLTester/SQLTester.mjs 4a8fc2194a67180772830f503129c93fe44887b9573f50a4e24868b4bbc817f4
|
||||||
|
F ext/wasm/SQLTester/SQLTester.run.mjs a50a1f9314d22d68b62a2f21d8913de163fce1fa420229711d6749c2b4fff9d0
|
||||||
|
F ext/wasm/SQLTester/index.html e5f18af71749d81d86e4649d8c6efc9b78361738cb8e5c5014ba0dd3dc3de6ac
|
||||||
|
F ext/wasm/SQLTester/touint8array.c 2d5ece04ec1393a6a60c4bf96385bda5e1a10ad49f3038b96460fc5e5aa7e536
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab
|
||||||
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see fb29e62082a658f0d81102488414d422c393c4b20cc2f685b216bc566237957b
|
||||||
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
F ext/wasm/api/EXPORTED_RUNTIME_METHODS.sqlite3-api 1ec3c73e7d66e95529c3c64ac3de2470b0e9e7fbf7a5b41261c367cf4f1b7287
|
||||||
@ -560,14 +565,14 @@ F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057af
|
|||||||
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e
|
||||||
F ext/wasm/api/sqlite3-api-glue.js b65e546568f1dfb35205b9792feb5146a6323d71b55cda58e2ed30def6dd52f3
|
F ext/wasm/api/sqlite3-api-glue.js b65e546568f1dfb35205b9792feb5146a6323d71b55cda58e2ed30def6dd52f3
|
||||||
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8
|
||||||
F ext/wasm/api/sqlite3-api-prologue.js ef6f67c5ea718490806e5e17d2644b8b2f6e6ba5284d23dc1fbfd14d401c1ab5
|
F ext/wasm/api/sqlite3-api-prologue.js 9aeba7b45cf41b3a26d34d7fb2525633cd1adfc544888c1ea8dbb077496f4ce9
|
||||||
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec
|
||||||
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89
|
||||||
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379
|
||||||
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 561463ac5380e4ccf1839a1922e6d7a5585660f32e3b9701a270b78cd35566cf
|
F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js 561463ac5380e4ccf1839a1922e6d7a5585660f32e3b9701a270b78cd35566cf
|
||||||
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js d9e62d42b86f7bb3143eb071628b24e2ba7dcc749e41a0e9d3e2451bfea1a6b6
|
F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js d9e62d42b86f7bb3143eb071628b24e2ba7dcc749e41a0e9d3e2451bfea1a6b6
|
||||||
F ext/wasm/api/sqlite3-wasm.c 6773e949034369ddd2a1efdedc39b2808a10b7274b0769188905432e561feebe
|
F ext/wasm/api/sqlite3-wasm.c 65d60439671e24d50d9119ca805ac1c68fb36129e164377eb46f8d037bd88b07
|
||||||
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f
|
||||||
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
|
F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75
|
||||||
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8
|
||||||
@ -2110,8 +2115,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 253fe4a45decdcc4180c5aeccaf4cd0d1325a0f6df0913b0e6721ea3e26b4fe2
|
P 058722b2d0b995195a8ce3effe9722ae1c18cb1e7a520b481030da0bd579fe41 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c
|
||||||
R ec116b42076aac24bc9f57b015b724bc
|
R 1d37ca9b2e6614cb5d02f3816f204e9d
|
||||||
U drh
|
T +closed 249e82b9917ea47c56ee1cbd3345a977d335fd3fc0d67a1ef157813ef4571c7c Closed\sby\sintegrate-merge.
|
||||||
Z f129cd2d47b4d4fea322d97826168fb6
|
U stephan
|
||||||
|
Z 4d7d0ed957593edddd1409081f78edf6
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
058722b2d0b995195a8ce3effe9722ae1c18cb1e7a520b481030da0bd579fe41
|
b530792a514d95c4e8f93cf2170d9fc4de367055fa1704fc171551c946024fa9
|
Reference in New Issue
Block a user