Extend the carray extension to allow the use of BLOB values to be bound
as an array of "struct iovec" objects. FossilOrigin-Name: e117a03ca6560e958884f277db827c51ae337a970c17143a0a5f9b150f52f87a
This commit is contained in:
parent
42d652c047
commit
a96cd076fe
@ -28,7 +28,7 @@
|
||||
**
|
||||
** There is an optional third parameter to determine the datatype of
|
||||
** the C-language array. Allowed values of the third parameter are
|
||||
** 'int32', 'int64', 'double', 'char*'. Example:
|
||||
** 'int32', 'int64', 'double', 'char*', 'struct iovec'. Example:
|
||||
**
|
||||
** SELECT * FROM carray($ptr,10,'char*');
|
||||
**
|
||||
@ -56,6 +56,14 @@
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
#else
|
||||
# include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
/* Allowed values for the mFlags parameter to sqlite3_carray_bind().
|
||||
** Must exactly match the definitions in carray.h.
|
||||
@ -65,6 +73,7 @@ SQLITE_EXTENSION_INIT1
|
||||
# define CARRAY_INT64 1 /* Data is 64-bit signed integers */
|
||||
# define CARRAY_DOUBLE 2 /* Data is doubles */
|
||||
# define CARRAY_TEXT 3 /* Data is char* */
|
||||
# define CARRAY_BLOB 4 /* Data is struct iovec* */
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_API
|
||||
@ -80,7 +89,8 @@ SQLITE_EXTENSION_INIT1
|
||||
/*
|
||||
** Names of allowed datatypes
|
||||
*/
|
||||
static const char *azType[] = { "int32", "int64", "double", "char*" };
|
||||
static const char *azType[] = { "int32", "int64", "double", "char*",
|
||||
"struct iovec" };
|
||||
|
||||
/*
|
||||
** Structure used to hold the sqlite3_carray_bind() information
|
||||
@ -224,6 +234,12 @@ static int carrayColumn(
|
||||
sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
case CARRAY_BLOB: {
|
||||
const struct iovec *p = (struct iovec*)pCur->pPtr;
|
||||
sqlite3_result_blob(ctx, p[pCur->iRowid-1].iov_base,
|
||||
(int)p[pCur->iRowid-1].iov_len, SQLITE_TRANSIENT);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,7 +284,7 @@ static int carrayFilter(
|
||||
if( pBind==0 ) break;
|
||||
pCur->pPtr = pBind->aData;
|
||||
pCur->iCnt = pBind->nData;
|
||||
pCur->eType = pBind->mFlags & 0x03;
|
||||
pCur->eType = pBind->mFlags & 0x07;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
@ -431,24 +447,29 @@ SQLITE_API int sqlite3_carray_bind(
|
||||
pNew->mFlags = mFlags;
|
||||
if( xDestroy==SQLITE_TRANSIENT ){
|
||||
sqlite3_int64 sz = nData;
|
||||
switch( mFlags & 0x03 ){
|
||||
case CARRAY_INT32: sz *= 4; break;
|
||||
case CARRAY_INT64: sz *= 8; break;
|
||||
case CARRAY_DOUBLE: sz *= 8; break;
|
||||
case CARRAY_TEXT: sz *= sizeof(char*); break;
|
||||
switch( mFlags & 0x07 ){
|
||||
case CARRAY_INT32: sz *= 4; break;
|
||||
case CARRAY_INT64: sz *= 8; break;
|
||||
case CARRAY_DOUBLE: sz *= 8; break;
|
||||
case CARRAY_TEXT: sz *= sizeof(char*); break;
|
||||
case CARRAY_BLOB: sz *= sizeof(struct iovec); break;
|
||||
}
|
||||
if( (mFlags & 0x03)==CARRAY_TEXT ){
|
||||
if( (mFlags & 0x07)==CARRAY_TEXT ){
|
||||
for(i=0; i<nData; i++){
|
||||
const char *z = ((char**)aData)[i];
|
||||
if( z ) sz += strlen(z) + 1;
|
||||
}
|
||||
}else if( (mFlags & 0x07)==CARRAY_BLOB ){
|
||||
for(i=0; i<nData; i++){
|
||||
sz += ((struct iovec*)aData)[i].iov_len;
|
||||
}
|
||||
}
|
||||
pNew->aData = sqlite3_malloc64( sz );
|
||||
if( pNew->aData==0 ){
|
||||
sqlite3_free(pNew);
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
if( (mFlags & 0x03)==CARRAY_TEXT ){
|
||||
if( (mFlags & 0x07)==CARRAY_TEXT ){
|
||||
char **az = (char**)pNew->aData;
|
||||
char *z = (char*)&az[nData];
|
||||
for(i=0; i<nData; i++){
|
||||
@ -463,6 +484,16 @@ SQLITE_API int sqlite3_carray_bind(
|
||||
memcpy(z, zData, n+1);
|
||||
z += n+1;
|
||||
}
|
||||
}else if( (mFlags & 0x07)==CARRAY_BLOB ){
|
||||
struct iovec *p = (struct iovec*)pNew->aData;
|
||||
unsigned char *z = (unsigned char*)&p[nData];
|
||||
for(i=0; i<nData; i++){
|
||||
size_t n = ((struct iovec*)aData)[i].iov_len;
|
||||
p[i].iov_len = n;
|
||||
p[i].iov_base = z;
|
||||
z += n;
|
||||
memcpy(p[i].iov_base, ((struct iovec*)aData)[i].iov_base, n);
|
||||
}
|
||||
}else{
|
||||
memcpy(pNew->aData, aData, sz);
|
||||
}
|
||||
|
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Two\sbranches\sassociated\swith\smemdb\sare\snow\salways\staken\s(I\sbelieve).\s\sTag\nthem\swith\sALWAYS()\sto\sverify\sthis.
|
||||
D 2023-01-20T19:19:24.597
|
||||
C Extend\sthe\scarray\sextension\sto\sallow\sthe\suse\sof\sBLOB\svalues\sto\sbe\sbound\nas\san\sarray\sof\s"struct\siovec"\sobjects.
|
||||
D 2023-01-20T21:00:03.027
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -268,7 +268,7 @@ F ext/misc/base85.c 4b53d66c50e120e8697dd2a8ea6ddbc8750a4a1f6bcc6e0b7202a3998b08
|
||||
F ext/misc/basexx.c 5e859e1820620aa8080fb9145eb47089de426ae808f6abb01a8e12921c3a8e67
|
||||
F ext/misc/blobio.c a867c4c4617f6ec223a307ebfe0eabb45e0992f74dd47722b96f3e631c0edb2a
|
||||
F ext/misc/btreeinfo.c d28ce349b40054eaa9473e835837bad7a71deec33ba13e39f963d50933bfa0f9
|
||||
F ext/misc/carray.c b752f46411e4e47e34dce6f0c88bc8e51bb821ba9e49bfcd882506451c928f69
|
||||
F ext/misc/carray.c 0ba03f1e6647785d4e05b51be567f5652f06941314ff9d3d3763900aa353b6b5
|
||||
F ext/misc/carray.h d2b1b12486d531367c37832d3d0dad34eea4bdd83ed839d445521ef01f0bc4e3
|
||||
F ext/misc/cksumvfs.c 9224e33cc0cb6aa61ff1d7d7b8fd6fe56beca9f9c47954fa4ae0a69bef608f69
|
||||
F ext/misc/closure.c dbfd8543b2a017ae6b1a5843986b22ddf99ff126ec9634a2f4047cd14c85c243
|
||||
@ -630,7 +630,7 @@ F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a3
|
||||
F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
F src/tclsqlite.c 8522a04fb9c84faa1d80354430ae0ee9349727a3a4b32e3cfe39b9be8324cabd
|
||||
F src/test1.c 39c13c25f5c4e75a07cb6bd34cfc1b8aa97ecc6f80f08953fa164db7e92ce71e
|
||||
F src/test1.c 06645f545329458c8c445c125d8af4fe066ffd5f16df596dd26ca5319d18c288
|
||||
F src/test2.c 827446e259a3b7ab949da1542953edda7b5117982576d3e6f1c24a0dd20a5cef
|
||||
F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644
|
||||
F src/test4.c 4533b76419e7feb41b40582554663ed3cd77aaa54e135cf76b3205098cd6e664
|
||||
@ -838,7 +838,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 d55d57bf66b1af1c7ac55fae66ff4910884a8f5d21a90a18797ce386212a2634
|
||||
F test/carray01.test 23ed7074307c4a829ba5ff2970993a9d87db7c5cdbbe1a2cbef672d0df6d6e31
|
||||
F test/cast.test e3a7e452f37efec0df0a89e55aa2f04861ba6613deb16075101414668bf4bb24
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/changes.test 9dd8e597d84072122fc8a4fcdea837f4a54a461e6e536053ea984303e8ca937b
|
||||
@ -2043,8 +2043,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P a02da71f3a80dd8e817e89cdaa775c95e38c90d2471f8fec516bed086539e2c0
|
||||
R bf07522ded69fabebaa5b325f6b73b2b
|
||||
P 20b9b5aa4fa6136059cf1123f00d86cb7bd8fb0f0f86f971e9714f22725e60b5
|
||||
R b63d4e1bb53a7ee90a20a60e3fcee608
|
||||
U drh
|
||||
Z e4cafc4e045b3b49d125bdbd66067c68
|
||||
Z 70e393e1d3aa605a996a878e1787d9d5
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
20b9b5aa4fa6136059cf1123f00d86cb7bd8fb0f0f86f971e9714f22725e60b5
|
||||
e117a03ca6560e958884f277db827c51ae337a970c17143a0a5f9b150f52f87a
|
43
src/test1.c
43
src/test1.c
@ -4137,6 +4137,14 @@ static int SQLITE_TCLAPI test_bind_value_from_select(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
struct iovec {
|
||||
void *iov_base;
|
||||
size_t iov_len;
|
||||
};
|
||||
#else
|
||||
# include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
/*
|
||||
@ -4149,6 +4157,7 @@ static int SQLITE_TCLAPI test_bind_value_from_select(
|
||||
** -int64
|
||||
** -double
|
||||
** -text
|
||||
** -blob
|
||||
**
|
||||
** Each call clears static data. Called with no options does nothing
|
||||
** but clear static data.
|
||||
@ -4188,6 +4197,11 @@ static int SQLITE_TCLAPI test_carray_bind(
|
||||
sqlite3_free(((char**)aStaticData)[i]);
|
||||
}
|
||||
}
|
||||
if( eStaticType==4 ){
|
||||
for(i=0; i<nStaticData; i++){
|
||||
sqlite3_free(((struct iovec*)aStaticData)[i].iov_base);
|
||||
}
|
||||
}
|
||||
sqlite3_free(aStaticData);
|
||||
aStaticData = 0;
|
||||
nStaticData = 0;
|
||||
@ -4217,6 +4231,9 @@ static int SQLITE_TCLAPI test_carray_bind(
|
||||
if( strcmp(z, "-text")==0 ){
|
||||
eType = 3; /* CARRAY_TEXT */
|
||||
}else
|
||||
if( strcmp(z, "-blob")==0 ){
|
||||
eType = 4; /* CARRAY_BLOB */
|
||||
}else
|
||||
if( strcmp(z, "--")==0 ){
|
||||
break;
|
||||
}else
|
||||
@ -4230,6 +4247,11 @@ static int SQLITE_TCLAPI test_carray_bind(
|
||||
(char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( eType==4 && !isStatic && !isTransient ){
|
||||
Tcl_AppendResult(interp, "blob data must be either -static or -transient",
|
||||
(char*)0);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( isStatic && isTransient ){
|
||||
Tcl_AppendResult(interp, "cannot be both -static and -transient",
|
||||
(char*)0);
|
||||
@ -4244,7 +4266,7 @@ static int SQLITE_TCLAPI test_carray_bind(
|
||||
if( Tcl_GetIntFromObj(interp, objv[i], &idx) ) return TCL_ERROR;
|
||||
i++;
|
||||
nData = objc - i;
|
||||
switch( eType + 4*(nData<=0) ){
|
||||
switch( eType + 5*(nData<=0) ){
|
||||
case 0: { /* INT32 */
|
||||
int *a = sqlite3_malloc( sizeof(int)*nData );
|
||||
if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
|
||||
@ -4297,7 +4319,24 @@ static int SQLITE_TCLAPI test_carray_bind(
|
||||
aData = a;
|
||||
break;
|
||||
}
|
||||
case 4: { /* nData==0 */
|
||||
case 4: { /* BLOB */
|
||||
struct iovec *a = sqlite3_malloc( sizeof(struct iovec)*nData );
|
||||
if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; }
|
||||
for(j=0; j<nData; j++){
|
||||
int n = 0;
|
||||
unsigned char *v = Tcl_GetByteArrayFromObj(objv[i+i], &n);
|
||||
a[j].iov_len = n;
|
||||
a[j].iov_base = sqlite3_malloc64( n );
|
||||
if( a[j].iov_base==0 ){
|
||||
a[j].iov_len = 0;
|
||||
}else{
|
||||
memcpy(a[j].iov_base, v, n);
|
||||
}
|
||||
}
|
||||
aData = a;
|
||||
break;
|
||||
}
|
||||
case 5: { /* nData==0 */
|
||||
aData = "";
|
||||
xDel = SQLITE_STATIC;
|
||||
isTransient = 0;
|
||||
|
@ -23,110 +23,137 @@ ifcapable !vtab {
|
||||
load_static_extension db carray
|
||||
|
||||
# Parameter $stmt must be a prepared statement created using
|
||||
# the sqlite3_prepare_v2 command and with parameters fullly bound.
|
||||
# the sqlite3_prepare_v2 command and with parameters fully bound.
|
||||
# This routine simply runs the statement, gathers the result, and
|
||||
# returns a list containing the result.
|
||||
#
|
||||
# If the optional second argument is true, then the stmt is finalized
|
||||
# after it is run.
|
||||
#
|
||||
proc run_stmt {stmt {finalizeFlag 0}} {
|
||||
proc run_stmt {stmt} {
|
||||
set r {}
|
||||
while {[sqlite3_step $stmt]=="SQLITE_ROW"} {
|
||||
for {set i 0} {$i<[sqlite3_data_count $stmt]} {incr i} {
|
||||
lappend r [sqlite3_column_text $stmt $i]
|
||||
}
|
||||
}
|
||||
if {$finalizeFlag} {
|
||||
sqlite3_finalize $stmt
|
||||
} else {
|
||||
sqlite3_reset $stmt
|
||||
}
|
||||
sqlite3_reset $stmt
|
||||
return $r
|
||||
}
|
||||
|
||||
do_test 100 {
|
||||
set STMT [sqlite3_prepare_v2 db {SELECT 5 IN carray(?3)} -1]
|
||||
sqlite3_carray_bind $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 101 {
|
||||
sqlite3_carray_bind -static $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 102 {
|
||||
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
|
||||
run_stmt $STMT2
|
||||
} {integer}
|
||||
do_test 110 {
|
||||
sqlite3_carray_bind $STMT 3 1 2 3 4 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 120 {
|
||||
sqlite3_carray_bind -int64 $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 120b {
|
||||
sqlite3_carray_bind -int64 $STMT2 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT2
|
||||
} {integer}
|
||||
do_test 121 {
|
||||
sqlite3_carray_bind -int64 -transient $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 122 {
|
||||
sqlite3_carray_bind -int64 -static $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 123 {
|
||||
sqlite3_carray_bind -int32 -transient $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 124 {
|
||||
sqlite3_carray_bind -int32 -static $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 125 {
|
||||
sqlite3_carray_bind -int32 $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 130 {
|
||||
sqlite3_carray_bind -int64 $STMT 3 1 2 3 4 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 131 {
|
||||
sqlite3_carray_bind -int64 -transient $STMT 3 1 2 3 4 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 131 {
|
||||
sqlite3_carray_bind -int64 -static $STMT 3 1 2 3 4 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 140 {
|
||||
sqlite3_carray_bind -double $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 141 {
|
||||
sqlite3_carray_bind -double -transient $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 142 {
|
||||
sqlite3_carray_bind -double -static $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 143 {
|
||||
sqlite3_carray_bind -double $STMT2 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT2
|
||||
} {real}
|
||||
do_test 150 {
|
||||
sqlite3_carray_bind -double $STMT 3 1 2 3 4 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 160 {
|
||||
sqlite3_carray_bind -double $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {1}
|
||||
do_test 170 {
|
||||
sqlite3_carray_bind -text -static $STMT 3 1 2 3 4 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 171 {
|
||||
sqlite3_carray_bind -text -static $STMT2 3 1 2 3 4 6 7
|
||||
run_stmt $STMT2
|
||||
} {text}
|
||||
do_test 180 {
|
||||
sqlite3_carray_bind -text -transient $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 190 {
|
||||
sqlite3_carray_bind -blob -static $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 191 {
|
||||
sqlite3_carray_bind -blob -static $STMT2 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT2
|
||||
} {blob}
|
||||
do_test 200 {
|
||||
sqlite3_carray_bind -blob -transient $STMT 3 1 2 3 4 5 6 7
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
do_test 300 {
|
||||
sqlite3_carray_bind $STMT 3
|
||||
run_stmt $STMT 0
|
||||
run_stmt $STMT
|
||||
} {0}
|
||||
|
||||
sqlite3_finalize $STMT
|
||||
sqlite3_finalize $STMT2
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user