Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Experimental implementation of sqlite3_result_subtype() and sqlite3_value_subtype() interfaces. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | subtypes |
Files: | files | file ages | folders |
SHA1: |
7b5be299c617a3d3ed327ed30ef0a66a |
User & Date: | drh 2015-09-10 20:34:56.434 |
Context
2015-09-10
| ||
20:40 | Make the sqlite3_value_subtype() and sqlite3_result_subtype() interfaces available to loadable extensions. (check-in: c6fca0be11 user: drh tags: subtypes) | |
20:34 | Experimental implementation of sqlite3_result_subtype() and sqlite3_value_subtype() interfaces. (check-in: 7b5be299c6 user: drh tags: subtypes) | |
19:22 | Fix a potential NULL pointer deref in the testing logic of pcache1. NB: The -DSQLITE_TEST compile-time option is needed to hit the problem. (check-in: f5580f0853 user: drh tags: trunk) | |
Changes
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 | const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values ** METHOD: sqlite3_value ** ** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. | > > > > > > > > > > > > > > > > | 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 | const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); /* ** CAPI3REF: Obtaining SQL Values ** METHOD: sqlite3_value ** ** The sqlite3_value_subtype(V) function returns the subtype for ** an application-defined SQL function argument V. The subtype ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. ** ** SQLite makes no use of subtype itself. It merely passes the subtype ** from the result of one application-defined function to the input of ** another. */ unsigned int sqlite3_value_subtype(sqlite3_value*); /* ** CAPI3REF: Copy And Free SQL Values ** METHOD: sqlite3_value ** ** ^The sqlite3_value_dup(V) interface makes a copy of the [sqlite3_value] ** object D and returns a pointer to that copy. ^The [sqlite3_value] returned ** is a [protected sqlite3_value] object even if the input is not. |
︙ | ︙ | |||
4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 | void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); void sqlite3_result_value(sqlite3_context*, sqlite3_value*); void sqlite3_result_zeroblob(sqlite3_context*, int n); int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Define New Collating Sequences ** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. ** | > > > > > > > > > > > > > > | 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 | void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*)); void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*)); void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*)); void sqlite3_result_value(sqlite3_context*, sqlite3_value*); void sqlite3_result_zeroblob(sqlite3_context*, int n); int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* ** CAPI3REF: Setting The Subtype Of An SQL Function ** METHOD: sqlite3_context ** ** The sqlite3_result_subtype(C,T) function causes the subtype of ** the result from the application-defined function with context C ** to be T. Only the lower 8 bits of the subtype T are preserved ** in current versions of SQLite; higher order bits are discarded. ** The number of subtype bytes preserved by SQLite might increase ** in future releases of SQLite. */ void sqlite3_result_subtype(sqlite3_context*,unsigned int); /* ** CAPI3REF: Define New Collating Sequences ** METHOD: sqlite3 ** ** ^These functions add, remove, or modify a [collation] associated ** with the [database connection] specified as the first argument. ** |
︙ | ︙ |
Changes to src/test_func.c.
︙ | ︙ | |||
458 459 460 461 462 463 464 | } } zOut[16] = 0; sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); } /* | | | 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | } } zOut[16] = 0; sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); } /* ** test_extract(record, field) ** ** This function implements an SQL user-function that accepts a blob ** containing a formatted database record as the first argument. The ** second argument is the index of the field within that record to ** extract and return. */ static void test_extract( |
︙ | ︙ | |||
505 506 507 508 509 510 511 | } if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc); } } /* | | | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | } if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc); } } /* ** test_decode(record) ** ** This function implements an SQL user-function that accepts a blob ** containing a formatted database record as its only argument. It returns ** a tcl list (type SQLITE_TEXT) containing each of the values stored ** in the record. */ static void test_decode( |
︙ | ︙ | |||
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | } sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); Tcl_DecrRefCount(pRet); } /* ** The implementation of scalar SQL function "test_zeroblob()". This is ** similar to the built-in zeroblob() function, except that it does not ** check that the integer parameter is within range before passing it ** to sqlite3_result_zeroblob(). */ static void test_zeroblob( sqlite3_context *context, int argc, sqlite3_value **argv ){ int nZero = sqlite3_value_int(argv[0]); sqlite3_result_zeroblob(context, nZero); } static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; signed char nArg; unsigned int eTextRep; /* 1: UTF-16. 0: UTF-8 */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | } sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); Tcl_DecrRefCount(pRet); } /* ** test_zeroblob(N) ** ** The implementation of scalar SQL function "test_zeroblob()". This is ** similar to the built-in zeroblob() function, except that it does not ** check that the integer parameter is within range before passing it ** to sqlite3_result_zeroblob(). */ static void test_zeroblob( sqlite3_context *context, int argc, sqlite3_value **argv ){ int nZero = sqlite3_value_int(argv[0]); sqlite3_result_zeroblob(context, nZero); } /* test_getsubtype(V) ** ** Return the subtype for value V. */ static void test_getsubtype( sqlite3_context *context, int argc, sqlite3_value **argv ){ sqlite3_result_int(context, (int)sqlite3_value_subtype(argv[0])); } /* test_setsubtype(V, T) ** ** Return the value V with its subtype changed to T */ static void test_setsubtype( sqlite3_context *context, int argc, sqlite3_value **argv ){ sqlite3_result_value(context, argv[0]); sqlite3_result_subtype(context, (unsigned int)sqlite3_value_int(argv[1])); } static int registerTestFunctions(sqlite3 *db){ static const struct { char *zName; signed char nArg; unsigned int eTextRep; /* 1: UTF-16. 0: UTF-8 */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); |
︙ | ︙ | |||
637 638 639 640 641 642 643 644 645 646 647 648 649 650 | { "test_eval", 1, SQLITE_UTF8, test_eval}, { "test_isolation", 2, SQLITE_UTF8, test_isolation}, { "test_counter", 1, SQLITE_UTF8, counterFunc}, { "real2hex", 1, SQLITE_UTF8, real2hex}, { "test_decode", 1, SQLITE_UTF8, test_decode}, { "test_extract", 2, SQLITE_UTF8, test_extract}, { "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob}, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); } | > > | 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 | { "test_eval", 1, SQLITE_UTF8, test_eval}, { "test_isolation", 2, SQLITE_UTF8, test_isolation}, { "test_counter", 1, SQLITE_UTF8, counterFunc}, { "real2hex", 1, SQLITE_UTF8, real2hex}, { "test_decode", 1, SQLITE_UTF8, test_decode}, { "test_extract", 2, SQLITE_UTF8, test_extract}, { "test_zeroblob", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, test_zeroblob}, { "test_getsubtype", 1, SQLITE_UTF8, test_getsubtype}, { "test_setsubtype", 2, SQLITE_UTF8, test_setsubtype}, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].eTextRep, 0, aFuncs[i].xFunc, 0, 0); } |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 180 181 182 183 184 | int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ int n; /* Number of characters in string value, excluding '\0' */ char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ int szMalloc; /* Size of the zMalloc allocation */ u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ sqlite3 *db; /* The associated database connection */ | > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | int nZero; /* Used when bit MEM_Zero is set in flags */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */ u8 eSubtype; /* Subtype for this value */ int n; /* Number of characters in string value, excluding '\0' */ char *z; /* String or BLOB value */ /* ShallowCopy only needs to copy the information above */ char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */ int szMalloc; /* Size of the zMalloc allocation */ u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */ sqlite3 *db; /* The associated database connection */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
182 183 184 185 186 187 188 189 190 191 192 193 194 195 | return sqlite3VdbeRealValue((Mem*)pVal); } int sqlite3_value_int(sqlite3_value *pVal){ return (int)sqlite3VdbeIntValue((Mem*)pVal); } sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); | > > > | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | return sqlite3VdbeRealValue((Mem*)pVal); } int sqlite3_value_int(sqlite3_value *pVal){ return (int)sqlite3VdbeIntValue((Mem*)pVal); } sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){ return sqlite3VdbeIntValue((Mem*)pVal); } unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ return ((Mem*)pVal)->eSubtype; } const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } #ifndef SQLITE_OMIT_UTF16 const void *sqlite3_value_text16(sqlite3_value* pVal){ return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE); |
︙ | ︙ | |||
360 361 362 363 364 365 366 367 368 369 370 371 372 373 | void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } void sqlite3_result_null(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } void sqlite3_result_text( sqlite3_context *pCtx, const char *z, int n, void (*xDel)(void *) ){ | > > > > | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 | void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } void sqlite3_result_null(sqlite3_context *pCtx){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); sqlite3VdbeMemSetNull(pCtx->pOut); } void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) ); pCtx->pOut->eSubtype = eSubtype & 0xff; } void sqlite3_result_text( sqlite3_context *pCtx, const char *z, int n, void (*xDel)(void *) ){ |
︙ | ︙ |
Added test/subtype1.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | # 2015-09-10 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements tests for sqlite3_value_subtype() and # sqlite3_result_subtype() interfaces. # set testdir [file dirname $argv0] source $testdir/tester.tcl do_execsql_test subtype1-100 { SELECT test_getsubtype('hello'); } {0} do_execsql_test subtype1-110 { SELECT test_getsubtype(test_setsubtype('hello',123)); } {123} do_execsql_test subtype1-120 { SELECT typeof(test_setsubtype('hello',123)); } {text} do_execsql_test subtype1-130 { SELECT test_setsubtype('hello',123); } {hello} finish_test |