/ Changes On Branch value_frombind
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch value_frombind Excluding Merge-Ins

This is equivalent to a diff from 965cbcea11 to 1dc7993bb6

2019-04-02
00:28
Add the sqlite3_value_frombind() interface. Use that interface to improve fts3_tokenizer(). (check-in: b3f2c3205a user: drh tags: trunk)
2019-04-01
20:57
Performance improvement on the OP_Variable opcode. (Closed-Leaf check-in: 1dc7993bb6 user: drh tags: value_frombind)
2019-03-29
17:26
Change the fts3_tokenizer() function to always return the pointer as a BLOB as long as the first argument is a bound parameter, regardless of the SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER setting. (check-in: 27160df7b3 user: drh tags: value_frombind)
11:48
Fix typos in the comments of the sessions extension, one of which affects the generated documentation. No code changes. (check-in: 040d5d515b user: drh tags: trunk)
11:13
Initial implementation of the sqlite3_value_frombind() interface. (check-in: 98da62dfda user: drh tags: value_frombind)
01:15
Recover a some of the performance lost by window function alias fix two check-ins back. (check-in: 965cbcea11 user: drh tags: trunk)
2019-03-28
20:50
Add new test cases to test/fuzzdata8.db (check-in: f908cd40b2 user: drh tags: trunk)

Changes to ext/fts3/fts3_tokenizer.c.

    75     75   
    76     76     pHash = (Fts3Hash *)sqlite3_user_data(context);
    77     77   
    78     78     zName = sqlite3_value_text(argv[0]);
    79     79     nName = sqlite3_value_bytes(argv[0])+1;
    80     80   
    81     81     if( argc==2 ){
    82         -    if( fts3TokenizerEnabled(context) ){
           82  +    if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[1]) ){
    83     83         void *pOld;
    84     84         int n = sqlite3_value_bytes(argv[1]);
    85     85         if( zName==0 || n!=sizeof(pPtr) ){
    86     86           sqlite3_result_error(context, "argument type mismatch", -1);
    87     87           return;
    88     88         }
    89     89         pPtr = *(void **)sqlite3_value_blob(argv[1]);
................................................................................
   102    102       if( !pPtr ){
   103    103         char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
   104    104         sqlite3_result_error(context, zErr, -1);
   105    105         sqlite3_free(zErr);
   106    106         return;
   107    107       }
   108    108     }
   109         -  if( fts3TokenizerEnabled(context) ){
          109  +  if( fts3TokenizerEnabled(context) || sqlite3_value_frombind(argv[0]) ){
   110    110       sqlite3_result_blob(context, (void *)&pPtr, sizeof(pPtr), SQLITE_TRANSIENT);
   111    111     }
   112    112   }
   113    113   
   114    114   int sqlite3Fts3IsIdChar(char c){
   115    115     static const char isFtsIdChar[] = {
   116    116         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 0x */

Changes to src/sqlite.h.in.

  4975   4975   ** <tr><td><b>sqlite3_value_type</b><td>&rarr;<td>Default
  4976   4976   ** datatype of the value
  4977   4977   ** <tr><td><b>sqlite3_value_numeric_type&nbsp;&nbsp;</b>
  4978   4978   ** <td>&rarr;&nbsp;&nbsp;<td>Best numeric datatype of the value
  4979   4979   ** <tr><td><b>sqlite3_value_nochange&nbsp;&nbsp;</b>
  4980   4980   ** <td>&rarr;&nbsp;&nbsp;<td>True if the column is unchanged in an UPDATE
  4981   4981   ** against a virtual table.
         4982  +** <tr><td><b>sqlite3_value_frombind&nbsp;&nbsp;</b>
         4983  +** <td>&rarr;&nbsp;&nbsp;<td>True if value originated a bound parameter
  4982   4984   ** </table></blockquote>
  4983   4985   **
  4984   4986   ** <b>Details:</b>
  4985   4987   **
  4986   4988   ** These routines extract type, size, and content information from
  4987   4989   ** [protected sqlite3_value] objects.  Protected sqlite3_value objects
  4988   4990   ** are used to pass parameter information into implementation of
................................................................................
  5035   5037   ** the value for that column returned without setting a result (probably
  5036   5038   ** because it queried [sqlite3_vtab_nochange()] and found that the column
  5037   5039   ** was unchanging).  ^Within an [xUpdate] method, any value for which
  5038   5040   ** sqlite3_value_nochange(X) is true will in all other respects appear
  5039   5041   ** to be a NULL value.  If sqlite3_value_nochange(X) is invoked anywhere other
  5040   5042   ** than within an [xUpdate] method call for an UPDATE statement, then
  5041   5043   ** the return value is arbitrary and meaningless.
         5044  +**
         5045  +** ^The sqlite3_value_frombind(X) interface returns non-zero if the
         5046  +** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
         5047  +** interfaces.  ^If X comes from an SQL literal value, or a table column,
         5048  +** and expression, then sqlite3_value_frombind(X) returns zero.
  5042   5049   **
  5043   5050   ** Please pay particular attention to the fact that the pointer returned
  5044   5051   ** from [sqlite3_value_blob()], [sqlite3_value_text()], or
  5045   5052   ** [sqlite3_value_text16()] can be invalidated by a subsequent call to
  5046   5053   ** [sqlite3_value_bytes()], [sqlite3_value_bytes16()], [sqlite3_value_text()],
  5047   5054   ** or [sqlite3_value_text16()].
  5048   5055   **
................................................................................
  5081   5088   const void *sqlite3_value_text16le(sqlite3_value*);
  5082   5089   const void *sqlite3_value_text16be(sqlite3_value*);
  5083   5090   int sqlite3_value_bytes(sqlite3_value*);
  5084   5091   int sqlite3_value_bytes16(sqlite3_value*);
  5085   5092   int sqlite3_value_type(sqlite3_value*);
  5086   5093   int sqlite3_value_numeric_type(sqlite3_value*);
  5087   5094   int sqlite3_value_nochange(sqlite3_value*);
         5095  +int sqlite3_value_frombind(sqlite3_value*);
  5088   5096   
  5089   5097   /*
  5090   5098   ** CAPI3REF: Finding The Subtype Of SQL Values
  5091   5099   ** METHOD: sqlite3_value
  5092   5100   **
  5093   5101   ** The sqlite3_value_subtype(V) function returns the subtype for
  5094   5102   ** an [application-defined SQL function] argument V.  The subtype

Changes to src/test_func.c.

   625    625   static void test_getsubtype(
   626    626     sqlite3_context *context,
   627    627     int argc,
   628    628     sqlite3_value **argv
   629    629   ){
   630    630     sqlite3_result_int(context, (int)sqlite3_value_subtype(argv[0]));
   631    631   }
          632  +
          633  +/*         test_frombind(A,B,C,...)
          634  +**
          635  +** Return an integer bitmask that has a bit set for every argument
          636  +** (up to the first 63 arguments) that originates from a bind a parameter.
          637  +*/
          638  +static void test_frombind(
          639  +  sqlite3_context *context,
          640  +  int argc,
          641  +  sqlite3_value **argv
          642  +){
          643  +  sqlite3_uint64 m = 0;
          644  +  int i;
          645  +  for(i=0; i<argc && i<63; i++){
          646  +    if( sqlite3_value_frombind(argv[i]) ) m |= ((sqlite3_uint64)1)<<i;
          647  +  }
          648  +  sqlite3_result_int64(context, (sqlite3_int64)m);
          649  +}
   632    650   
   633    651   /*         test_setsubtype(V, T)
   634    652   **
   635    653   ** Return the value V with its subtype changed to T
   636    654   */
   637    655   static void test_setsubtype(
   638    656     sqlite3_context *context,
................................................................................
   671    689       { "test_counter",          1, SQLITE_UTF8, counterFunc},
   672    690       { "real2hex",              1, SQLITE_UTF8, real2hex},
   673    691       { "test_decode",           1, SQLITE_UTF8, test_decode},
   674    692       { "test_extract",          2, SQLITE_UTF8, test_extract},
   675    693       { "test_zeroblob",  1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob},
   676    694       { "test_getsubtype",       1, SQLITE_UTF8, test_getsubtype},
   677    695       { "test_setsubtype",       2, SQLITE_UTF8, test_setsubtype},
          696  +    { "test_frombind",        -1, SQLITE_UTF8, test_frombind},
   678    697     };
   679    698     int i;
   680    699   
   681    700     for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
   682    701       sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
   683    702           aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0);
   684    703     }

Changes to src/vdbe.c.

  1232   1232     assert( pOp->p1>0 && pOp->p1<=p->nVar );
  1233   1233     assert( pOp->p4.z==0 || pOp->p4.z==sqlite3VListNumToName(p->pVList,pOp->p1) );
  1234   1234     pVar = &p->aVar[pOp->p1 - 1];
  1235   1235     if( sqlite3VdbeMemTooBig(pVar) ){
  1236   1236       goto too_big;
  1237   1237     }
  1238   1238     pOut = &aMem[pOp->p2];
  1239         -  sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
         1239  +  if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
         1240  +  memcpy(pOut, pVar, MEMCELLSIZE);
         1241  +  pOut->flags &= ~(MEM_Dyn|MEM_Ephem);
         1242  +  pOut->flags |= MEM_Static|MEM_FromBind;
  1240   1243     UPDATE_MAX_BLOBSIZE(pOut);
  1241   1244     break;
  1242   1245   }
  1243   1246   
  1244   1247   /* Opcode: Move P1 P2 P3 * *
  1245   1248   ** Synopsis: r[P2@P3]=r[P1@P3]
  1246   1249   **

Changes to src/vdbeInt.h.

   242    242   */
   243    243   #define MEM_Null      0x0001   /* Value is NULL (or a pointer) */
   244    244   #define MEM_Str       0x0002   /* Value is a string */
   245    245   #define MEM_Int       0x0004   /* Value is an integer */
   246    246   #define MEM_Real      0x0008   /* Value is a real number */
   247    247   #define MEM_Blob      0x0010   /* Value is a BLOB */
   248    248   #define MEM_AffMask   0x001f   /* Mask of affinity bits */
   249         -/* Available          0x0020   */
          249  +#define MEM_FromBind  0x0020   /* Value originates from sqlite3_bind() */
   250    250   /* Available          0x0040   */
   251    251   #define MEM_Undefined 0x0080   /* Value is undefined */
   252    252   #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
   253    253   #define MEM_TypeMask  0xc1ff   /* Mask of type bits */
   254    254   
   255    255   
   256    256   /* Whenever Mem contains a valid string or blob representation, one of

Changes to src/vdbeapi.c.

   270    270     return aType[pVal->flags&MEM_AffMask];
   271    271   }
   272    272   
   273    273   /* Return true if a parameter to xUpdate represents an unchanged column */
   274    274   int sqlite3_value_nochange(sqlite3_value *pVal){
   275    275     return (pVal->flags&(MEM_Null|MEM_Zero))==(MEM_Null|MEM_Zero);
   276    276   }
          277  +
          278  +/* Return true if a parameter value originated from an sqlite3_bind() */
          279  +int sqlite3_value_frombind(sqlite3_value *pVal){
          280  +  return (pVal->flags&MEM_FromBind)!=0;
          281  +}
   277    282   
   278    283   /* Make a copy of an sqlite3_value object
   279    284   */
   280    285   sqlite3_value *sqlite3_value_dup(const sqlite3_value *pOrig){
   281    286     sqlite3_value *pNew;
   282    287     if( pOrig==0 ) return 0;
   283    288     pNew = sqlite3_malloc( sizeof(*pNew) );

Changes to src/vdbemem.c.

    53     53         /* This is a pointer type.  There may be a flag to indicate what to
    54     54         ** do with the pointer. */
    55     55         assert( ((p->flags&MEM_Dyn)!=0 ? 1 : 0) +
    56     56                 ((p->flags&MEM_Ephem)!=0 ? 1 : 0) +
    57     57                 ((p->flags&MEM_Static)!=0 ? 1 : 0) <= 1 );
    58     58   
    59     59         /* No other bits set */
    60         -      assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype
           60  +      assert( (p->flags & ~(MEM_Null|MEM_Term|MEM_Subtype|MEM_FromBind
    61     61                              |MEM_Dyn|MEM_Ephem|MEM_Static))==0 );
    62     62       }else{
    63     63         /* A pure NULL might have other flags, such as MEM_Static, MEM_Dyn,
    64     64         ** MEM_Ephem, MEM_Cleared, or MEM_Subtype */
    65     65       }
    66     66     }else{
    67     67       /* The MEM_Cleared bit is only allowed on NULLs */

Changes to test/fts3atoken.test.

    82     82       INSERT INTO t1(content) VALUES('There was movement at the station');
    83     83       INSERT INTO t1(content) VALUES('For the word has passed around');
    84     84       INSERT INTO t1(content) VALUES('That the colt from ol regret had got');
    85     85       SELECT content FROM t1 WHERE content MATCH 'movement'
    86     86     }
    87     87   } {{There was movement at the station}}
    88     88   
           89  +unset -nocomplain simple blah2name simplename
           90  +set simplename "simple"
           91  +set blah2name "blah2"
           92  +set simple [db one {SELECT fts3_tokenizer('simple')}]
    89     93   sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 0
    90     94   do_catchsql_test 1.6 {
    91     95     SELECT fts3_tokenizer('blah', fts3_tokenizer('simple')) IS NULL;
    92     96   } {1 {fts3tokenize disabled}}
           97  +do_test fts3atoken-1.7 {
           98  +  execsql {
           99  +    SELECT fts3_tokenizer('blah2', $simple) IS NULL;
          100  +  }
          101  +} {1}
    93    102   
          103  +# With ENABLE_FTS3_TOKENIZER off, the fts3_tokenzer(1) function
          104  +# returns NULL unless the first parameter is a bound parameter.
          105  +# If the first parameter is a bound parameter, then fts3_tokenizer(1)
          106  +# returns the actual pointer value as a BLOB.
          107  +#
          108  +do_test fts3atoken-1.8 {
          109  +  execsql {
          110  +    SELECT fts3_tokenizer($blah2name) == fts3_tokenizer($simplename),
          111  +           typeof(fts3_tokenizer($blah2name)),
          112  +           typeof(fts3_tokenizer('blah2')),
          113  +           typeof(fts3_tokenizer($simplename)),
          114  +           typeof(fts3_tokenizer('simple'));
          115  +  }
          116  +} {1 blob null blob null}
          117  +
          118  +# With ENABLE_FTS3_TOKENIZER on, fts3_tokenizer() always returns
          119  +# the BLOB pointer, regardless the parameter
          120  +#
          121  +sqlite3_db_config db SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1
          122  +do_test fts3atoken-1.9 {
          123  +  execsql {
          124  +    SELECT fts3_tokenizer('blah2') == fts3_tokenizer('simple'),
          125  +           typeof(fts3_tokenizer($blah2name)),
          126  +           typeof(fts3_tokenizer('blah2')),
          127  +           typeof(fts3_tokenizer($simplename)),
          128  +           typeof(fts3_tokenizer('simple'));
          129  +  }
          130  +} {1 blob blob blob blob}
    94    131   
    95    132   #--------------------------------------------------------------------------
    96    133   # Test cases fts3atoken-2.* test error cases in the scalar function based
    97    134   # API for getting and setting tokenizers.
    98    135   #
    99    136   do_test fts3atoken-2.1 {
   100    137     catchsql {

Changes to test/func.test.

  1387   1387   }
  1388   1388   
  1389   1389   # Test char().
  1390   1390   #
  1391   1391   do_execsql_test func-31.1 { 
  1392   1392     SELECT char(), length(char()), typeof(char()) 
  1393   1393   } {{} 0 text}
         1394  +
         1395  +# sqlite3_value_frombind()
         1396  +#
         1397  +do_execsql_test func-32.100 {
         1398  +  SELECT test_frombind(1,2,3,4);
         1399  +} {0}
         1400  +do_execsql_test func-32.110 {
         1401  +  SELECT test_frombind(1,2,?,4);
         1402  +} {4}
         1403  +do_execsql_test func-32.120 {
         1404  +  SELECT test_frombind(1,(?),4,?+7);
         1405  +} {2}
         1406  +do_execsql_test func-32.130 {
         1407  +  DROP TABLE IF EXISTS t1;
         1408  +  CREATE TABLE t1(a,b,c,e,f);
         1409  +  INSERT INTO t1 VALUES(1,2.5,'xyz',x'e0c1b2a3',null);
         1410  +  SELECT test_frombind(a,b,c,e,f,$xyz) FROM t1;
         1411  +} {32}
         1412  +do_execsql_test func-32.140 {
         1413  +  SELECT test_frombind(a,b,c,e,f,$xyz+f) FROM t1;
         1414  +} {0}
         1415  +do_execsql_test func-32.150 {
         1416  +  SELECT test_frombind(x.a,y.b,x.c,:123,y.e,x.f,$xyz+y.f) FROM t1 x, t1 y;
         1417  +} {8}
         1418  +
         1419  +
         1420  +
         1421  +
  1394   1422   finish_test