]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Extend the carray extension to allow the use of BLOB values to be bound
authordrh <>
Fri, 20 Jan 2023 21:00:03 +0000 (21:00 +0000)
committerdrh <>
Fri, 20 Jan 2023 21:00:03 +0000 (21:00 +0000)
as an array of "struct iovec" objects.

FossilOrigin-Name: e117a03ca6560e958884f277db827c51ae337a970c17143a0a5f9b150f52f87a

ext/misc/carray.c
manifest
manifest.uuid
src/test1.c
test/carray01.test

index b6eb0453a034ecd1e99431882dd9c2443f553fdb..709c894f276032d54128f4d4533ae5d04eeed674 100644 (file)
@@ -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*');
 **
 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);
     }
index 1f56d7368a2aff54b29d998eb2a2aeee166ea5e8..b11a10787df198b536856dc2fe2fe6fde1226d7f 100644 (file)
--- a/manifest
+++ b/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.
index 077c1fe317636a96798635ad31213a01503ebb63..4eb51b78b975ab65e45b95afacfacbcef7aa9dbb 100644 (file)
@@ -1 +1 @@
-20b9b5aa4fa6136059cf1123f00d86cb7bd8fb0f0f86f971e9714f22725e60b5
\ No newline at end of file
+e117a03ca6560e958884f277db827c51ae337a970c17143a0a5f9b150f52f87a
\ No newline at end of file
index dda77a90a50ce4e1b2f404722c02aa01315a7c12..2f384a2c08af6c5c8a104141b2ed6d34c17d6353 100644 (file)
@@ -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;
index d6243eb2743bb0d7cf3c1b6934edee3381f6e2bf..1af9cb66e33457ab20cf523041c91b02d24065b2 100644 (file)
@@ -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