mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Per /chat and forum discussions: (A) Remove the value type output pointer from text/blob_v2(). (B) Teach blob_v2() to return an opaque non-NULL pointer for length-0 blobs.
FossilOrigin-Name: c96539beb5ca3c6a467e5388b942767765a3f071e009c1767d3b4f1b0fb5da9c
This commit is contained in:
@ -3352,20 +3352,20 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
try {
|
||||
let sv, rc;
|
||||
q = db.prepare("select a, b from t order by a");
|
||||
let [ppOut, pnOut, pType] = P.allocPtr(3);
|
||||
let [ppOut, pnOut] = P.allocPtr(2);
|
||||
const clearPtrs = ()=>{
|
||||
wasm.pokePtr(ppOut, 0).poke32(pnOut, 0).poke32(pType, 0);
|
||||
wasm.pokePtr(ppOut, 0).poke32(pnOut, 0);
|
||||
};
|
||||
const next = ()=>{
|
||||
T.assert( q.step() );
|
||||
sv = capi.sqlite3_column_value(q, 1);
|
||||
T.assert( sv );
|
||||
clearPtrs();
|
||||
rc = capi.sqlite3_value_text_v2(sv, ppOut, pnOut, pType);
|
||||
rc = capi.sqlite3_value_text_v2(sv, ppOut, pnOut);
|
||||
T.assert( 0===rc );
|
||||
return sv;
|
||||
};
|
||||
const cmp = function(type,expect){
|
||||
const cmp = function(expect){
|
||||
const blob = wasm.peekPtr(ppOut);
|
||||
const len = wasm.peek32(pnOut);
|
||||
//log("blob=",wasm.cstrToJs(blob));
|
||||
@ -3381,20 +3381,20 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
.assert( str===expect, "String mismatch: got ["
|
||||
+str+"] expected ["+expect+"]");
|
||||
};
|
||||
const cmp2 = (type,expect)=>{
|
||||
const cmp2 = (expect)=>{
|
||||
next();
|
||||
cmp(type,expect);
|
||||
cmp(expect);
|
||||
clearPtrs();
|
||||
const rc = capi.sqlite3_column_text_v2(q, 1, ppOut, pnOut, pType);
|
||||
const rc = capi.sqlite3_column_text_v2(q, 1, ppOut, pnOut);
|
||||
T.assert( 0==rc, "expecting column_text_v2() rc 0 but got "+rc );
|
||||
cmp(type,expect);
|
||||
cmp(expect);
|
||||
};
|
||||
|
||||
cmp2(capi.SQLITE_INTEGER,'123');
|
||||
cmp2(capi.SQLITE_NULL,null);
|
||||
cmp2(capi.SQLITE_TEXT,'hi world');
|
||||
cmp2(capi.SQLITE_BLOB, '#*');
|
||||
cmp2(capi.SQLITE_TEXT, ''); // empty strings are not null
|
||||
cmp2('123');
|
||||
cmp2(null);
|
||||
cmp2('hi world');
|
||||
cmp2('#*');
|
||||
cmp2(''); // empty strings are not null
|
||||
|
||||
const checkRc = (name, descr, rc)=>{
|
||||
T.assert( capi[name] === rc,
|
||||
@ -3408,25 +3408,22 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
|
||||
// This does not set a persistent error flag on q:
|
||||
checkRc('SQLITE_RANGE', "column_text_v2() bad index",
|
||||
capi.sqlite3_column_text_v2(q, 11, ppOut, pnOut, 0) );
|
||||
capi.sqlite3_column_text_v2(q, 11, ppOut, pnOut) );
|
||||
checkRc('SQLITE_OK', "column_text_v2() valid index",
|
||||
capi.sqlite3_column_text_v2(q, 1, ppOut, 0, 0));
|
||||
capi.sqlite3_column_text_v2(q, 1, ppOut, 0));
|
||||
|
||||
checkRc('SQLITE_OK', "column null pnOut",
|
||||
capi.sqlite3_column_text_v2(q, 1, ppOut, 0, 0));
|
||||
capi.sqlite3_column_text_v2(q, 1, ppOut, 0));
|
||||
|
||||
/* The MISUSE returns only apply because we build with
|
||||
SQLITE_ENABLE_API_ARMOR. Without API_ARMOR, these result in
|
||||
null pointer dereferences. */
|
||||
checkRc('SQLITE_MISUSE', "value null ppOut",
|
||||
capi.sqlite3_value_text_v2(sv, 0, pnOut, 0));
|
||||
capi.sqlite3_value_text_v2(sv, 0, pnOut));
|
||||
checkRc('SQLITE_MISUSE', "value null arg0",
|
||||
capi.sqlite3_value_text_v2(0, ppOut, pnOut, 0));
|
||||
capi.sqlite3_value_text_v2(0, ppOut, pnOut));
|
||||
checkRc('SQLITE_MISUSE', "column null ppOut",
|
||||
capi.sqlite3_column_text_v2(q, 1, 0, pnOut, 0));
|
||||
/* But a 0 pnOut is always okay. */
|
||||
checkRc('SQLITE_OK', "value null pnOut",
|
||||
capi.sqlite3_value_text_v2(sv, ppOut, 0, 0));
|
||||
capi.sqlite3_column_text_v2(q, 1, 0, pnOut));
|
||||
|
||||
}finally{
|
||||
if( q ) q.finalize();
|
||||
@ -3446,52 +3443,50 @@ globalThis.sqlite3InitModule = sqlite3InitModule;
|
||||
try {
|
||||
let sv, rc;
|
||||
q = db.prepare("select a, b from t order by a");
|
||||
let [ppOut, pnOut, pType] = P.allocPtr(3);
|
||||
let [ppOut, pnOut] = P.allocPtr(2);
|
||||
const clearPtrs = ()=>{
|
||||
wasm.pokePtr(ppOut, 0).poke32(pnOut, 0).poke32(pType, 0);
|
||||
wasm.pokePtr(ppOut, 0).poke32(pnOut, 0);
|
||||
};
|
||||
|
||||
const next = ()=>{
|
||||
++next.n;
|
||||
T.assert( q.step() );
|
||||
sv = capi.sqlite3_column_value(q, 1);
|
||||
T.assert( sv );
|
||||
clearPtrs();
|
||||
rc = capi.sqlite3_value_blob_v2(sv, ppOut, pnOut, pType);
|
||||
T.assert( !wasm.peekPtr(ppOut) );
|
||||
rc = capi.sqlite3_value_blob_v2(sv, ppOut, pnOut);
|
||||
T.assert( 0==rc, "expecting value_blob_v2() rc 0 but got "+rc );
|
||||
return sv;
|
||||
};
|
||||
const cmp = (type,byteList)=>{
|
||||
next.n = 0;
|
||||
const cmp = (byteList)=>{
|
||||
const blob = wasm.peekPtr(ppOut);
|
||||
const len = wasm.peek32(pnOut);
|
||||
//log("blob=",wasm.cstrToJs(blob));
|
||||
T.assert(len === byteList.length, "Lengths don't match")
|
||||
T.assert( len ? !!blob : !blob,
|
||||
"Expecting len=non-0/blob=non-null or len=0/blob=null. "+
|
||||
"Got len="+len+" blob=@"+blob );
|
||||
T.assert( type === wasm.peek32(pType),
|
||||
"Expecting value_blob_v2 type "+type+" but got "
|
||||
+wasm.peek32(pType)+". Value="+wasm.cstrToJs(blob));
|
||||
T.assert(len === byteList.length, "Lengths don't match: "
|
||||
+len +" != " + byteList.length)
|
||||
for( let i = 0; i < len; ++i ){
|
||||
T.assert( byteList[i] === wasm.peek8(blob+i),
|
||||
"mismatch at offset "+i+": "+byteList[i]
|
||||
+"!=="+wasm.peek8(blob+i) );
|
||||
}
|
||||
};
|
||||
const cmp2 = (type,byteList)=>{
|
||||
const cmp2 = (byteList)=>{
|
||||
next();
|
||||
cmp(type,byteList);
|
||||
cmp(byteList);
|
||||
clearPtrs();
|
||||
const rc = capi.sqlite3_column_blob_v2(q, 1, ppOut, pnOut, pType);
|
||||
const rc = capi.sqlite3_column_blob_v2(q, 1, ppOut, pnOut);
|
||||
T.assert( 0==rc, "expecting column_blob_v2() rc 0 but got "+rc);
|
||||
cmp(type,byteList);
|
||||
cmp(byteList);
|
||||
};
|
||||
|
||||
cmp2(capi.SQLITE_INTEGER, [49,50,51]); // 123
|
||||
cmp2(capi.SQLITE_NULL, []); // null
|
||||
cmp2(capi.SQLITE_TEXT, [104,105]); // "hi"
|
||||
cmp2(capi.SQLITE_BLOB, [0x23, 0, 0x2a]); // X'23002A'
|
||||
cmp2(capi.SQLITE_TEXT, []) /* length-0 non-NULL blobs are NULL
|
||||
but this one has type TEXT */;
|
||||
cmp2([49,50,51]); // 123
|
||||
cmp2([]); // null
|
||||
T.assert( !wasm.peekPtr(ppOut), "Expecting NULL in row "+next.n);
|
||||
cmp2([104,105]); // "hi"
|
||||
cmp2([0x23, 0, 0x2a]); // X'23002A'
|
||||
cmp2([]) /* length-0 blob */;
|
||||
T.assert( wasm.peekPtr(ppOut), "Expecting non-NULL in row "+next.n);
|
||||
|
||||
/** Tests which cover the same code paths for both text_v2 and
|
||||
blob_v2 are in the previous test group. */
|
||||
|
Reference in New Issue
Block a user