module-init-internal state which isn't normally visible to
us.
*/
- allocate: (slab, allocator=SQM.ALLOC_NORMAL)=>SQM.allocate(slab, allocator)
+ allocate: (slab, allocator=SQM.ALLOC_NORMAL)=>SQM.allocate(slab, allocator),
+ /**
+ The buffer which holds the heap memory managed by the
+ emscripten-installed allocator.
+ */
+ HEAP8: SQM.HEAP8
}
};
[/* C-side functions to bind. Each entry is an array with 3 or 4
/** Returns true if n is a 32-bit (signed) integer,
else false. */
const isInt32 = function(n){
- return (n===n|0 && n<0xFFFFFFFF) ? true : undefined;
+ return (n===(n|0) && n<0xFFFFFFFF) ? true : undefined;
};
/**
};
if(out.sql instanceof Uint8Array){
out.sql = uint8ToString(out.sql);
+ }else if(Array.isArray(out.sql)){
+ out.sql = out.sql.join('');
}else if('string'!==typeof out.sql){
toss("Missing SQL argument.");
}
properties:
- .sql = the SQL to run (unless it's provided as the first
- argument). This must be of type string or Uint8Array.
+ argument). This must be of type string, Uint8Array, or an
+ array of strings (in which case they're concatenated
+ together as-is, with no separator between elements,
+ before evaluation).
- .bind = a single value valid as an argument for
Stmt.bind(). This is ONLY applied to the FIRST non-empty
parameters. (Empty statements are skipped entirely.)
- .callback = a function which gets called for each row of
- the FIRST statement in the SQL (if it has any result
- rows). The second argument passed to the callback is
- always the current Stmt object (so that the caller
- may collect column names, or similar). The first
- argument passed to the callback defaults to the current
- Stmt object but may be changed with ...
+ the FIRST statement in the SQL which has result
+ _columns_, but only if that statement has any result
+ _rows_. The second argument passed to the callback is
+ always the current Stmt object (so that the caller may
+ collect column names, or similar). The first argument
+ passed to the callback defaults to the current Stmt
+ object but may be changed with ...
- .rowMode = a string describing what type of argument
should be passed as the first argument to the callback. A
stmt.bind(bind);
bind = null;
}
- if(opt.callback && null!==rowMode){
+ if(opt.callback && null!==rowMode && stmt.columnCount){
while(stmt.step()){
stmt._isLocked = true;
callback(arg.cbArg(stmt), stmt);
case api.SQLITE_FLOAT:
arg = api.sqlite3_value_double(pVal);
break;
- case SQLITE_TEXT:
+ case api.SQLITE_TEXT:
arg = api.sqlite3_value_text(pVal);
break;
- case SQLITE_BLOB:{
- const n = api.sqlite3_value_bytes(ptr);
- const pBlob = api.sqlite3_value_blob(ptr);
+ case api.SQLITE_BLOB:{
+ const n = api.sqlite3_value_bytes(pVal);
+ const pBlob = api.sqlite3_value_blob(pVal);
arg = new Uint8Array(n);
let i;
- for(i = 0; i < n; ++i) arg[i] = HEAP8[pBlob+i];
+ for(i = 0; i < n; ++i) arg[i] = api.wasm.HEAP8[pBlob+i];
break;
}
default:
api.wasm.allocate(val);
api.sqlite3_result_blob(pCx, pBlob, val.length,
api.SQLITE_TRANSIENT);
- api.wasm._free(blobptr);
+ api.wasm._free(pBlob);
break;
}
// else fall through
const affirmParamIndex = function(stmt,key){
const n = ('number'===typeof key)
? key : api.sqlite3_bind_parameter_index(stmt._pStmt, key);
- if(0===n || (n===key && (n!==(n|0)/*floating point*/))){
+ if(0===n || !isInt32(n)){
toss("Invalid bind() parameter name: "+key);
}
else if(n<1 || n>stmt.parameterCount) toss("Bind index",key,"is out of range.");
const n = api.sqlite3_column_bytes(this._pStmt, ndx);
const ptr = api.sqlite3_column_blob(this._pStmt, ndx);
const rc = new Uint8Array(n);
- for(let i = 0; i < n; ++i) rc[i] = HEAP8[ptr + i];
+ for(let i = 0; i < n; ++i) rc[i] = api.wasm.HEAP8[ptr + i];
if(n && this.db._blobXfer instanceof Array){
/* This is an optimization soley for the
Worker-based API. These values will be
let list = [];
db.exec({
- sql:`CREATE TABLE t(a,b);
-INSERT INTO t(a,b) VALUES(1,2),(3,4),(?,?);`,
+ sql:['CREATE TABLE t(a,b);',
+ "INSERT INTO t(a,b) VALUES(1,2),(3,4),",
+ "(?,?),('blob',X'6869');"
+ ],
multi: true,
saveSql: list,
bind: [5,6]
+ /* Achtung: ^^^ bind support might be removed from multi-mode exec. */
});
T.assert(2 === list.length);
//log("Exec'd SQL:", list);
columnNames: colNames,
callback: function(row,stmt){
++counter;
- T.assert(row.a%2 && row.a<6);
+ T.assert((row.a%2 && row.a<6) || 'blob'===row.a);
}
});
T.assert(2 === colNames.length)
.assert('a' === colNames[0])
- .assert(3 === counter)
- .assert(3 === list.length);
+ .assert(4 === counter)
+ .assert(4 === list.length);
list.length = 0;
db.exec("SELECT a a, b b FROM t",{
rowMode: 'array',
callback: function(row,stmt){
++counter;
T.assert(Array.isArray(row))
- .assert(0===row[1]%2 && row[1]<7);
+ .assert((0===row[1]%2 && row[1]<7)
+ || (row[1] instanceof Uint8Array));
}
});
- T.assert(6 === counter);
+ T.assert(8 === counter);
};
const testUDF = function(db){
db.createFunction("foo",function(a,b){return a+b});
T.assert(7===db.selectValue("select foo(3,4)")).
assert(5===db.selectValue("select foo(3,?)",2)).
- assert(5===db.selectValue("select foo(?,?)",[1,4])).
+ assert(5===db.selectValue("select foo(?,?2)",[1,4])).
assert(5===db.selectValue("select foo($a,$b)",{$a:0,$b:5}));
db.createFunction("bar", {
arity: -1,
for(let i = 0; i < arguments.length; ++i) rc += arguments[i];
return rc;
}
+ }).createFunction({
+ name: "asis",
+ callback: function(arg){
+ return arg;
+ }
});
log("Testing DB::selectValue() w/ UDF...");
T.assert(0===db.selectValue("select bar()")).
assert(1===db.selectValue("select bar(1)")).
assert(3===db.selectValue("select bar(1,2)")).
- assert(-1===db.selectValue("select bar(1,2,-4)"));
+ assert(-1===db.selectValue("select bar(1,2,-4)")).
+ assert('hi'===db.selectValue("select asis('hi')"));
+ let blob = db.selectValue("select asis(X'6869')");
+ T.assert(blob instanceof Uint8Array).
+ assert(2 === blob.length).
+ assert(0x68==blob[0] && 0x69==blob[1]);
const eqApprox = function(v1,v2,factor=0.05){
+ //log('eqApprox',v1, v2);
return v1>=(v2-factor) && v1<=(v2+factor);
};
assert(null === db.selectValue("select ?",null)).
assert(null === db.selectValue("select ?",[null])).
assert(null === db.selectValue("select $a",{$a:null})).
- assert(eqApprox(3.1,db.selectValue("select 3.0 + 0.1")))
+ assert(eqApprox(3.1,db.selectValue("select 3.0 + 0.1"))).
+ assert(eqApprox(1.3,db.selectValue("select asis(1 + 0.3)")))
;
};
-C Minor\swasm\sdoc\stweaks.
-D 2022-06-25T02:54:20.783
+C wasm:\scorrected\sthe\spropagation\sof\stext/blob\svalues\svia\sUDFs.\sDB.exec()'s\ssql\smay\snow\sbe\san\sarray\sof\sstrings\swhich\sget\sconcatenated\stogether\sbefore\spassing\sit\son\sto\ssqlite3_prepare_v2().\sDB.exec()'s\scallback\snow\sapplies\sto\sthe\sfirst\sstatement\swhich\shas\sresult\scolumns\sinstead\sof\sonly\sthe\sfirst\sstatement.\sFixed\sa\sprecedence\sbut\swhich\scaused\sisInt32()\sto\sreport\sfalse\spositives.
+D 2022-06-25T03:53:43.503
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F ext/fiddle/fiddle.html 550c5aafce40bd218de9bf26192749f69f9b10bc379423ecd2e162bcef885c08
F ext/fiddle/fiddle.js 812f9954cc7c4b191884ad171f36fcf2d0112d0a7ecfdf6087896833a0c079a8
F ext/fiddle/index.md d9c1c308d8074341bc3b11d1d39073cd77754cb3ca9aeb949f23fdd8323d81cf
-F ext/fiddle/sqlite3-api.js c54f0ee6a65a59284e6b0184f556376b35f5996b6b82607d7275a95f759a380a
+F ext/fiddle/sqlite3-api.js b706be1f777a4508f9e3e237301e11c108933ae651b3fa599bf047cac34b5bdb
F ext/fiddle/sqlite3-worker.js a9c2b614beca187dbdd8c053ec2770cc61ec1ac9c0ec6398ceb49a79f705a421
F ext/fiddle/testing.css 750572dded671d2cf142bbcb27af5542522ac08db128245d0b9fe410aa1d7f2a
F ext/fiddle/testing1.html ea1f3be727f78e420007f823912c1a03b337ecbb8e79449abc2244ad4fe15d9a
-F ext/fiddle/testing1.js 2ba8d14b335cdfc694757c25a3ffcfa76f4696bb21187db5c12ea6e505c44af0
+F ext/fiddle/testing1.js 3e5f1fb22764ec735396db518b85ea6b3070f6c2da479cba69c8d8e89f8299f8
F ext/fiddle/testing2.html 9063b2430ade2fe9da4e711addd1b51a2741cf0c7ebf6926472a5e5dd63c0bc4
F ext/fiddle/testing2.js 7b45b4e7fddbd51dbaf89b6722c02758051b34bac5a98c11b569a7e7572f88ee
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P ab3e50dab4d71557ab5d179bbd6caf7fb61ab7c51dffc8e4714441c189ce3e5c
-R bbdb5fff926c789b277af363fc1aa00d
+P 42dc500819bfc1308a9542aa2cae4f6dfd98a29237c59cec82e0e6f9e0bf3779
+R a152bf70e7d16ac14f437dceeb13aaae
U stephan
-Z 54385a773b385e5557f29a3390198b0f
+Z 385f37f8ee9972f16da6e6bace96df52
# Remove this line to create a well-formed Fossil manifest.
-42dc500819bfc1308a9542aa2cae4f6dfd98a29237c59cec82e0e6f9e0bf3779
\ No newline at end of file
+37a8fecb56793fbd3763a2240a0bd62b639c811934d3af2ef0e5ff579073d632
\ No newline at end of file