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>→<td>Default 4976 4976 ** datatype of the value 4977 4977 ** <tr><td><b>sqlite3_value_numeric_type </b> 4978 4978 ** <td>→ <td>Best numeric datatype of the value 4979 4979 ** <tr><td><b>sqlite3_value_nochange </b> 4980 4980 ** <td>→ <td>True if the column is unchanged in an UPDATE 4981 4981 ** against a virtual table. 4982 +** <tr><td><b>sqlite3_value_frombind </b> 4983 +** <td>→ <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