Compare commits

...

1 Commits

Author SHA1 Message Date
drh 00c5fef154 A failed attempt to add a new sqlite3_result_zeroterminated() interface that
is a hint to SQLite that a TEXT result does have a zero terminator.  The idea
is to avoid unnecessary copying of TEXT values. This seems like an
unnecessary complication at the moment, but maybe I'll return to this later.
Note that this check-in does not work - it is a proof of concept only.

FossilOrigin-Name: a0de01108c4b462f8e79bc58fbfe40dec562bbec682679fd0479c79a3c415578
2023-07-28 12:59:10 +00:00
9 changed files with 102 additions and 21 deletions
+17 -13
View File
@@ -1,5 +1,5 @@
C Fix\sa\scouple\sof\scompiler\swarnings\sin\sfts5_index.c.
D 2023-07-27T20:08:44.624
C A\sfailed\sattempt\sto\sadd\sa\snew\ssqlite3_result_zeroterminated()\sinterface\sthat\nis\sa\shint\sto\sSQLite\sthat\sa\sTEXT\sresult\sdoes\shave\sa\szero\sterminator.\s\sThe\sidea\nis\sto\savoid\sunnecessary\scopying\sof\sTEXT\svalues.\sThis\sseems\slike\san\nunnecessary\scomplication\sat\sthe\smoment,\sbut\smaybe\sI'll\sreturn\sto\sthis\slater.\nNote\sthat\sthis\scheck-in\sdoes\snot\swork\s-\sit\sis\sa\sproof\sof\sconcept\sonly.
D 2023-07-28T12:59:10.672
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -596,16 +596,16 @@ F src/delete.c cd5f5cd06ed0b6a882ec1a8c2a0d73b3cecb28479ad19e9931c4706c5e2182be
F src/expr.c ef4a81822da6f767696bd7f4b9983328af061158958138540142285a5b1181b7
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c a7fcbf7e66d14dbb73cf49f31489ebf66d0e6006c62b95246924a3bae9f37b36
F src/func.c cc1da67fd643a43cfe691784158ec656d8ec6d13bb17e67018b01b38b3e4f5ab
F src/func.c c1511ca3ab74a02a6b04bab0e7c6ff2ebf49ca3a5a1ed892f1fa231cb6fc1a03
F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d
F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276
F src/json.c c992d2a87a6888bf16a5c7270ef523eb838cf49e6643420c3cf917124f41f97f
F src/json.c b3d1811118a140febeda3b6be96abbb4e8545c3d6d8f26ba8ca2dfb6a8a8edde
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465
F src/loadext.c e389600cd7e6581b486a00fcc4cbff833a9ad186d9ab1aca3bb5974a38e37e8c
F src/main.c 512b1d45bc556edf4471a845afb7ba79e64bd5b832ab222dc195c469534cd002
F src/malloc.c 47b82c5daad557d9b963e3873e99c22570fb470719082c6658bf64e3012f7d23
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
@@ -639,15 +639,15 @@ F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
F src/pragma.c 37b8fb02d090262280c86e1e2654bf59d8dbfbfe8dc6733f2b968a11374c095a
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c d6c4354f8ea0dc06962fbabc4b68c4471a45276a2918c929be00f9f537f69eb1
F src/printf.c e3ba080e2f409f9bfcc8d34724e6fc160e9c718dc92d0548f6b71b8b6f860ce2
F src/printf.c be332893e1daebbc0638aa16cfb2a7daf7613e8ae7b72352e01afbda6a4b5ad3
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 37953a5f36c60bea413c3c04efcd433b6177009f508ef2ace0494728912fe2e9
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
F src/select.c 3ab1186290a311a8ceed1286c0e286209f7fe97b2d02c7593258004ce295dd88
F src/shell.c.in 62b58d7be1e44ec3eb729411278b079c39949e683853445323fd3f250b674a29
F src/sqlite.h.in f999ef3642f381d69679b2516b430dbcb6c5a2a951b7f5e43dc4751b474a5774
F src/sqlite.h.in f6891cc5e6ffaa4a16ff46c2b5fed53653034e58d9eecca972efc5f913d8c183
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h da473ce2b3d0ae407a6300c4a164589b9a6bfdbec9462688a8593ff16f3bb6e4
F src/sqlite3ext.h a2d57a373740a2a19052a85da26e0cbfb8d58eadcd65b7af3be8ed66f1201031
F src/sqliteInt.h 30d7b0d586a4d03a384dcb60088c81b6fc6f74ce85cc3a0b3242eedc3cc24dbd
F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
@@ -716,7 +716,7 @@ F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
F src/vdbe.c 4cda877d413a18fa07346b08d6959b3d18ce982357921e7acb9649fca2534a12
F src/vdbe.h 41485521f68e9437fdb7ec4a90f9d86ab294e9bb8281e33b235915e29122cfc0
F src/vdbeInt.h 401813862f9d75af01bdb2ab99253ad019e9d6ddcc8058e4fa61a43e9a60d1f7
F src/vdbeapi.c dde6c4d0f87486f056b9db4d1ea185bb1d84a6839102b86e76316ba590d07cc7
F src/vdbeapi.c 5bf0376376e7b7f284d81436b471ef76f0b210ce64a5988d875c3b502db888df
F src/vdbeaux.c b5e3f7e158518b4eca6f166ac43900640a3fe9735c710e12bfa119af21059339
F src/vdbeblob.c 2516697b3ee8154eb8915f29466fb5d4f1ae39ee8b755ea909cefaf57ec5e2ce
F src/vdbemem.c 33da4f30ddba2670bc1e617c3262b66aef2a8039043d4ff93e5c97974991089d
@@ -2049,8 +2049,12 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d66b182d2bc6ce0772e69401b7affe1adbc1b128c4631cb3c17f98dde72af00a
R 67e5566856c21efabeaa9f30d61da2e8
U dan
Z 82b2d14bd5c4ac2218712be1054b30ff
P bf71faa2a1d29ea762c4d2485522d6f4f8a5a7166981a92d3ba9c96ccbbe1213
R eb8bcba9b38858125330a6f1f21381a9
T *branch * sqlite3_result_zeroterminated
T *sym-sqlite3_result_zeroterminated *
T +closed *
T -sym-trunk *
U drh
Z 3eed865c1f50875c4bb3e8a707d0d1f4
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
bf71faa2a1d29ea762c4d2485522d6f4f8a5a7166981a92d3ba9c96ccbbe1213
a0de01108c4b462f8e79bc58fbfe40dec562bbec682679fd0479c79a3c415578
+9
View File
@@ -329,6 +329,7 @@ static void printfFunc(
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
SQLITE_DYNAMIC);
sqlite3_result_zeroterminated(context);
}
}
@@ -516,7 +517,9 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
for(i=0; i<n; i++){
z1[i] = (char)sqlite3Toupper(z2[i]);
}
z1[i] = 0;
sqlite3_result_text(context, z1, n, sqlite3_free);
sqlite3_result_zeroterminated(context);
}
}
}
@@ -535,7 +538,9 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
for(i=0; i<n; i++){
z1[i] = sqlite3Tolower(z2[i]);
}
z1[i] = 0;
sqlite3_result_text(context, z1, n, sqlite3_free);
sqlite3_result_zeroterminated(context);
}
}
}
@@ -1168,6 +1173,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
sqlite3QuoteValue(&str,argv[0]);
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), str.nChar,
SQLITE_DYNAMIC);
sqlite3_result_zeroterminated(context);
if( str.accError!=SQLITE_OK ){
sqlite3_result_null(context);
sqlite3_result_error_code(context, str.accError);
@@ -1229,6 +1235,7 @@ static void charFunc(
}
*zOut = 0;
sqlite3_result_text64(context, (char*)z, zOut-z, sqlite3_free, SQLITE_UTF8);
sqlite3_result_zeroterminated(context);
}
/*
@@ -1257,6 +1264,7 @@ static void hexFunc(
}
*z = 0;
sqlite3_result_text(context, zHex, n*2, sqlite3_free);
sqlite3_result_zeroterminated(context);
}
}
@@ -1463,6 +1471,7 @@ static void replaceFunc(
assert( j<=nOut );
zOut[j] = 0;
sqlite3_result_text(context, (char*)zOut, j, sqlite3_free);
sqlite3_result_zeroterminated(context);
}
/*
+12 -6
View File
@@ -572,6 +572,7 @@ static void jsonResult(JsonString *p){
sqlite3_result_text64(p->pCtx, p->zBuf, p->nUsed,
(void(*)(void*))sqlite3RCStrUnref,
SQLITE_UTF8);
sqlite3_result_zeroterminated(p->pCtx);
}
}
if( p->bErr==1 ){
@@ -993,6 +994,7 @@ static void jsonReturn(
} /* end for() */
zOut[j] = 0;
sqlite3_result_text(pCtx, zOut, j, sqlite3_free);
sqlite3_result_zeroterminated(pCtx);
}
break;
}
@@ -3086,17 +3088,19 @@ static void jsonArrayCompute(sqlite3_context *ctx, int isFinal){
if( pStr ){
pStr->pCtx = ctx;
jsonAppendChar(pStr, ']');
jsonAppendChar(pStr, 0);
if( pStr->bErr ){
if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
assert( pStr->bStatic );
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed-1,
pStr->bStatic ? SQLITE_TRANSIENT :
(void(*)(void*))sqlite3RCStrUnref);
sqlite3_result_zeroterminated(ctx);
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
pStr->nUsed--;
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed-1,SQLITE_TRANSIENT);
pStr->nUsed -= 2;
}
}else{
sqlite3_result_text(ctx, "[]", 2, SQLITE_STATIC);
@@ -3195,17 +3199,19 @@ static void jsonObjectCompute(sqlite3_context *ctx, int isFinal){
pStr = (JsonString*)sqlite3_aggregate_context(ctx, 0);
if( pStr ){
jsonAppendChar(pStr, '}');
jsonAppendChar(pStr, 0);
if( pStr->bErr ){
if( pStr->bErr==1 ) sqlite3_result_error_nomem(ctx);
assert( pStr->bStatic );
}else if( isFinal ){
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed,
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed-1,
pStr->bStatic ? SQLITE_TRANSIENT :
(void(*)(void*))sqlite3RCStrUnref);
sqlite3_result_zeroterminated(ctx);
pStr->bStatic = 1;
}else{
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed, SQLITE_TRANSIENT);
pStr->nUsed--;
sqlite3_result_text(ctx, pStr->zBuf, (int)pStr->nUsed-1,SQLITE_TRANSIENT);
pStr->nUsed -= 2;
}
}else{
sqlite3_result_text(ctx, "{}", 2, SQLITE_STATIC);
+3 -1
View File
@@ -512,7 +512,9 @@ static const sqlite3_api_routines sqlite3Apis = {
/* Version 3.40.0 and later */
sqlite3_value_encoding,
/* Version 3.41.0 and later */
sqlite3_is_interrupted
sqlite3_is_interrupted,
/* Version 3.43.0 and later */
sqlite3_result_zeroterminated
};
/* True if x is the directory separator character
+2
View File
@@ -1076,7 +1076,9 @@ void sqlite3ResultStrAccum(sqlite3_context *pCtx, StrAccum *p){
sqlite3_result_error_code(pCtx, p->accError);
sqlite3_str_reset(p);
}else if( isMalloced(p) ){
p->zText[p->nChar] = 0;
sqlite3_result_text(pCtx, p->zText, p->nChar, SQLITE_DYNAMIC);
sqlite3_result_zeroterminated(pCtx);
}else{
sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
sqlite3_str_reset(p);
+49
View File
@@ -6102,6 +6102,55 @@ int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
*/
void sqlite3_result_subtype(sqlite3_context*,unsigned int);
/*
** CAPI3REF: Indicate That A Text Result Is Zero-Terminated
** METHOD: sqlite3_context
**
** There are five interfaces that can be used by an
** [application-defined SQL function] or [virtual table] to indicate that
** a result value returned to SQLite is TEXT. Specifically:
**
** <ul>
** <li> [sqlite3_result_text(C,P,N,D)]
** <li> [sqlite3_result_text64(C,P,N,D,E)]
** <li> [sqlite3_result_text16(C,P,N,D)]
** <li> [sqlite3_result_text16le(C,P,N,D)]
** <li> [sqlite3_result_text16be(C,P,N,D)]
** </ul>
**
** In all cases, the N parameter is the size of the TEXT value in bytes.
**
** The sqlite3_result_zeroterminated(C) indicates to SQLite that the TEXT
** value passed in the previous call to one or the sqlite3_result_text()
** interfaces contains one additional zero character (either a single 0x00
** bytes for UTF-8 or two 0x00 bytes for UTF-16) following the N bytes
** specified. Knowing this can sometimes help SQLite avoid having to
** make copies of the TEXT value.
**
** This interface is an optimization. Application-defined functions and
** virtual tables can use this interface to help SQLite run faster by
** avoiding unnecessary copying of TEXT values. But the same result should
** be obtained regardless of whether or not this function is used.
**
** If the N argument to the prior sqlite3_result_text() method is negative,
** then it is pointless (though harmless) to call sqlite3_result_zeroterminated()
** because in that case SQLite already knows that the TEXT result is
** zero terminated. (NB: Negative N values are not allowed for
** sqlite3_result_text64().) Likewise, if the D argument to the prior
** sqlite3_result_text() method is SQLITE_TRANSIENT, then SQLite has already
** made a copy of the TEXT value and inserted its own zero terminator in
** that copy, so a call to sqlite3_result_zeroterminated() is pointless.
**
** It is a harmless no-op to invoke the sqlite3_result_zeroterminated(C)
** method if the result of the SQL function or virtual table is something
** other than TEXT.
**
** Note that sqlite3_result_zeroterminated() must be call after the call
** the sqlite3_result_text() method. If sqlite3_result_zeroterminated()
** is called before the sqlite3_result_text() method, it will have no effect.
*/
void sqlite3_result_zeroterminated(sqlite3_context*);
/*
** CAPI3REF: Define New Collating Sequences
** METHOD: sqlite3
+4
View File
@@ -361,6 +361,8 @@ struct sqlite3_api_routines {
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
/* Version 3.43.0 and later */
void (*result_zeroterminated)(sqlite3_context*);
};
/*
@@ -689,6 +691,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
/* Version 3.43.0 and later */
#define sqlite3_result_zeroterminated sqlite3_api->result_zeroterminated
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
+5
View File
@@ -546,6 +546,11 @@ void sqlite3_result_text16le(
setResultStrOrError(pCtx, z, n & ~(u64)1, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
void sqlite3_result_zeroterminated(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
assert( (pCtx->pOut->flags & MEM_Str)==0 || pCtx->pOut->z[pCtx->pOut->n]==0 );
pCtx->pOut->flags |= MEM_Term;
}
void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
Mem *pOut = pCtx->pOut;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );