From: drh <> Date: Mon, 26 Jan 2026 13:44:42 +0000 (+0000) Subject: Add alternative sqlite3_carray_bind_v2() interface. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=49bf78685efba527a612ba2e80012a6ad81ebb16;p=thirdparty%2Fsqlite.git Add alternative sqlite3_carray_bind_v2() interface. FossilOrigin-Name: 925384d7711867428644595c0903682e6e365eb974c57e6680b51d511c980054 --- diff --git a/manifest b/manifest index 12036b0482..bcb5a02793 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sspeedtest1.wasm\sbuild\sregression\sintroduced\swith\sEmscripten\s5.0.0. -D 2026-01-26T10:53:24.426 +C Add\salternative\ssqlite3_carray_bind_v2()\sinterface. +D 2026-01-26T13:44:42.812 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -683,7 +683,7 @@ F src/btree.h e823c46d87f63d904d735a24b76146d19f51f04445ea561f71cc3382fd1307f0 F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886 F src/build.c 4e1afafc56504ed6253e1b115c1502de4243c2287a0c799f4967fcd2d7716ad9 F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad -F src/carray.c ff6081a31878fc34df8fa1052a9cbf17ddc22652544dcb3e2326886ed1053b55 +F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/date.c e19e0cfff9a41bfdd884c655755f6f00bca4c1a22272b56e0dd6667b7ea893a2 F src/dbpage.c c9ea81c11727f27e02874611e92773e68e2a90a875ef2404b084564c235fd91f @@ -740,16 +740,16 @@ F src/resolve.c 47aa7fdc9ec4c19b103ac5e79d7887d30119b5675309facf5eed1118391c868b F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c 65d7ffa2af9670b5e9ca2b23a98a92cd4a32c12b098edeff80e6df61da9b9a6e F src/shell.c.in e8818572acd50464bc00426fe0d755e98239f73d531437c3dc7721d1fecb1231 -F src/sqlite.h.in 69eccc01b4c0ff8e8c830e1961971290f1b94d46dc59cfd40f82d26cb9331eb0 +F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61 F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 -F src/sqlite3ext.h f590cd8cb4c36fc727632c9b5fbbafc85f7efe2c6890f9958d7e711dc26ec01e +F src/sqlite3ext.h 1b7a0ee438bb5c2896d0609c537e917d8057b3340f6ad004d2de44f03e3d3cca F src/sqliteInt.h f4b50f8c287b858bb23dd51daee29ff424697be9a0753cf37df98fbe1806125b F src/sqliteLimit.h 904a3f520362c7065c18165aaabd504fb13cc1b76cb411f38bd41ac219e4af1e F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/tclsqlite.c 85b5a20df96016e5d1d8fdc68c8a4c279c5b93e2049b77cd806c2cc50b9d8c56 F src/tclsqlite.h 614b3780a62522bc9f8f2b9fb22689e8009958e7aa77e572d0f3149050af348a -F src/test1.c 2986148389a86555db7e6b731767154f165a2c7bc690131f90596fa6263fe79d +F src/test1.c 302cc00a5f0bbfa36d73b299d600c073b02ffa7f2b59fd2c81091983ccd574a8 F src/test2.c 62f0830958f9075692c29c6de51b495ae8969e1bef85f239ffcd9ba5fb44a5ff F src/test3.c 432646f581d8af1bb495e58fc98234380250954f5d5535e507fc785eccc3987a F src/test4.c 0ac87fc13cdb334ab3a71823f99b6c32a6bebe5d603cd6a71d84c823d43a25a0 @@ -955,7 +955,7 @@ F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4 F test/capi3c.test 31d3a6778f2d06f2d9222bd7660c41a516d1518a059b069e96ebbeadb5a490f7 F test/capi3d.test 8b778794af891b0dca3d900bd345fbc8ebd2aa2aae425a9dccdd10d5233dfbde F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe -F test/carray01.test 49e2aedfdf2c715bc002d2773cdc1217166679639542c79c8aa4115f06421407 +F test/carray01.test 17c1cf8287862b15dda949dba626fd5fee5c58471dcc1cae0341471c2ae7da01 F test/carray02.test 9d070b54f24a34d1f3b3c552ba34db0375a9d1c4219067416fb07d1595987c9d F test/carrayfault.test 108a7d83904fc267c448e27c13b2a857c700bd6ddaa2f1e2518be718b159cb6b F test/cast.test a2a3b32df86e3c0601ffa2e9f028a18796305d251801efea807092dbf374a040 @@ -2193,8 +2193,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P c38797d400dc4135108a6e303f2c10779ba9adf0daae28f1789f9106a68d21d5 -R 548ba2dbbfa7fb559bd775cbf8869e64 -U stephan -Z f43acac73851a6860774192e86d8201c +P 4733d351ec2376291f093ba8d2ba71d82c6f100c68dc860eee0532986c154e71 +R 6915ffc4b5955ec1130e76c663a36e6f +U drh +Z f6d7b74ce0e68fae0513da37a10a7a67 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index fb4f2f0930..d41034337c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4733d351ec2376291f093ba8d2ba71d82c6f100c68dc860eee0532986c154e71 +925384d7711867428644595c0903682e6e365eb974c57e6680b51d511c980054 diff --git a/src/carray.c b/src/carray.c index 154d107ddf..ff0691a851 100644 --- a/src/carray.c +++ b/src/carray.c @@ -79,6 +79,7 @@ struct carray_bind { int nData; /* Number of elements */ int mFlags; /* Control flags */ void (*xDel)(void*); /* Destructor for aData */ + void *pDel; /* Alternative argument to xDel() */ }; @@ -411,7 +412,7 @@ static sqlite3_module carrayModule = { static void carrayBindDel(void *pPtr){ carray_bind *p = (carray_bind*)pPtr; if( p->xDel!=SQLITE_STATIC ){ - p->xDel(p->aData); + p->xDel(p->pDel); } sqlite3_free(p); } @@ -419,14 +420,26 @@ static void carrayBindDel(void *pPtr){ /* ** Invoke this interface in order to bind to the single-argument ** version of CARRAY(). +** +** pStmt The prepared statement to which to bind +** idx The index of the parameter of pStmt to which to bind +** aData The data to be bound +** nData The number of elements in aData +** mFlags One of SQLITE_CARRAY_xxxx indicating datatype of aData +** xDestroy Destructor for pDestroy or aData if pDestroy==NULL. +** pDestroy Invoke xDestroy on this pointer if not NULL +** +** The destructor is called pDestroy if pDestroy!=NULL, or against +** aData if pDestroy==NULL. */ -SQLITE_API int sqlite3_carray_bind( +SQLITE_API int sqlite3_carray_bind_v2( sqlite3_stmt *pStmt, int idx, void *aData, int nData, int mFlags, - void (*xDestroy)(void*) + void (*xDestroy)(void*), + void *pDestroy ){ carray_bind *pNew = 0; int i; @@ -503,20 +516,38 @@ SQLITE_API int sqlite3_carray_bind( memcpy(pNew->aData, aData, sz); } pNew->xDel = sqlite3_free; + pNew->pDel = pNew->aData; }else{ pNew->aData = aData; pNew->xDel = xDestroy; + pNew->pDel = pDestroy; } return sqlite3_bind_pointer(pStmt, idx, pNew, "carray-bind", carrayBindDel); carray_bind_error: if( xDestroy!=SQLITE_STATIC && xDestroy!=SQLITE_TRANSIENT ){ - xDestroy(aData); + xDestroy(pDestroy); } sqlite3_free(pNew); return rc; } +/* +** Invoke this interface in order to bind to the single-argument +** version of CARRAY(). Same as sqlite3_carray_bind_v2() with the +** pDestroy parameter set to NULL. +*/ +SQLITE_API int sqlite3_carray_bind( + sqlite3_stmt *pStmt, + int idx, + void *aData, + int nData, + int mFlags, + void (*xDestroy)(void*) +){ + return sqlite3_carray_bind_v2(pStmt,idx,aData,nData,mFlags,xDestroy,aData); +} + /* ** Invoke this routine to register the carray() function. */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 67e03ef387..e1f478a0a9 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -11252,19 +11252,41 @@ int sqlite3_deserialize( /* ** CAPI3REF: Bind array values to the CARRAY table-valued function ** -** The sqlite3_carray_bind(S,I,P,N,F,X) interface binds an array value to -** one of the first argument of the [carray() table-valued function]. The -** S parameter is a pointer to the [prepared statement] that uses the carray() -** functions. I is the parameter index to be bound. P is a pointer to the -** array to be bound, and N is the number of eements in the array. The -** F argument is one of constants [SQLITE_CARRAY_INT32], [SQLITE_CARRAY_INT64], -** [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], or [SQLITE_CARRAY_BLOB] to -** indicate the datatype of the array being bound. The X argument is not a -** NULL pointer, then SQLite will invoke the function X on the P parameter -** after it has finished using P, even if the call to -** sqlite3_carray_bind() fails. The special-case finalizer -** SQLITE_TRANSIENT has no effect here. -*/ +** The sqlite3_carray_bind_v2(S,I,P,N,F,X,D) interface binds an array value to +** parameter that is the first argument of the [carray() table-valued function]. +** The S parameter is a pointer to the [prepared statement] that uses the carray() +** functions. I is the parameter index to be bound. I must be the index of the +** parameter that is the first argument to the carray() table-valued function. +** P is a pointer to the array to be bound, and N is the number of elements in +** the array. The F argument is one of constants [SQLITE_CARRAY_INT32], +** [SQLITE_CARRAY_INT64], [SQLITE_CARRAY_DOUBLE], [SQLITE_CARRAY_TEXT], +** or [SQLITE_CARRAY_BLOB] to indicate the datatype of the array P. +** +** If the X argument is not a NULL pointer or one of the special +** values [SQLITE_STATIC] or [SQLITE_TRANSIENT], then SQLite will invoke +** the function X with argument D when it is finished using the data in P. +** The call to X(D) is a destructor for the array P. The destructor X(D) +** is invoked even if the call to sqlite3_carray_bind() fails. If the X +** parameter is the special-case value [SQLITE_STATIC], then SQLite assumes +** that the data static and the destructor is never invoked. If the X +** parameter is the special-case value [SQLITE_TRANSIENT], then +** sqlite3_carray_bind_v2() makes its own private copy of the data prior +** to returning and never invokes the destructor X. +** +** The sqlite3_carray_bind() function works the same as sqlite_carray_bind_v2() +** with a D parameter set to P. In other words, +** sqlite3_carray_bind(S,I,P,N,F,X) is same as +** sqlite3_carray_bind(S,I,P,N,F,X,P). +*/ +int sqlite3_carray_bind_v2( + sqlite3_stmt *pStmt, /* Statement to be bound */ + int i, /* Parameter index */ + void *aData, /* Pointer to array data */ + int nData, /* Number of data elements */ + int mFlags, /* CARRAY flags */ + void (*xDel)(void*), /* Destructor for aData */ + void *pDel /* Optional argument to xDel() */ +); int sqlite3_carray_bind( sqlite3_stmt *pStmt, /* Statement to be bound */ int i, /* Parameter index */ diff --git a/src/sqlite3ext.h b/src/sqlite3ext.h index 36c35b7b10..cad1a2a001 100644 --- a/src/sqlite3ext.h +++ b/src/sqlite3ext.h @@ -375,6 +375,7 @@ struct sqlite3_api_routines { void (*str_truncate)(sqlite3_str*,int); void (*str_free)(sqlite3_str*); int (*carray_bind)(sqlite3_stmt*,int,void*,int,int,void(*)(void*)); + int (*carray_bind_v2)(sqlite3_stmt*,int,void*,int,int,void(*)(void*),void*); }; /* @@ -717,6 +718,7 @@ typedef int (*sqlite3_loadext_entry)( #define sqlite3_str_truncate sqlite3_api->str_truncate #define sqlite3_str_free sqlite3_api->str_free #define sqlite3_carray_bind sqlite3_api->carray_bind +#define sqlite3_carray_bind_v2 sqlite3_api->carray_bind_v2 #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) diff --git a/src/test1.c b/src/test1.c index 6f2e2e94ed..230034fa01 100644 --- a/src/test1.c +++ b/src/test1.c @@ -4411,7 +4411,7 @@ static void delIntptr(void *p){ } /* -** bind_carray_intptr STMT IPARAM INT0 INT1 INT2... +** bind_carray_intptr STMT IPARAM INT-0 INT-1 INT-2... */ static int SQLITE_TCLAPI bind_carray_intptr( void * clientData, @@ -4455,6 +4455,7 @@ static int SQLITE_TCLAPI bind_carray_intptr( ** -malloc ** -transient ** -static +** -v2 ** -int32 ** -int64 ** -double @@ -4477,6 +4478,7 @@ static int SQLITE_TCLAPI test_carray_bind( void *aData = 0; int isTransient = 0; int isStatic = 0; + int isV2 = 0; int isMalloc = 0; /* True to use custom xDel function */ int idx; int i, j; @@ -4509,16 +4511,22 @@ static int SQLITE_TCLAPI test_carray_bind( const char *z = Tcl_GetString(objv[i]); if( strcmp(z, "-transient")==0 ){ isTransient = 1; + isStatic = isMalloc = 0; xDel = SQLITE_TRANSIENT; }else if( strcmp(z, "-static")==0 ){ isStatic = 1; + isMalloc = isTransient = 0; xDel = SQLITE_STATIC; }else if( strcmp(z, "-malloc")==0 ){ isMalloc = 1; + isStatic = isTransient = 0; xDel = testCarrayFree; }else + if( strcmp(z, "-v2")==0 ){ + isV2 = 1; + }else if( strcmp(z, "-int32")==0 ){ eType = 0; /* CARRAY_INT32 */ }else @@ -4687,7 +4695,20 @@ static int SQLITE_TCLAPI test_carray_bind( if( rc==SQLITE_OK ){ if( mFlagsOverride==0 ) mFlagsOverride = eType; - rc = sqlite3_carray_bind(pStmt, idx, aData, nData, mFlagsOverride, xDel); + if( isV2 ){ + void *pDel; + if( xDel==testCarrayFree ){ + u8 *p2 = (u8*)aData; + pDel = (void*)&p2[-16]; + xDel = sqlite3_free; + }else{ + pDel = aData; + } + rc = sqlite3_carray_bind_v2(pStmt, idx, aData, nData, mFlagsOverride, + xDel, pDel); + }else{ + rc = sqlite3_carray_bind(pStmt, idx, aData, nData, mFlagsOverride, xDel); + } } if( isTransient ){ if( eType==3 && aData ){ diff --git a/test/carray01.test b/test/carray01.test index 86ea069961..b17a481e1b 100644 --- a/test/carray01.test +++ b/test/carray01.test @@ -51,6 +51,10 @@ do_test 101 { run_stmt $STMT } {1} do_test 102 { + sqlite3_carray_bind -v2 -malloc $STMT 3 1 2 3 4 5 6 7 + run_stmt $STMT +} {1} +do_test 103 { set STMT2 [sqlite3_prepare_v2 db { SELECT DISTINCT typeof(value) FROM carray(?3)} -1] sqlite3_carray_bind $STMT2 3 1 2 3 4 5 6 7 @@ -124,6 +128,10 @@ do_test 160 { sqlite3_carray_bind -double $STMT 3 1 2 3 4 5 6 7 run_stmt $STMT } {1} +do_test 161 { + sqlite3_carray_bind -double -v2 $STMT 3 1 2 3 4 5 6 7 + run_stmt $STMT +} {1} do_test 170 { sqlite3_carray_bind -text -static $STMT 3 1 2 3 4 6 7 run_stmt $STMT