From 4f26d6c42911f7d6ee6daea5332bac4a128e7861 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 26 May 2004 23:25:30 +0000 Subject: [PATCH] Refactoring of the vdbe Mem functions and the APIs that deal with them. The code will not compile in its current state. (CVS 1465) FossilOrigin-Name: bba6684d502ba1ecd9614d2470ec94296e3c07c2 --- manifest | 34 +- manifest.uuid | 2 +- src/date.c | 8 +- src/func.c | 45 ++- src/legacy.c | 6 +- src/md5.c | 9 +- src/sqlite.h.in | 652 ++++++++------------------------ src/tclsqlite.c | 4 +- src/test1.c | 32 +- src/test4.c | 7 +- src/vdbe.c | 974 ++---------------------------------------------- src/vdbeInt.h | 31 +- src/vdbeapi.c | 503 +++++++++++++++++++++++++ src/vdbeaux.c | 4 +- src/vdbemem.c | 398 ++++++++++++++++++++ 15 files changed, 1157 insertions(+), 1552 deletions(-) create mode 100644 src/vdbeapi.c create mode 100644 src/vdbemem.c diff --git a/manifest b/manifest index 4aa25c5fa2..20ef5496fe 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sdataType\sand\sincludeTypes\sflags\sfrom\sfunction\sdefinitions.\s\sAdded\snew\nP3_FUNCDEF\stype\sfor\sP3\sarguments\son\sopcodes.\s\sFixes\sto\sseveral\suser\sfunctions.\n28\stests\sfail\snow.\s(CVS\s1464) -D 2004-05-26T16:54:42 +C Refactoring\sof\sthe\svdbe\sMem\sfunctions\sand\sthe\sAPIs\sthat\sdeal\swith\sthem.\nThe\scode\swill\snot\scompile\sin\sits\scurrent\sstate.\s(CVS\s1465) +D 2004-05-26T23:25:31 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -28,17 +28,17 @@ F src/btree.c 6db76fbf63efd6008c5e6cb038ea40f94abffcf7 F src/btree.h b65140b5ae891f30d2a39e64b9f0343225553545 F src/build.c 35cbeb439b49cca5eb5e8a1de010a5194f4523e8 F src/copy.c 6eb7cc08ae6dc60bf83ecadf4508a0bef909dbd2 -F src/date.c 37bb5784da38457d0762281e0176b27e5aa00cf5 +F src/date.c 0eb922af5c5f5e2455f8dc2f98023ed3e04a857e F src/delete.c 66c5ab98cbad7e6b315fc997bfe6c8080784a701 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 F src/expr.c 90573f18f946c94848d5ca1c925a141ef5dfe111 -F src/func.c 6274bceb41a032ff60297a992f54861e9d63cb20 +F src/func.c a25ec101ac83e62abb249d4d3e5204c60a772224 F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/insert.c dd117e8b3f50e943e6cf5fbcf4bbdc0b907b0b4c -F src/legacy.c a856d2d5317ed2ac93c2c6cbba7d4faa564a5b20 +F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f F src/main.c 488ec788a06019521e53ffd25c4af97943937fb5 -F src/md5.c 833671b541a76fc0e62404433c9176706eeacdf0 +F src/md5.c d2c738fedfb27f73cefcf2b0ac1f9f21894b073e F src/os.h ab42f4a7c4c716f26b988e759b6e12085a3bfc67 F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0 @@ -55,14 +55,14 @@ F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c e90e2a147273cdcdb1ee9e14574ab28f04382e63 F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f -F src/sqlite.h.in 91a42246b390974361fdf8daf273d6c3bbf95e85 +F src/sqlite.h.in 68e165dc4dc2d477c95c76b9ede13eed5fbaabf4 F src/sqliteInt.h 6b0d8d856c4af325eb5a00d1c32d89aacf432875 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 -F src/tclsqlite.c b9386659cec1eac402ac7a2371deefe70709bf6a -F src/test1.c f8dacbbdfa206ed975c02842c52dee0c97952817 +F src/tclsqlite.c 86daf7bf6ba715bf0f0c7a47beb1d947a15cb868 +F src/test1.c f9d1e36b87b5a2253dabd4c563e110e8d8273dbf F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872 F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968 -F src/test4.c 014478492bddb3f9b4a3151b05f9ac708fe279fb +F src/test4.c 34848a9fd31aa65857b20a8bfc03aff77d8c3426 F src/test5.c 9a1f15133f6955f067c5246e564723b5f23ff221 F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847 F src/trigger.c 11afe9abfba13a2ba142944c797c952e162d117f @@ -70,10 +70,12 @@ F src/update.c 96461bcf4e946697e83c09c77c7e61b545a2f66e F src/utf.c 1d38da85bffb928fb0d9f301e7db913a6df486ce F src/util.c 4c0adcbc9ce6678dd046931253e45d623c6d279f F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad -F src/vdbe.c a4b2f800137c652433b786537f1750ee769b2014 +F src/vdbe.c 4419d3b7e4d56b0c1d973ebf4de40ee5045e612e F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb -F src/vdbeInt.h 1064ce1723c9c739772af2903e7e06ad2b214be1 -F src/vdbeaux.c 951985ea55c6bac6dcd0041ee652a4eec2a65b06 +F src/vdbeInt.h d7eda2403e11de5e0c581f91bd202cc952190a97 +F src/vdbeapi.c 36d4c78bc765dc89cac07ff975b26256e0ac90fc +F src/vdbeaux.c 677317be4021eadce96365b16d9deeda9e565bef +F src/vdbemem.c c92c41c80c333b3cd405a08ebfd014d02a9f7b8c F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83 @@ -203,7 +205,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P ce8b15203413f38a8b7127eb08ae5db1c1eb164a -R d2e1633ebc6abb34ef4a297a6d817967 +P 36e031625995b2f7baf7654d771ca8fb764a0085 +R f8551815839ed9151ff9855a8a833baa U drh -Z 933339c84dc9b3a3ef071d1cac60a7a8 +Z af6c613d004b8ea284a0c6f10b3031e5 diff --git a/manifest.uuid b/manifest.uuid index ee904ddb3c..326af42a5c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36e031625995b2f7baf7654d771ca8fb764a0085 \ No newline at end of file +bba6684d502ba1ecd9614d2470ec94296e3c07c2 \ No newline at end of file diff --git a/src/date.c b/src/date.c index 3a15ba1632..42f42f22de 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.25 2004/05/26 16:54:42 drh Exp $ +** $Id: date.c,v 1.26 2004/05/26 23:25:31 drh Exp $ ** ** NOTES: ** @@ -645,10 +645,10 @@ static int isDate(int argc, sqlite3_value **argv, DateTime *p){ int i; if( argc==0 ) return 1; if( SQLITE3_NULL==sqlite3_value_type(argv[0]) || - parseDateOrTime(sqlite3_value_data(argv[0]), p) ) return 1; + parseDateOrTime(sqlite3_value_text(argv[0]), p) ) return 1; for(i=1; i #include @@ -88,7 +88,7 @@ static void lengthFunc( break; } case SQLITE3_TEXT: { - const char *z = sqlite3_value_data(argv[0]); + const char *z = sqlite3_value_text(argv[0]); for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } sqlite3_result_int32(context, len); break; @@ -108,7 +108,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ assert( argc==1 ); switch( sqlite3_value_type(argv[0]) ){ case SQLITE3_INTEGER: { - sqlite3_result_int64(context, -sqlite3_value_int(argv[0])); + sqlite3_result_int64(context, -sqlite3_value_int64(argv[0])); break; } case SQLITE3_NULL: { @@ -116,7 +116,7 @@ static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ break; } default: { - sqlite3_result_double(context, -sqlite3_value_float(argv[0])); + sqlite3_result_double(context, -sqlite3_value_double(argv[0])); break; } } @@ -136,7 +136,7 @@ static void substrFunc( int p1, p2, len; assert( argc==3 ); - z = sqlite3_value_data(argv[0]); + z = sqlite3_value_text(argv[0]); if( z==0 ) return; p1 = sqlite3_value_int(argv[1]); p2 = sqlite3_value_int(argv[2]); @@ -180,7 +180,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( n<0 ) n = 0; } if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; - r = sqlite3_value_float(argv[0]); + r = sqlite3_value_double(argv[0]); sprintf(zBuf,"%.*f",n,r); sqlite3_result_text(context, zBuf, -1, 1); } @@ -194,7 +194,7 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( argc<1 || SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])); if( z==0 ) return; - strcpy(z, sqlite3_value_data(argv[0])); + strcpy(z, sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ if( islower(z[i]) ) z[i] = toupper(z[i]); } @@ -207,7 +207,7 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ if( argc<1 || SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; z = sqliteMalloc(sqlite3_value_bytes(argv[0])); if( z==0 ) return; - strcpy(z, sqlite3_value_data(argv[0])); + strcpy(z, sqlite3_value_text(argv[0])); for(i=0; z[i]; i++){ if( isupper(z[i]) ) z[i] = tolower(z[i]); } @@ -301,8 +301,8 @@ static void likeFunc( int argc, sqlite3_value **argv ){ - const unsigned char *zA = sqlite3_value_data(argv[0]); - const unsigned char *zB = sqlite3_value_data(argv[1]); + const unsigned char *zA = sqlite3_value_text(argv[0]); + const unsigned char *zB = sqlite3_value_text(argv[1]); if( zA && zB ){ sqlite3_result_int32(context, sqlite3LikeCompare(zA, zB)); } @@ -318,8 +318,8 @@ static void likeFunc( ** is implemented as glob(A,B). */ static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){ - const unsigned char *zA = sqlite3_value_data(argv[0]); - const unsigned char *zB = sqlite3_value_data(argv[1]); + const unsigned char *zA = sqlite3_value_text(argv[0]); + const unsigned char *zB = sqlite3_value_text(argv[1]); if( zA && zB ){ sqlite3_result_int32(context, sqlite3GlobCompare(zA, zB)); } @@ -364,7 +364,6 @@ static void versionFunc( ** single-quote escapes. */ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - const char *zArg = sqlite3_value_data(argv[0]); if( argc<1 ) return; switch( sqlite3_value_type(argv[0]) ){ case SQLITE3_NULL: { @@ -379,7 +378,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ case SQLITE3_BLOB: /*** FIX ME. Use a BLOB encoding ***/ case SQLITE3_TEXT: { int i,j,n; - const char *zArg = sqlite3_value_data(argv[0]); + const char *zArg = sqlite3_value_text(argv[0]); char *z; for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } @@ -419,7 +418,7 @@ static void soundexFunc(sqlite3_context *context, int argc, sqlite3_value **argv 1, 2, 6, 2, 3, 0, 1, 0, 2, 0, 2, 0, 0, 0, 0, 0, }; assert( argc==1 ); - zIn = sqlite3_value_data(argv[0]); + zIn = sqlite3_value_text(argv[0]); for(i=0; zIn[i] && !isalpha(zIn[i]); i++){} if( zIn[i] ){ zResult[0] = toupper(zIn[i]); @@ -499,20 +498,20 @@ struct SumCtx { static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){ SumCtx *p; if( argc<1 ) return; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && SQLITE3_NULL!=sqlite3_value_type(argv[0]) ){ - p->sum += sqlite3_value_float(argv[0]); + p->sum += sqlite3_value_double(argv[0]); p->cnt++; } } static void sumFinalize(sqlite3_context *context){ SumCtx *p; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_double(context, p ? p->sum : 0.0); } static void avgFinalize(sqlite3_context *context){ SumCtx *p; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); if( p && p->cnt>0 ){ sqlite3_result_double(context, p->sum/(double)p->cnt); } @@ -570,14 +569,14 @@ struct CountCtx { */ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){ CountCtx *p; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); if( (argc==0 || SQLITE3_NULL!=sqlite3_value_type(argv[0])) && p ){ p->n++; } } static void countFinalize(sqlite3_context *context){ CountCtx *p; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_int32(context, p ? p->n : 0); } @@ -598,7 +597,7 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv) int max = 0; int cmp = 0; Mem *pArg = (Mem *)argv[0]; - Mem *pBest = (Mem *)sqlite3_get_context(context, sizeof(*pBest)); + Mem *pBest = (Mem *)sqlite3_aggregate_context(context, sizeof(*pBest)); if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return; @@ -622,7 +621,7 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv) } static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; - pRes = (sqlite3_value *)sqlite3_get_context(context, sizeof(Mem)); + pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem)); if( pRes->flags ){ sqlite3_result(context, pRes); } diff --git a/src/legacy.c b/src/legacy.c index 655f2bb7bd..664705ba0b 100644 --- a/src/legacy.c +++ b/src/legacy.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: legacy.c,v 1.2 2004/05/26 02:04:57 danielk1977 Exp $ +** $Id: legacy.c,v 1.3 2004/05/26 23:25:31 drh Exp $ */ #include "sqliteInt.h" @@ -90,7 +90,7 @@ int sqlite3_exec( if( rc==SQLITE_ROW ){ azVals = &azCols[nCol]; for(i=0; iTEXT +** FLOAT INTEGER Convert from float to integer +** FLOAT TEXT ASCII rendering of the float +** FLOAT BLOB Same as FLOAT->TEXT +** TEXT INTEGER Use atoi() +** TEXT FLOAT Use atof() +** TEXT BLOB No change +** BLOB INTEGER Convert to TEXT then use atoi() +** BLOB FLOAT Convert to TEXT then use atof() +** BLOB TEXT Add a \000 terminator if needed +** +** The following access routines are provided: +** +** _type() Return the datatype of the result. This is one of +** SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, SQLITE_BLOB, +** or SQLITE_NULL. +** _blob() Return the value of a BLOB. +** _bytes() Return the number of bytes in a BLOB value or the number +** of bytes in a TEXT value represented as UTF-8. The \000 +** terminator is included in the byte count for TEXT values. +** _bytes16() Return the number of bytes in a BLOB value or the number +** of bytes in a TEXT value represented as UTF-16. The \u0000 +** terminator is included in the byte count for TEXT values. +** _double() Return a FLOAT value. +** _int() Return an INTEGER value in the host computer's native +** integer representation. This might be either a 32- or 64-bit +** integer depending on the host. +** _int64() Return an INTEGER value as a 64-bit signed integer. +** _text() Return the value as UTF-8 text. +** _text16() Return the value as UTF-16 text. */ -int sqlite3_column_type(sqlite3_stmt *pStmt, int i); - -/* -** The first parameter is a compiled SQL statement for which the most -** recent call to sqlite3_step() has returned SQLITE_ROW. This routine -** retrieves the value of the Nth column of the current row, where -** N is the second function parameter. -** -** The value returned depends on the type of the SQL column value, as -** returned by sqlite3_column_type(): -** -** SQLITE3_NULL A Null pointer. -** SQLITE3_INTEGER String representation of the integer, UTF-8 encoded. -** SQLITE3_FLOAT String representation of the real, UTF-8 encoded. -** SQLITE3_TEXT The string UTF-8 encoded. -** SQLITE3_BLOB A pointer to the blob of data. -*/ -const unsigned char *sqlite3_column_data(sqlite3_stmt*,int); - -/* -** The first parameter is a compiled SQL statement for which the most -** recent call to sqlite3_step() has returned SQLITE_ROW. This routine -** retrieves the value of the Nth column of the current row, where -** N is the second function parameter. -** -** The value returned depends on the type of the SQL column value, as -** returned by sqlite3_column_type(): -** -** SQLITE3_NULL A Null pointer. -** SQLITE3_INTEGER String representation of the integer, UTF-16 encoded. -** SQLITE3_FLOAT String representation of the real, UTF-16 encoded. -** SQLITE3_TEXT The string UTF-16 encoded. -** SQLITE3_BLOB A pointer to the blob of data. -*/ -const void *sqlite3_column_data16(sqlite3_stmt*,int); - -/* -** The first parameter is a compiled SQL statement for which the most -** recent call to sqlite3_step() has returned SQLITE_ROW. This routine -** retrieves the length of the data in bytes returned by the -** sqlite3_column_data() routine for the same second parameter value. -** -** If sqlite3_column_data() returns a UTF-8 string, then the length -** returned by this function includes the nul terminator character at the -** end of the UTF-8 string. -*/ -int sqlite3_column_bytes(sqlite3_stmt*,int); - -/* -** The first parameter is a compiled SQL statement for which the most -** recent call to sqlite3_step() has returned SQLITE_ROW. This routine -** retrieves the length of the data in bytes returned by the -** sqlite3_column_data() routine for the same second parameter value. -** -** If sqlite3_column_data() returns a UTF-16 string, then the length -** returned by this function includes the nul terminator character (two -** bytes) at the end of the UTF-16 string. -*/ -int sqlite3_column_bytes16(sqlite3_stmt *, int); - -/* -** The first parameter is a compiled SQL statement for which the most -** recent call to sqlite3_step() has returned SQLITE_ROW. This routine -** retrieves the value of the Nth column of the current row, where -** N is the second function parameter as an integer. -** -** SQLITE3_NULL 0 -** SQLITE3_INTEGER The integer value. -** SQLITE3_FLOAT The integer component of the real (2^63 if too large) -** SQLITE3_TEXT Integer conversion of string, or 0 -** SQLITE3_BLOB 0 -*/ -long long int sqlite3_column_int(sqlite3_stmt*,int); - -/* -** The first parameter is a compiled SQL statement for which the most -** recent call to sqlite3_step() has returned SQLITE_ROW. This routine -** retrieves the value of the Nth column of the current row, where -** N is the second function parameter as an integer. -** -** SQLITE3_NULL 0.0 -** SQLITE3_INTEGER The value of the integer. Some rounding may occur. -** SQLITE3_FLOAT The value of the float. -** SQLITE3_TEXT Real number conversion of string, or 0.0 -** SQLITE3_BLOB 0.0 -*/ -double sqlite3_column_float(sqlite3_stmt*,int); +void *sqlite3_column_blob(sqlite3_stmt*, int iCol) +int sqlite3_column_bytes(sqlite3_stmt*, int iCol) +int sqlite3_column_bytes16(sqlite3_stmt*, int iCol) +double sqlite3_column_double(sqlite3_stmt*, int iCol) +int sqlite3_column_int(sqlite3_stmt*, int iCol) +long long int sqlite3_column_int64(sqlite3_stmt*, int iCol) +const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol) +const void *sqlite3_column_text16(sqlite3_stmt*, int iCol) +int sqlite3_column_type(sqlite3_stmt*, int iCol); /* ** The sqlite3_finalize() function is called to delete a compiled @@ -1131,78 +901,24 @@ int sqlite3_create_function16( */ int sqlite3_aggregate_count(sqlite3_context*); - /* -** Return the type of the sqlite3_value* passed as the first argument. -** The type is one of SQLITE3_NULL, SQLITE3_INTEGER, SQLITE3_FLOAT, -** SQLITE3_TEXT or SQLITE3_BLOB. +** The next group of routines returns information about parameters to +** a user-defined function. Function implementations use these routines +** to access their parameters. These routines are the same as the +** sqlite3_column_* routines except that these routines take a single +** sqlite3_value* pointer instead of an sqlite3_stmt* and an integer +** column number. */ +void *sqlite3_value_blob(sqlite3_value*) +int sqlite3_value_bytes(sqlite3_value*) +int sqlite3_value_bytes16(sqlite3_value*) +double sqlite3_value_double(sqlite3_value*) +int sqlite3_value_int(sqlite3_value*) +long long int sqlite3_value_int64(sqlite3_value*) +const unsigned char *sqlite3_value_text(sqlite3_value*) +const void *sqlite3_value_text16(sqlite3_value*) int sqlite3_value_type(sqlite3_value*); -/* -** Return the value of the sqlite3_value* passed as the first argument. -** The value returned depends on the type of the value, as returned by -** sqlite3_value_type(): -** -** SQLITE3_NULL A Null pointer. -** SQLITE3_INTEGER String representation of the integer, UTF-8 encoded. -** SQLITE3_FLOAT String representation of the real, UTF-8 encoded. -** SQLITE3_TEXT The string UTF-8 encoded. -** SQLITE3_BLOB A pointer to the blob of data. -*/ -const unsigned char *sqlite3_value_data(sqlite3_value*); - -/* -** Return the number of bytes in the string or blob returned by a call -** to sqlite3_value_data() on the same sqlite3_value* object. -*/ -int sqlite3_value_bytes(sqlite3_value*); - -/* -** Return the value of the sqlite3_value* passed as the first argument. -** The value returned depends on the type of the value, as returned by -** sqlite3_value_type(): -** -** SQLITE3_NULL A Null pointer. -** SQLITE3_INTEGER String representation of the integer, UTF-16 encoded. -** SQLITE3_FLOAT String representation of the real, UTF-16 encoded. -** SQLITE3_TEXT The string UTF-16 encoded. -** SQLITE3_BLOB A pointer to the blob of data. -*/ -const void *sqlite3_value_data16(sqlite3_value*); - -/* -** Return the number of bytes in the string or blob returned by a call -** to sqlite3_value_data16() on the same sqlite3_value* object. -*/ -int sqlite3_value_bytes16(sqlite3_value*); - -/* -** Return the value of the sqlite3_value* passed as the first argument. -** The value returned depends on the type of the value, as returned by -** sqlite3_value_type(): -** -** SQLITE3_NULL 0 -** SQLITE3_INTEGER The integer value. -** SQLITE3_FLOAT The integer component of the real (2^63 if too large) -** SQLITE3_TEXT Integer conversion of string, or 0 -** SQLITE3_BLOB 0 -*/ -long long int sqlite3_value_int(sqlite3_value*); - -/* -** Return the value of the sqlite3_value* passed as the first argument. -** The value returned depends on the type of the value, as returned by -** sqlite3_value_type(): -** -** SQLITE3_NULL 0.0 -** SQLITE3_INTEGER The value of the integer. Some rounding may occur. -** SQLITE3_FLOAT The value of the float. -** SQLITE3_TEXT Real number conversion of string, or 0.0 -** SQLITE3_BLOB 0.0 -*/ -double sqlite3_value_float(sqlite3_value*); - /* ** Aggregate functions use the following routine to allocate ** a structure for storing their state. The first time this routine @@ -1213,7 +929,7 @@ double sqlite3_value_float(sqlite3_value*); ** ** The buffer allocated is freed automatically by SQLite. */ -void *sqlite3_get_context(sqlite3_context*, int nBytes); +void *sqlite3_aggregate_context(sqlite3_context*, int nBytes); /* ** The pUserData parameter to the sqlite3_create_function() and @@ -1224,89 +940,19 @@ void *sqlite3_get_context(sqlite3_context*, int nBytes); void *sqlite3_user_data(sqlite3_context*); /* -** The following three functions may be called from within a user-defined -** function callback or a user-defined aggregate finalizer callback. The -** result of the user-defined function or aggregate is set to the value of -** the second parameter. Any value previously set as the return value via -** an sqlite3_result_*() call is overwritten. -** -** The first parameter to each of these routines must be a copy of the -** sqlite3_context* pointer passed to the user-defined function or -** aggregate finalizer function. -*/ -void sqlite3_result_int32(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, long long int); -void sqlite3_result_double(sqlite3_context*, double); - -/* -** This function may be called from within a user-defined function callback -** or a user-defined aggregate finalizer callback. The result of the -** user-defined function or aggregate is set to NULL. Any value previously -** set as the return value via an sqlite3_result_*() call is overwritten. -** -** The parameter to this routine must be a copy of the sqlite3_context* -** pointer passed to the user-defined function or aggregate finalizer -** function. -*/ -void sqlite3_result_null(sqlite3_context*); - -/* -** The following two functions may be called from within a user-defined or -** a user-defined aggregate finalizer callback to return a text value. -** The second parameter is a pointer to the string, encoded in UTF-8 -** for sqlite3_result_text() and UTF-16 (machine byte order) for -** sqlite3_result_text16(). -** -** If the third parameter, n, is positive, it is the number of bytes (not -** characters) in the string data. A negative n value indicates that the -** string may be read up to the nul terminator character. -** -** If the fourth parameter is non-zero, then a copy is made of the string. -** Otherwise, SQLite stores a pointer to the original string data. -** -** The first parameter to this routine must be a copy of the -** sqlite3_context* pointer passed to the user-defined function or -** aggregate finalizer function. -*/ -void sqlite3_result_text(sqlite3_context*, const char*, int n, int eCopy); -void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy); - -/* -** The following function may be called from within a user-defined or a -** user-defined aggregate finalizer callback to return a blob value. The -** second parameter is a pointer to the blob of data. The third parameter -** is the number of bytes of data in the blob. -** -** If the fourth parameter is non-zero, then a copy is made of the blob. -** Otherwise, SQLite stores a pointer to the original blob data. -** -** The first parameter to this routine must be a copy of the -** sqlite3_context* pointer passed to the user-defined function or -** aggregate finalizer function. +** User-defined functions invoke the following routines in order to +** set their return value. */ void sqlite3_result_blob(sqlite3_context*, const void*, int n, int eCopy); - -/* -** These routines are used from within a user-defined or a user-defined -** aggregate finalizer callback to return an error. The second parameter -** is a pointer to a string describing the error, or NULL if no explanation -** is provided. -** -** The string should be encoded in UTF-8 for sqlite3_result_error() and -** UTF-16 (machine byte order) for sqlite3_result_error16(). -** -** If not negative, the third parameter is the number of bytes (not -** characters) in the string passed as the second argument. If the third -** parameter is negative, then the string is read up to the first nul -** terminator character. -*/ +void sqlite3_result_double(sqlite3_context*, double); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); - -/* -** Copy a function parameter into the result of the function. -*/ -void sqlite3_result(sqlite3_context*, sqlite3_value*); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, long long int); +void sqlite3_result_null(sqlite3_context*); +void sqlite3_result_text(sqlite3_context*, const char*, int n, int eCopy); +void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy); +void sqlite3_result_value(sqlite3_context*, sqlite3_value*); #ifdef __cplusplus } /* End of the 'extern "C"' block */ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index a1a1a44c91..33355ba2b0 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.72 2004/05/26 16:54:46 drh Exp $ +** $Id: tclsqlite.c,v 1.73 2004/05/26 23:25:31 drh Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -391,7 +391,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value **argv) if( SQLITE3_NULL==sqlite3_value_type(argv[i]) ){ Tcl_DStringAppendElement(&cmd, ""); }else{ - Tcl_DStringAppendElement(&cmd, sqlite3_value_data(argv[i])); + Tcl_DStringAppendElement(&cmd, sqlite3_value_text(argv[i])); } } rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd)); diff --git a/src/test1.c b/src/test1.c index e695cce5f3..c09ced4cd8 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.58 2004/05/26 13:27:00 danielk1977 Exp $ +** $Id: test1.c,v 1.59 2004/05/26 23:25:31 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -300,7 +300,7 @@ static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv) int i; for(i=0; in++; } } static void countFinalize(sqlite3_context *context){ CountCtx *p; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); sqlite3_result_int32(context, p ? p->n : 0); } @@ -645,8 +645,8 @@ static int sqlite_abort( */ static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ while( argc>=2 ){ - const char *zArg0 = sqlite3_value_data(argv[0]); - const char *zArg1 = sqlite3_value_data(argv[1]); + const char *zArg0 = sqlite3_value_text(argv[0]); + const char *zArg1 = sqlite3_value_text(argv[1]); if( zArg0==0 ){ sqlite3_result_error(context, "first argument to test function " "may not be NULL", -1); @@ -1316,11 +1316,11 @@ static int test_step( } /* -** Usage: sqlite3_column_data STMT column +** Usage: sqlite3_column_text STMT column ** ** Advance the statement to the next row. */ -static int test_column_data( +static int test_column_text( void * clientData, Tcl_Interp *interp, int objc, @@ -1341,9 +1341,9 @@ static int test_column_data( if( SQLITE3_BLOB==sqlite3_column_type(pStmt, col) ){ int len = sqlite3_column_bytes(pStmt, col); - pRet = Tcl_NewByteArrayObj(sqlite3_column_data(pStmt, col), len); + pRet = Tcl_NewByteArrayObj(sqlite3_column_text(pStmt, col), len); }else{ - pRet = Tcl_NewStringObj(sqlite3_column_data(pStmt, col), -1); + pRet = Tcl_NewStringObj(sqlite3_column_text(pStmt, col), -1); } Tcl_SetObjResult(interp, pRet); @@ -1351,11 +1351,11 @@ static int test_column_data( } /* -** Usage: sqlite3_column_data16 STMT column +** Usage: sqlite3_column_text16 STMT column ** ** Advance the statement to the next row. */ -static int test_column_data16( +static int test_column_text16( void * clientData, Tcl_Interp *interp, int objc, @@ -1376,7 +1376,7 @@ static int test_column_data16( if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; len = sqlite3_column_bytes16(pStmt, col); - pRet = Tcl_NewByteArrayObj(sqlite3_column_data16(pStmt, col), len); + pRet = Tcl_NewByteArrayObj(sqlite3_column_text16(pStmt, col), len); Tcl_SetObjResult(interp, pRet); return TCL_OK; @@ -1663,8 +1663,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_finalize", (Tcl_ObjCmdProc*)test_finalize }, { "sqlite3_reset", (Tcl_ObjCmdProc*)test_reset }, { "sqlite3_step", (Tcl_ObjCmdProc*)test_step}, - { "sqlite3_column_data", (Tcl_ObjCmdProc*)test_column_data }, - { "sqlite3_column_data16", (Tcl_ObjCmdProc*)test_column_data16 }, + { "sqlite3_column_text", (Tcl_ObjCmdProc*)test_column_text }, + { "sqlite3_column_text16", (Tcl_ObjCmdProc*)test_column_text16 }, { "sqlite3_column_count", (Tcl_ObjCmdProc*)test_column_count }, { "sqlite3_column_name", (Tcl_ObjCmdProc*)test_column_name }, { "sqlite3_column_name16", (Tcl_ObjCmdProc*)test_column_name16 }, diff --git a/src/test4.c b/src/test4.c index 054e578af8..46d6e3c4fa 100644 --- a/src/test4.c +++ b/src/test4.c @@ -11,7 +11,7 @@ ************************************************************************* ** Code for testing the the SQLite library in a multithreaded environment. ** -** $Id: test4.c,v 1.7 2004/05/26 02:04:57 danielk1977 Exp $ +** $Id: test4.c,v 1.8 2004/05/26 23:25:31 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -498,7 +498,7 @@ static void do_step(Thread *p){ if( p->rc==SQLITE_ROW ){ p->argc = sqlite3_column_count(p->pStmt); for(i=0; ipStmt); i++){ - p->argv[i] = sqlite3_column_data(p->pStmt, i); + p->argv[i] = sqlite3_column_text(p->pStmt, i); } for(i=0; iargc; i++){ p->colv[i] = sqlite3_column_name(p->pStmt, i); @@ -648,6 +648,3 @@ int Sqlitetest4_Init(Tcl_Interp *interp){ #else int Sqlitetest4_Init(Tcl_Interp *interp){ return TCL_OK; } #endif /* OS_UNIX */ - - - diff --git a/src/vdbe.c b/src/vdbe.c index 2b8e2822ed..c5f75a9daa 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.335 2004/05/26 16:54:47 drh Exp $ +** $Id: vdbe.c,v 1.336 2004/05/26 23:25:31 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -75,122 +75,8 @@ int sqlite3_interrupt_count = 0; ** TEXT_Utf16le or TEXT_Utf16be. */ #define MemEnc(p) ( \ - p->flags&MEM_Utf16le?TEXT_Utf16le: \ - (p->flags&MEM_Utf16le?TEXT_Utf16be:TEXT_Utf8) ) - -/* -** The following macros each take one parameter, a pointer to a Mem -** structure. The value returned is non-zero if the value stored in -** the Mem structure is of or can be losslessly converted to the -** type implicit in the macro name. -** -** MemIsNull # NULL values -** MemIsInt # Ints and reals and strings that can be converted to ints. -** MemIsReal # Reals, ints and strings that look like numbers -** MemIsStr # Strings, reals and ints. -** MemIsBlob # Blobs. -** -** These macros do not alter the contents of the Mem structure. -*/ -#define MemIsNull(p) ((p)->flags&Mem_Null) -#define MemIsBlob(p) ((p)->flags&Mem_Blob) -#define MemIsStr(p) ((p)->flags&(MEM_Int|MEM_Real|MEM_Str)) -#define MemIsInt(p) ((p)->flags&(MEM_Int|MEM_Real) || hardMemIsInt(p)) -#define MemIsReal(p) ((p)->flags&(MEM_Int|MEM_Real) || hardMemIsReal(p)) -static int hardMemIsInt(Mem *p){ - assert( !(p->flags&(MEM_Int|MEM_Real)) ); - if( p->flags&MEM_Str ){ - int realnum = 0; - if( sqlite3IsNumber(p->z, &realnum, MemEnc(p)) && !realnum ){ - return 1; - } - } - return 0; -} -static int hardMemIsReal(Mem *p){ - assert( !(p->flags&(MEM_Int|MEM_Real)) ); - if( p->flags&MEM_Str && sqlite3IsNumber(p->z, 0, MemEnc(p)) ){ - return 1; - } - return 0; -} - -/* -** The following two macros each take one parameter, a pointer to a Mem -** structure. They return the value stored in the Mem structure coerced -** to a 64-bit integer or real, respectively. -** -** MemInt -** MemReal -** -** These macros do not alter the contents of the Mem structure, although -** they may cache the integer or real value cast of the value. -*/ -#define MemInt(p) (((p)->flags&MEM_Int)?(p)->i:hardMemInt(p)) -#define MemReal(p) (((p)->flags&MEM_Real)?(p)->r:hardMemReal(p)) -static i64 hardMemInt(Mem *p){ - assert( !(p->flags&MEM_Int) ); - if( !MemIsInt(p) ) return 0; - - if( p->flags&MEM_Real ){ - p->i = p->r; - }else{ - assert( p->flags&MEM_Str ); - sqlite3atoi64(p->z, &(p->i), MemEnc(p)); - } - p->flags |= MEM_Int; - return p->i; -} -static double hardMemReal(Mem *p){ - assert( !(p->flags&MEM_Real) ); - if( !MemIsReal(p) ) return 0.0; - - if( p->flags&MEM_Int ){ - p->r = p->i; - }else{ - assert( p->flags&MEM_Str ); - /* p->r = sqlite3AtoF(p->z, 0, MemEnc(p)); */ - p->r = sqlite3AtoF(p->z, 0); - } - p->flags |= MEM_Real; - return p->r; -} - - -#if 0 -/* -** MemStr(Mem *pMem) -** MemBlob(Mem *pMem) -** MemBloblen(Mem *pMem) -** -** MemType(Mem *pMem) -** -** MemSetBlob -** MemSetStr -** -** MemSetEnc -** MemSetType -** -** MemCopy -*/ -struct MemRecord { - char *zData; /* Serialized record */ - int nField; /* Number of fields in the header */ - int nHeader; /* Number of bytes in the entire header */ - u64 *aType; /* Type values for all entries in the record */ -}; -typedef struct MemRecord MemRecord; - -/* -** Transform the value stored in pMem, which must be a blob into a -** MemRecord. An Mem cell used to store a MemRecord works as follows: -** -** Mem.z points at a MemRecord struct -*/ -static int Recordify(Mem *pMem){ - return 0; -} -#endif + ((p)->flags&MEM_Utf16le)?TEXT_Utf16le: \ + ((p)->flags&MEM_Utf16be)?TEXT_Utf16be:TEXT_Utf8) ) /* ** Release the memory associated with the given stack level. This @@ -223,7 +109,7 @@ static u8 flagsToEnc(int flags){ */ static int encToFlags(u8 enc){ switch( enc ){ - case TEXT_Utf8: return MEM_Utf8; + case TEXT_Utf8: return MEM_Utf8; case TEXT_Utf16be: return MEM_Utf16be; case TEXT_Utf16le: return MEM_Utf16le; } @@ -239,24 +125,12 @@ static int encToFlags(u8 enc){ ((pMem->flags & ~(MEM_Utf8|MEM_Utf16le|MEM_Utf16be))) | encToFlags(enc)) static int SetEncoding(Mem*, int); -/* -** Set the MEM_TypeStr, MEM_TypeReal or MEM_TypeInt flags in pMem if -** required. -*/ -static void MemSetTypeFlags(Mem *pMem){ - int f = pMem->flags; - if( f&MEM_Int ) pMem->flags |= MEM_TypeInt; - else if( f&MEM_Real ) pMem->flags |= MEM_TypeReal; - else if( f&MEM_Str ) pMem->flags |= MEM_TypeStr; -} - - /* ** Convert the given stack entity into a string if it isn't one ** already. Return non-zero if a malloc() fails. */ #define Stringify(P, enc) \ -if( !((P)->flags&(MEM_Str|MEM_Blob)) ) hardStringify(P, enc); +(!((P)->flags&(MEM_Str|MEM_Blob)) && hardStringify(P, enc)) static int hardStringify(Mem *pStack, u8 enc){ int rc = SQLITE_OK; int fg = pStack->flags; @@ -344,125 +218,6 @@ static int hardDeephem(Mem *pStack){ return 0; } -/* -** If pMem is a string object, this routine sets the encoding of the string -** (to one of UTF-8 or UTF16) and whether or not the string is -** nul-terminated. If pMem is not a string object, then this routine is -** a no-op. -** -** The second argument, "flags" consists of one of MEM_Utf8, MEM_Utf16le -** or MEM_Utf16be, possible ORed with MEM_Term. If necessary this function -** manipulates the value stored by pMem so that it matches the flags passed -** in "flags". -** -** SQLITE_OK is returned if the conversion is successful (or not required). -** SQLITE_NOMEM may be returned if a malloc() fails during conversion -** between formats. -*/ -int SetEncoding(Mem *pMem, int flags){ - u8 enc1; /* Current string encoding (TEXT_Utf* value) */ - u8 enc2; /* Required string encoding (TEXT_Utf* value) */ - - /* If this is not a string, do nothing. */ - if( !(pMem->flags&MEM_Str) ){ - return SQLITE_OK; - } - - enc1 = flagsToEnc(pMem->flags); - enc2 = flagsToEnc(flags); - - if( enc1!=enc2 ){ - if( enc1==TEXT_Utf8 || enc2==TEXT_Utf8 ){ - /* If the current encoding does not match the desired encoding, then - ** we will need to do some translation between encodings. - */ - char *z; - int n; - int rc = sqlite3utfTranslate(pMem->z,pMem->n,enc1,(void **)&z,&n,enc2); - if( rc!=SQLITE_OK ){ - return rc; - } - - /* Result of sqlite3utfTranslate is currently always dynamically - ** allocated and nul terminated. This might be altered as a performance - ** enhancement later. - */ - pMem->z = z; - pMem->n = n; - pMem->flags &= ~(MEM_Utf8|MEM_Utf16le|MEM_Utf16be); - pMem->flags &= ~(MEM_Static|MEM_Short|MEM_Ephem); - pMem->flags |= (MEM_Dyn|MEM_Term|flags); - }else{ - /* Must be translating between UTF-16le and UTF-16be. */ - int i; - if( pMem->flags&MEM_Static ){ - Dynamicify(pMem, enc1); - } - for(i=0; in; i+=2){ - char c = pMem->z[i]; - pMem->z[i] = pMem->z[i+1]; - pMem->z[i+1] = c; - } - SetEncodingFlags(pMem, enc2); - } - } - - if( (flags&MEM_Term) && !(pMem->flags&MEM_Term) ){ - /* If we did not do any translation, but currently the string is - ** not nul terminated (and is required to be), then we add the - ** nul terminator now. We never have to do this if we translated - ** the encoding of the string, as the translation functions return - ** nul terminated values. - */ - int f = pMem->flags; - int nulTermLen = 2; /* The number of 0x00 bytes to append */ - if( enc2==MEM_Utf8 ){ - nulTermLen = 1; - } - - if( pMem->n+nulTermLen<=NBFS ){ - /* If the string plus the nul terminator will fit in the Mem.zShort - ** buffer, and it is not already stored there, copy it there. - */ - if( !(f&MEM_Short) ){ - memcpy(pMem->z, pMem->zShort, pMem->n); - if( f&MEM_Dyn ){ - sqliteFree(pMem->z); - } - pMem->z = pMem->zShort; - pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Dyn); - pMem->flags |= MEM_Short; - } - }else{ - /* Otherwise we have to malloc for memory. If the string is already - ** dynamic, use sqliteRealloc(). Otherwise sqliteMalloc() enough - ** space for the string and the nul terminator, and copy the string - ** data there. - */ - if( f&MEM_Dyn ){ - pMem->z = (char *)sqliteRealloc(pMem->z, pMem->n+nulTermLen); - if( !pMem->z ){ - return SQLITE_NOMEM; - } - }else{ - char *z = (char *)sqliteMalloc(pMem->n+nulTermLen); - memcpy(z, pMem->z, pMem->n); - pMem->z = z; - pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short); - pMem->flags |= MEM_Dyn; - } - } - - /* pMem->z now points at the string data, with enough space at the end - ** to insert the nul nul terminator. pMem->n has not yet been updated. - */ - memcpy(&pMem->z[pMem->n], "\0\0", nulTermLen); - pMem->n += nulTermLen; - pMem->flags |= MEM_Term; - } - return SQLITE_OK; -} - /* ** Convert the given stack entity into a integer if it isn't one ** already. @@ -506,679 +261,6 @@ static void hardRealify(Mem *pStack, u8 enc){ pStack->flags = MEM_Real; } -/* -** Execute the statement pStmt, either until a row of data is ready, the -** statement is completely executed or an error occurs. -*/ -int sqlite3_step(sqlite3_stmt *pStmt){ - Vdbe *p = (Vdbe*)pStmt; - sqlite *db; - int rc; - - if( p->magic!=VDBE_MAGIC_RUN ){ - return SQLITE_MISUSE; - } - db = p->db; - if( sqlite3SafetyOn(db) ){ - p->rc = SQLITE_MISUSE; - return SQLITE_MISUSE; - } - if( p->explain ){ - rc = sqlite3VdbeList(p); - }else{ - rc = sqlite3VdbeExec(p); - } - - if( sqlite3SafetyOff(db) ){ - rc = SQLITE_MISUSE; - } - - sqlite3Error(p->db, rc, p->zErrMsg); - return rc; -} - -/* -** Return the number of columns in the result set for the statement pStmt. -*/ -int sqlite3_column_count(sqlite3_stmt *pStmt){ - Vdbe *pVm = (Vdbe *)pStmt; - return pVm->nResColumn; -} - -/* -** Return the number of values available from the current row of the -** currently executing statement pStmt. -*/ -int sqlite3_data_count(sqlite3_stmt *pStmt){ - Vdbe *pVm = (Vdbe *)pStmt; - if( !pVm->resOnStack ) return 0; - return pVm->nResColumn; -} - -/* -** Return the value of the 'i'th column of the current row of the currently -** executing statement pStmt. -*/ -const unsigned char *sqlite3_column_data(sqlite3_stmt *pStmt, int i){ - int vals; - Vdbe *pVm = (Vdbe *)pStmt; - Mem *pVal; - - vals = sqlite3_data_count(pStmt); - if( i>=vals || i<0 ){ - sqlite3Error(pVm->db, SQLITE_RANGE, 0); - return 0; - } - - pVal = &pVm->pTos[(1-vals)+i]; - return sqlite3_value_data((sqlite3_value *)pVal); -} - -/* -** pVal is a Mem* cast to an sqlite_value* value. Return a pointer to -** the nul terminated UTF-8 string representation if the value is -** not a blob or NULL. If the value is a blob, then just return a pointer -** to the blob of data. If it is a NULL, return a NULL pointer. -** -** This function may translate the encoding of the string stored by -** pVal. The MEM_Utf8, MEM_Utf16le and MEM_Utf16be flags must be set -** correctly when this function is called. If a translation occurs, -** the flags are set to reflect the new encoding of the string. -** -** If a translation fails because of a malloc() failure, a NULL pointer -** is returned. -*/ -const unsigned char *sqlite3_value_data(sqlite3_value *pVal){ - int flags = pVal->flags; - - if( flags&MEM_Null ){ - /* For a NULL return a NULL Pointer */ - return 0; - } - - if( flags&MEM_Str ){ - /* If there is already a string representation, make sure it is in - ** encoded in UTF-8. - */ - SetEncoding(pVal, MEM_Utf8|MEM_Term); - }else if( !(flags&MEM_Blob) ){ - if( flags&MEM_Int ){ - sqlite3_snprintf(NBFS, pVal->zShort, "%lld", pVal->i); - }else{ - assert( flags&MEM_Real ); - sqlite3_snprintf(NBFS, pVal->zShort, "%.15g", pVal->r); - } - pVal->z = pVal->zShort; - pVal->n = strlen(pVal->z)+1; - pVal->flags |= (MEM_Str|MEM_Short); - } - - return pVal->z; -} - -/* -** pVal is a Mem* cast to an sqlite_value* value. Return a pointer to -** the nul terminated UTF-16 string representation if the value is -** not a blob or NULL. If the value is a blob, then just return a pointer -** to the blob of data. If it is a NULL, return a NULL pointer. -** -** The byte-order of the returned string data is the machines native byte -** order. -** -** This function may translate the encoding of the string stored by -** pVal. The MEM_Utf8, MEM_Utf16le and MEM_Utf16be flags must be set -** correctly when this function is called. If a translation occurs, -** the flags are set to reflect the new encoding of the string. -** -** If a translation fails because of a malloc() failure, a NULL pointer -** is returned. -*/ -const void *sqlite3_value_data16(sqlite3_value* pVal){ - if( pVal->flags&MEM_Null ){ - /* For a NULL return a NULL Pointer */ - return 0; - } - - if( pVal->flags&MEM_Str ){ - /* If there is already a string representation, make sure it is in - ** encoded in UTF-16 machine byte order. - */ - SetEncoding(pVal, encToFlags(TEXT_Utf16)|MEM_Term); - }else if( !(pVal->flags&MEM_Blob) ){ - sqlite3_value_data(pVal); - SetEncoding(pVal, encToFlags(TEXT_Utf16)|MEM_Term); - } - - return (const void *)(pVal->z); -} - -/* -** Return the value of the 'i'th column of the current row of the currently -** executing statement pStmt. -*/ -const void *sqlite3_column_data16(sqlite3_stmt *pStmt, int i){ - int vals; - Vdbe *pVm = (Vdbe *)pStmt; - Mem *pVal; - - vals = sqlite3_data_count(pStmt); - if( i>=vals || i<0 ){ - sqlite3Error(pVm->db, SQLITE_RANGE, 0); - return 0; - } - - pVal = &pVm->pTos[(1-vals)+i]; - return sqlite3_value_data16((sqlite3_value *)pVal); -} - -/* -** Return the number of bytes of data that will be returned by the -** equivalent sqlite3_value_data() call. -*/ -int sqlite3_value_bytes(sqlite3_value *pVal){ - if( sqlite3_value_data(pVal) ){ - return ((Mem *)pVal)->n; - } - return 0; -} - -/* -** Return the number of bytes of data that will be returned by the -** equivalent sqlite3_value_data16() call. -*/ -int sqlite3_value_bytes16(sqlite3_value *pVal){ - if( sqlite3_value_data16(pVal) ){ - return ((Mem *)pVal)->n; - } - return 0; -} - -/* -** Return the value of the sqlite_value* argument coerced to a 64-bit -** integer. -*/ -long long int sqlite3_value_int(sqlite3_value *pVal){ - Mem *pMem = (Mem *)pVal; - return MemInt(pMem); -} - -/* -** Return the value of the sqlite_value* argument coerced to a 64-bit -** IEEE float. -*/ -double sqlite3_value_float(sqlite3_value *pVal){ - Mem *pMem = (Mem *)pVal; - return MemReal(pMem); -} - -/* -** Return the number of bytes of data that will be returned by the -** equivalent sqlite3_column_data() call. -*/ -int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ - Vdbe *pVm = (Vdbe *)pStmt; - - if( sqlite3_column_data(pStmt, i) ){ - int vals = sqlite3_data_count(pStmt); - return pVm->pTos[(1-vals)+i].n; - } - return 0; -} - -/* -** Return the number of bytes of data that will be returned by the -** equivalent sqlite3_column_data16() call. -*/ -int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ - Vdbe *pVm = (Vdbe *)pStmt; - - if( sqlite3_column_data16(pStmt, i) ){ - int vals = sqlite3_data_count(pStmt); - return pVm->pTos[(1-vals)+i].n; - } - return 0; -} - -/* -** Return the value of the 'i'th column of the current row of the currently -** executing statement pStmt. -*/ -long long int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ - int vals; - Vdbe *pVm = (Vdbe *)pStmt; - Mem *pVal; - - vals = sqlite3_data_count(pStmt); - if( i>=vals || i<0 ){ - sqlite3Error(pVm->db, SQLITE_RANGE, 0); - return 0; - } - - pVal = &pVm->pTos[(1-vals)+i]; - return sqlite3_value_int(pVal); -} - -/* -** Return the value of the 'i'th column of the current row of the currently -** executing statement pStmt. -*/ -double sqlite3_column_float(sqlite3_stmt *pStmt, int i){ - int vals; - Vdbe *pVm = (Vdbe *)pStmt; - Mem *pVal; - - vals = sqlite3_data_count(pStmt); - if( i>=vals || i<0 ){ - sqlite3Error(pVm->db, SQLITE_RANGE, 0); - return 0; - } - - pVal = &pVm->pTos[(1-vals)+i]; - return sqlite3_value_float(pVal); -} - -/* -** Return the name of the Nth column of the result set returned by SQL -** statement pStmt. -*/ -const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ - Vdbe *p = (Vdbe *)pStmt; - Mem *pColName; - - if( N>=sqlite3_column_count(pStmt) || N<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - return 0; - } - - pColName = &(p->aColName[N]); - return sqlite3_value_data(pColName); -} - -/* -** Return the name of the 'i'th column of the result set of SQL statement -** pStmt, encoded as UTF-16. -*/ -const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ - Vdbe *p = (Vdbe *)pStmt; - Mem *pColName; - - if( N>=sqlite3_column_count(pStmt) || N<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - return 0; - } - - pColName = &(p->aColName[N]); - return sqlite3_value_data16(pColName); -} - - -/* -** Return the type of the value stored in the sqlite_value* object. -*/ -int sqlite3_value_type(sqlite3_value* pVal){ - int f = ((Mem *)pVal)->flags; - if( f&MEM_Null ){ - return SQLITE3_NULL; - } - if( f&MEM_TypeInt ){ - return SQLITE3_INTEGER; - } - if( f&MEM_TypeReal ){ - return SQLITE3_FLOAT; - } - if( f&MEM_TypeStr ){ - return SQLITE3_TEXT; - } - if( f&MEM_Blob ){ - return SQLITE3_BLOB; - } - assert(0); -} - -/* -** Return the type of the 'i'th column of the current row of the currently -** executing statement pStmt. -*/ -int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ - int vals; - Vdbe *p = (Vdbe *)pStmt; - - vals = sqlite3_data_count(pStmt); - if( i>=vals || i<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - return 0; - } - - return sqlite3_value_type(&(p->pTos[(1-vals)+i])); -} - -/* -** This routine returns either the column name, or declaration type (see -** sqlite3_column_decltype16() ) of the 'i'th column of the result set of -** SQL statement pStmt. The returned string is UTF-16 encoded. -** -** The declaration type is returned if 'decltype' is true, otherwise -** the column name. -*/ -static const void *columnName16(sqlite3_stmt *pStmt, int i, int decltype){ - Vdbe *p = (Vdbe *)pStmt; - - if( i>=sqlite3_column_count(pStmt) || i<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - return 0; - } - - if( decltype ){ - i += p->nResColumn; - } - - if( !p->azColName16 ){ - p->azColName16 = (void **)sqliteMalloc(sizeof(void *)*p->nResColumn*2); - if( !p->azColName16 ){ - sqlite3Error(p->db, SQLITE_NOMEM, 0); - return 0; - } - } - if( !p->azColName16[i] ){ - if( SQLITE3_BIGENDIAN ){ - p->azColName16[i] = sqlite3utf8to16be(p->azColName[i], -1); - } - if( !p->azColName16[i] ){ - sqlite3Error(p->db, SQLITE_NOMEM, 0); - return 0; - } - } - return p->azColName16[i]; -} - -/* -** Return the column declaration type (if applicable) of the 'i'th column -** of the result set of SQL statement pStmt, encoded as UTF-8. -*/ -const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int i){ - Vdbe *p = (Vdbe *)pStmt; - - if( i>=sqlite3_column_count(pStmt) || i<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - return 0; - } - - return p->azColName[i+p->nResColumn]; -} - -/* -** Return the column declaration type (if applicable) of the 'i'th column -** of the result set of SQL statement pStmt, encoded as UTF-16. -*/ -const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int i){ - return columnName16(pStmt, i, 1); -} - -/* -** Unbind the value bound to variable $i in virtual machine p. This is the -** the same as binding a NULL value to the column. If the "i" parameter is -** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. -** -** The error code stored in database p->db is overwritten with the return -** value in any case. -*/ -static int vdbeUnbind(Vdbe *p, int i){ - Mem *pVar; - if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 ){ - sqlite3Error(p->db, SQLITE_MISUSE, 0); - return SQLITE_MISUSE; - } - if( i<1 || i>p->nVar ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); - return SQLITE_RANGE; - } - i--; - pVar = &p->apVar[i]; - if( pVar->flags&MEM_Dyn ){ - sqliteFree(pVar->z); - } - pVar->flags = MEM_Null; - sqlite3Error(p->db, SQLITE_OK, 0); - return SQLITE_OK; -} - -/* -** This routine is used to bind text or blob data to an SQL variable (a ?). -** It may also be used to bind a NULL value, by setting zVal to 0. Any -** existing value is unbound. -** -** The error code stored in p->db is overwritten with the return value in -** all cases. -*/ -static int vdbeBindBlob( - Vdbe *p, /* Virtual machine */ - int i, /* Var number to bind (numbered from 1 upward) */ - const char *zVal, /* Pointer to blob of data */ - int bytes, /* Number of bytes to copy */ - int copy, /* True to copy the memory, false to copy a pointer */ - int flags /* Valid combination of MEM_Blob, MEM_Str, MEM_Term */ -){ - Mem *pVar; - int rc; - - rc = vdbeUnbind(p, i); - if( rc!=SQLITE_OK ){ - return rc; - } - pVar = &p->apVar[i-1]; - - if( zVal ){ - pVar->n = bytes; - pVar->flags = flags; - if( !copy ){ - pVar->z = (char *)zVal; - pVar->flags |= MEM_Static; - }else{ - if( bytes>NBFS ){ - pVar->z = (char *)sqliteMalloc(bytes); - if( !pVar->z ){ - sqlite3Error(p->db, SQLITE_NOMEM, 0); - return SQLITE_NOMEM; - } - pVar->flags |= MEM_Dyn; - }else{ - pVar->z = pVar->zShort; - pVar->flags |= MEM_Short; - } - memcpy(pVar->z, zVal, bytes); - } - } - - return SQLITE_OK; -} - -/* -** Bind a 64 bit integer to an SQL statement variable. -*/ -int sqlite3_bind_int64(sqlite3_stmt *p, int i, long long int iValue){ - int rc; - Vdbe *v = (Vdbe *)p; - rc = vdbeUnbind(v, i); - if( rc==SQLITE_OK ){ - Mem *pVar = &v->apVar[i-1]; - pVar->flags = MEM_Int; - pVar->i = iValue; - } - return rc; -} - -/* -** Bind a 32 bit integer to an SQL statement variable. -*/ -int sqlite3_bind_int32(sqlite3_stmt *p, int i, int iValue){ - return sqlite3_bind_int64(p, i, (long long int)iValue); -} - -/* -** Bind a double (real) to an SQL statement variable. -*/ -int sqlite3_bind_double(sqlite3_stmt *p, int i, double iValue){ - int rc; - Vdbe *v = (Vdbe *)p; - rc = vdbeUnbind(v, i); - if( rc==SQLITE_OK ){ - Mem *pVar = &v->apVar[i-1]; - pVar->flags = MEM_Real; - pVar->r = iValue; - } - return SQLITE_OK; -} - -/* -** Bind a NULL value to an SQL statement variable. -*/ -int sqlite3_bind_null(sqlite3_stmt* p, int i){ - return vdbeUnbind((Vdbe *)p, i); -} - -/* -** Bind a UTF-8 text value to an SQL statement variable. -*/ -int sqlite3_bind_text( - sqlite3_stmt *pStmt, - int i, - const char *zData, - int nData, - int eCopy -){ - Mem *pVar; - Vdbe *p = (Vdbe *)pStmt; - int rc = SQLITE_OK; - u8 db_enc = p->db->enc; /* Text encoding of the database */ - - /* Unbind any previous variable value */ - rc = vdbeUnbind(p, i); - if( rc==SQLITE_OK ){ - pVar = &p->apVar[i-1]; - - if( !zData ){ - /* If zData is NULL, then bind an SQL NULL value */ - pVar->flags = MEM_Null; - }else{ - if( zData && nData<0 ){ - nData = strlen(zData) + 1; - } - pVar->z = (char *)zData; - pVar->n = nData; - pVar->flags = MEM_Utf8|MEM_Str|(zData[nData-1]?0:MEM_Term); - if( !eCopy || db_enc!=TEXT_Utf8 ){ - pVar->flags |= MEM_Static; - rc = SetEncoding(pVar, encToFlags(db_enc)|MEM_Term); - }else{ - pVar->flags |= MEM_Ephem; - Deephemeralize(pVar); - } - } - } - - sqlite3Error(p->db, rc, 0); - return rc; - -no_mem: - sqlite3Error(p->db, SQLITE_NOMEM, 0); - return SQLITE_NOMEM; -} - -/* -** Bind a UTF-16 text value to an SQL statement variable. -*/ -int sqlite3_bind_text16( - sqlite3_stmt *pStmt, - int i, - const void *zData, - int nData, - int eCopy -){ - Vdbe *p = (Vdbe *)pStmt; - Mem *pVar; - u8 db_enc = p->db->enc; /* Text encoding of the database */ - u8 txt_enc; - int null_term = 0; - int rc; - - rc = vdbeUnbind(p, i); - if( rc!=SQLITE_OK ){ - return rc; - } - pVar = &p->apVar[i-1]; - - /* If zData is NULL, then bind an SQL NULL value */ - if( !zData ){ - pVar->flags = MEM_Null; - return SQLITE_OK; - } - - if( db_enc==TEXT_Utf8 ){ - /* If the database encoding is UTF-8, then do a translation. */ - pVar->z = sqlite3utf16to8(zData, nData, SQLITE3_BIGENDIAN); - if( !pVar->z ) return SQLITE_NOMEM; - pVar->n = strlen(pVar->z)+1; - pVar->flags = MEM_Str|MEM_Term|MEM_Dyn; - return SQLITE_OK; - } - - /* There may or may not be a byte order mark at the start of the UTF-16. - ** Either way set 'txt_enc' to the TEXT_Utf16* value indicating the - ** actual byte order used by this string. If the string does happen - ** to contain a BOM, then move zData so that it points to the first - ** byte after the BOM. - */ - txt_enc = sqlite3UtfReadBom(zData, nData); - if( txt_enc ){ - zData = (void *)(((u8 *)zData) + 2); - }else{ - txt_enc = SQLITE3_BIGENDIAN?TEXT_Utf16be:TEXT_Utf16le; - } - - if( nData<0 ){ - nData = sqlite3utf16ByteLen(zData, -1) + 2; - null_term = 1; - }else if( nData>1 && !((u8*)zData)[nData-1] && !((u8*)zData)[nData-2] ){ - null_term = 1; - } - - if( db_enc==txt_enc && !eCopy ){ - /* If the byte order of the string matches the byte order of the - ** database and the eCopy parameter is not set, then the string can - ** be used without making a copy. - */ - pVar->z = (char *)zData; - pVar->n = nData; - pVar->flags = MEM_Str|MEM_Static|(null_term?MEM_Term:0); - }else{ - /* Make a copy. Swap the byte order if required */ - pVar->n = nData + (null_term?0:2); - pVar->z = sqliteMalloc(pVar->n); - pVar->flags = MEM_Str|MEM_Dyn|MEM_Term; - if( db_enc==txt_enc ){ - memcpy(pVar->z, zData, nData); - }else{ - swab(zData, pVar->z, nData); - } - pVar->z[pVar->n-1] = '\0'; - pVar->z[pVar->n-2] = '\0'; - } - - return SQLITE_OK; -} - -/* -** Bind a blob value to an SQL statement variable. -*/ -int sqlite3_bind_blob( - sqlite3_stmt *p, - int i, - const void *zData, - int nData, - int eCopy -){ - return vdbeBindBlob((Vdbe *)p, i, zData, nData, eCopy, MEM_Blob); -} /* @@ -1793,16 +875,6 @@ case OP_String: { pTos++; pTos->flags = 0; - if( z ){ - /* FIX ME: For now the code in expr.c always puts UTF-8 in P3. It - ** should transform text to the native encoding before doing so. - */ - MemSetStr(pTos, z, -1, TEXT_Utf8, 0); - SetEncoding(pTos, encToFlags(db->enc)|MEM_Term); - }else if( op==OP_String ){ - pTos->flags = MEM_Null; - } - /* If this is an OP_Real or OP_Integer opcode, set the pTos->r or pTos->i ** values respectively. */ @@ -1810,13 +882,34 @@ case OP_String: { assert( z ); assert( sqlite3IsNumber(z, 0, TEXT_Utf8) ); pTos->r = sqlite3AtoF(z, 0); - pTos->flags |= MEM_Real; + pTos->flags = MEM_Real; }else if( op==OP_Integer ){ + pTos->flags = MEM_Int; pTos->i = pOp->p1; if( pTos->i==0 && pOp->p3 ){ - sqlite3GetInt64(z, &pTos->i); + sqlite3GetInt64(pOp->p3, &pTos->i); } - pTos->flags |= MEM_Int; + } + + if( z ){ + /* FIX ME: For now the code in expr.c always puts UTF-8 in P3. It + ** should transform text to the native encoding before doing so. + */ + if( db->enc!=TEXT_Utf8 ){ + rc = sqlite3utfTranslate(z, -1, TEXT_Utf8, (void **)&pTos->z, + &pTos->n, db->enc); + if( rc!=SQLITE_OK ){ + assert( !pTos->z ); + goto abort_due_to_error; + } + pTos->flags |= MEM_Str | MEM_Dyn | MEM_Term; + }else{ + pTos->z = z; + pTos->n = strlen(z) + 1; + pTos->flags |= MEM_Str | MEM_Static | MEM_Term; + } + }else if( op==OP_String ){ + pTos->flags = MEM_Null; } break; @@ -2036,8 +1129,7 @@ case OP_Callback: { for(i=0; ip1; i++){ Mem *pVal = &pTos[0-i]; SetEncodingFlags(pVal, db->enc); - MemNulTerminate(pVal); - MemSetTypeFlags(pVal); + sqlite3VdbeMemNulTerminate(pVal); } p->resOnStack = 1; @@ -2288,7 +1380,6 @@ case OP_Function: { pArg = &pTos[1-n]; for(i=0; ienc); - MemSetTypeFlags(pArg); apVal[i] = pArg; } @@ -5636,9 +4727,8 @@ case OP_AggFunc: { assert( apVal || n==0 ); for(i=0; ienc); - MemSetTypeFlags(pRec); + apVal[i] = pRec; + SetEncodingFlags(pRec, db->enc); } i = pTos->i; assert( i>=0 && iagg.nMem ); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 733b333f6c..10b32f9eac 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -137,31 +137,6 @@ struct Mem { }; typedef struct Mem Mem; -/* -** The following three macros are used to set the value and manifest type -** stored by a Mem structure. -** -** MemSetNull - Set the value to NULL. -** MemSetInt - Set the value to an integer. -** MemSetReal - Set the value to a real. -** MemSetStr - Set the value to a string (or blob if enc==0). -*/ -#define MemSetNull(p) sqlite3VdbeMemSetNull(p) -#define MemSetInt(p,v) sqlite3VdbeMemSetInt(p,v) -#define MemSetReal(p,v) sqlite3VdbeMemSetReal(p,v) -#define MemSetStr(p,z,n,enc,eCopy) sqlite3VdbeMemSetStr(p,z,n,enc,eCopy) - -/* -** This macro is used to ensure a string stored in a Mem struct is NULL -** terminated. When used on an object that is not a string or is a nul -** terminated string this is a no-op. When used on a non-nul-terminated -** string a nul terminator character is appended. -** -** Non-zero is returned if a malloc() fails. -*/ -#define MemNulTerminate(p) \ -if( ((p)->flags&MEM_Str) && !((p)->flags&MEM_Term) ) sqlite3VdbeMemNulTerminate(p); - /* One or more of the following flags are set to indicate the valid ** representations of the value stored in the Mem struct. ** @@ -215,8 +190,8 @@ if( ((p)->flags&MEM_Str) && !((p)->flags&MEM_Term) ) sqlite3VdbeMemNulTerminate( ** When a user-defined function is called (see OP_Function), the Mem* ** objects that store the argument values for the function call are ** passed to the user-defined function routine cast to sqlite3_value*. -** The user routine may then call sqlite3_value_data() or -** sqlite3_value_data16() to request a UTF-8 or UTF-16 string. If the +** The user routine may then call sqlite3_value_text() or +** sqlite3_value_text16() to request a UTF-8 or UTF-16 string. If the ** string representation currently stored in Mem.z is not the requested ** encoding, then a translation occurs. To keep track of things, the ** MEM_Utf* flags are set correctly for the database encoding before a @@ -228,7 +203,7 @@ if( ((p)->flags&MEM_Str) && !((p)->flags&MEM_Term) ) sqlite3VdbeMemNulTerminate( ** internally as Mem* objects. Before sqlite3_step() returns, the MEM_Utf* ** flags are set correctly for the database encoding. A translation may ** take place if the user requests a non-native encoding via -** sqlite3_column_data() or sqlite3_column_data16(). If this occurs, then +** sqlite3_column_text() or sqlite3_column_text16(). If this occurs, then ** the MEM_Utf* flags are updated accordingly. */ #define MEM_Utf8 0x2000 /* String uses UTF-8 encoding */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c new file mode 100644 index 0000000000..1a5e86c65f --- /dev/null +++ b/src/vdbeapi.c @@ -0,0 +1,503 @@ +/* +** 2004 May 26 +** +** 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 contains code use to implement APIs that are part of the +** VDBE. +*/ +#include "sqliteInt.h" +#include "vdbeInt.h" + +/**************************** sqlite3_value_ ******************************* +** The following routines extract information from a Mem or sqlite3_value +** structure. +*/ +const void *sqlite3_value_blob(sqlite3_value *pVal){ + Mem *p = (Mem*)pVal; + if( p->flags & (MEM_Blob|MEM_Str) ){ + return p->z; + }else{ + return sqlite3_value_text(pVal); + } +} +int sqlite3_value_bytes(sqlite3_value *pVal){ + Mem *p = (Mem*)pVal; + if( (p->flags & MEM_Blob)!=0 || sqlite3_value_text(pVal) ){ + return p->n; + } + return 0; +} +int sqlite3_value_bytes16(sqlite3_value *pVal){ + Mem *p = (Mem*)pVal; + if( (p->flags & MEM_Blob)!=0 || sqlite3_value_text16(pVal) ){ + return ((Mem *)pVal)->n; + } + return 0; +} +double sqlite3_value_double(sqlite3_value *pVal){ + Mem *pMem = (Mem *)pVal; + Realify(pMem, flagsToEnc(pMem->flags)); + return pMem->r; +} +int sqlite3_value_int(sqlite3_value *pVal){ + Mem *pMem = (Mem *)pVal; + Integerify(pMem, flagsToEnc(pMem->flags)); + return (int)pVal->i; +} +long long int sqlite3_value_int64(sqlite3_value *pVal){ + Mem *pMem = (Mem *)pVal; + Integerify(pMem, flagsToEnc(pMem->flags)); + return pVal->i; +} +const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ + if( pVal->flags&MEM_Null ){ + /* For a NULL return a NULL Pointer */ + return 0; + } + + if( pVal->flags&MEM_Str ){ + /* If there is already a string representation, make sure it is in + ** encoded in UTF-8. + */ + SetEncoding(pVal, MEM_Utf8|MEM_Term); + }else if( !(pVal->flags&MEM_Blob) ){ + /* Otherwise, unless this is a blob, convert it to a UTF-8 string */ + Stringify(pVal, TEXT_Utf8); + } + + return pVal->z; +} +const void *sqlite3_value_text16(sqlite3_value* pVal){ + if( pVal->flags&MEM_Null ){ + /* For a NULL return a NULL Pointer */ + return 0; + } + + if( pVal->flags&MEM_Str ){ + /* If there is already a string representation, make sure it is in + ** encoded in UTF-16 machine byte order. + */ + SetEncoding(pVal, encToFlags(TEXT_Utf16)|MEM_Term); + }else if( !(pVal->flags&MEM_Blob) ){ + /* Otherwise, unless this is a blob, convert it to a UTF-16 string */ + Stringify(pVal, TEXT_Utf16); + } + + return (const void *)(pVal->z); +} +int sqlite3_value_type(sqlite3_value* pVal){ + int f = ((Mem *)pVal)->flags; + if( f&MEM_Null ){ + return SQLITE3_NULL; + } + if( f&MEM_Int ){ + return SQLITE3_INTEGER; + } + if( f&MEM_Real ){ + return SQLITE3_FLOAT; + } + if( f&MEM_Str ){ + return SQLITE3_TEXT; + } + if( f&MEM_Blob ){ + return SQLITE3_BLOB; + } + assert(0); +} + +/**************************** sqlite3_result_ ******************************* +** The following routines are used by user-defined functions to specify +** the function result. +*/ +void sqlite3_result_blob( + sqlite3_context *pCtx, + const void *z, + int n, + int eCopy +){ + assert( n>0 ); + MemSetStr(&pCtx->s, z, n, 0, eCopy); +} +void sqlite3_result_double(sqlite3_context *pCtx, double rVal){ + sqlite3VdbeMemSetDouble(&pCtx->s, rVal); +} +void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){ + pCtx->isError = 1; + sqlite3VdbeMemSetStr(&pCtx->s, z, n, TEXT_Utf8, 1); +} +void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ + pCtx->isError = 1; + sqlite3VdbeMemSetStr(&pCtx->s, z, n, TEXT_Utf16, 1); +} +void sqlite3_result_int32(sqlite3_context *pCtx, int iVal){ + sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal); +} +void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){ + sqlite3VdbeMemSetInt64(&pCtx->s, iVal); +} +void sqlite3_result_null(sqlite3_context *pCtx){ + sqilte3VdbeMemSetNull(&pCtx->s); +} +void sqlite3_result_text( + sqlite3_context *pCtx, + const char *z, + int n, + int eCopy +){ + MemSetStr(&pCtx->s, z, n, TEXT_Utf8, eCopy); +} +void sqlite3_result_text16( + sqlite3_context *pCtx, + const void *z, + int n, + int eCopy +){ + MemSetStr(&pCtx->s, z, n, TEXT_Utf16, eCopy); +} +void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){ + sqlite3VdbeMemCopy(&pCtx->s, pValue); +} + + +/* +** Execute the statement pStmt, either until a row of data is ready, the +** statement is completely executed or an error occurs. +*/ +int sqlite3_step(sqlite3_stmt *pStmt){ + Vdbe *p = (Vdbe*)pStmt; + sqlite *db; + int rc; + + if( p->magic!=VDBE_MAGIC_RUN ){ + return SQLITE_MISUSE; + } + db = p->db; + if( sqlite3SafetyOn(db) ){ + p->rc = SQLITE_MISUSE; + return SQLITE_MISUSE; + } + if( p->explain ){ + rc = sqlite3VdbeList(p); + }else{ + rc = sqlite3VdbeExec(p); + } + + if( sqlite3SafetyOff(db) ){ + rc = SQLITE_MISUSE; + } + + sqlite3Error(p->db, rc, p->zErrMsg); + return rc; +} + +/* +** Return the number of columns in the result set for the statement pStmt. +*/ +int sqlite3_column_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; + return pVm->nResColumn; +} + +/* +** Return the number of values available from the current row of the +** currently executing statement pStmt. +*/ +int sqlite3_data_count(sqlite3_stmt *pStmt){ + Vdbe *pVm = (Vdbe *)pStmt; + if( !pVm->resOnStack ) return 0; + return pVm->nResColumn; +} + + +/* +** Check to see if column iCol of the given statement is valid. If +** it is, return a pointer to the Mem for the value of that column. +** If iCol is not valid, return a pointer to a Mem which has a value +** of NULL. +*/ +static Mem *columnMem(sqlite3_stmt *pStmt, int i){ + Vdbe *pVm = (Vdbe *)pStmt; + int vals = sqlite3_data_count(pStmt); + if( i>=vals || i<0 ){ + static Mem nullMem; + if( nullMem.flags==0 ){ nullMem.flags = MEM_Null; } + sqlite3Error(pVm->db, SQLITE_RANGE, 0); + return &nullMem; + } + return &pVm->pTos[(1-vals)+i]; +} + +/**************************** sqlite3_column_ ******************************* +** The following routines are used to access elements of the current row +** in the result set. +*/ +int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_bytes( columnMem(pStmt,i) ); +} +int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_bytes16( columnMem(pStmt,i) ); +} +double sqlite3_column_double(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_double( columnMem(pStmt,i) ); +} +int sqlite3_column_int(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_int( columnMem(pStmt,i) ); +} +long long int sqlite3_column_int64(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_int64( columnMem(pStmt,i) ); +} +const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_text( columnMem(pStmt,i) ); +} +const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_text16( columnMem(pStmt,i) ); +} +int sqlite3_column_type(sqlite3_stmt *pStmt, int i){ + return sqlite3_value_type( columnMem(pStmt,i) ); +} + + +/* +** Return the name of the Nth column of the result set returned by SQL +** statement pStmt. +*/ +const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pColName; + + if( N>=sqlite3_column_count(pStmt) || N<0 ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return 0; + } + + pColName = &(p->aColName[N]); + return sqlite3_value_text(pColName); +} + +/* +** Return the name of the 'i'th column of the result set of SQL statement +** pStmt, encoded as UTF-16. +*/ +const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pColName; + + if( N>=sqlite3_column_count(pStmt) || N<0 ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return 0; + } + + pColName = &(p->aColName[N]); + return sqlite3_value_text16(pColName); +} + + +/* +** This routine returns either the column name, or declaration type (see +** sqlite3_column_decltype16() ) of the 'i'th column of the result set of +** SQL statement pStmt. The returned string is UTF-16 encoded. +** +** The declaration type is returned if 'decltype' is true, otherwise +** the column name. +*/ +static const void *columnName16(sqlite3_stmt *pStmt, int i, int decltype){ + Vdbe *p = (Vdbe *)pStmt; + + if( i>=sqlite3_column_count(pStmt) || i<0 ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return 0; + } + + if( decltype ){ + i += p->nResColumn; + } + + if( !p->azColName16 ){ + p->azColName16 = (void **)sqliteMalloc(sizeof(void *)*p->nResColumn*2); + if( !p->azColName16 ){ + sqlite3Error(p->db, SQLITE_NOMEM, 0); + return 0; + } + } + if( !p->azColName16[i] ){ + if( SQLITE3_BIGENDIAN ){ + p->azColName16[i] = sqlite3utf8to16be(p->azColName[i], -1); + } + if( !p->azColName16[i] ){ + sqlite3Error(p->db, SQLITE_NOMEM, 0); + return 0; + } + } + return p->azColName16[i]; +} + +/* +** Return the column declaration type (if applicable) of the 'i'th column +** of the result set of SQL statement pStmt, encoded as UTF-8. +*/ +const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int i){ + Vdbe *p = (Vdbe *)pStmt; + + if( i>=sqlite3_column_count(pStmt) || i<0 ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return 0; + } + + return p->azColName[i+p->nResColumn]; +} + +/* +** Return the column declaration type (if applicable) of the 'i'th column +** of the result set of SQL statement pStmt, encoded as UTF-16. +*/ +const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int i){ + return columnName16(pStmt, i, 1); +} + +/******************************* sqlite3_bind_ *************************** +** +** Routines used to attach values to wildcards in a compiled SQL statement. +*/ +/* +** Unbind the value bound to variable i in virtual machine p. This is the +** the same as binding a NULL value to the column. If the "i" parameter is +** out of range, then SQLITE_RANGE is returned. Othewise SQLITE_OK. +** +** The error code stored in database p->db is overwritten with the return +** value in any case. +*/ +static int vdbeUnbind(Vdbe *p, int i){ + Mem *pVar; + if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 ){ + sqlite3Error(p->db, SQLITE_MISUSE, 0); + return SQLITE_MISUSE; + } + if( i<1 || i>p->nVar ){ + sqlite3Error(p->db, SQLITE_RANGE, 0); + return SQLITE_RANGE; + } + i--; + pVar = &p->apVar[i]; + if( pVar->flags&MEM_Dyn ){ + sqliteFree(pVar->z); + } + pVar->flags = MEM_Null; + sqlite3Error(p->db, SQLITE_OK, 0); + return SQLITE_OK; +} + +/* +** Bind a blob value to an SQL statement variable. +*/ +int sqlite3_bind_blob( + sqlite3_stmt *p, + int i, + const void *zData, + int nData, + int eCopy +){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pVar; + int rc; + + rc = vdbeUnbind(p, i); + if( rc ){ + return rc; + } + pVar = &p->apVar[i-1]; + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, 0, eCopy); + return rc; +} +int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + Mem *pVar; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetReal(&p->apVar[i-1], rValue); + } + return SQLITE_OK; +} +int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ + return sqlite3_bind_int64(p, i, (long long int)iValue); +} +int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, long long int iValue){ + int rc; + Vdbe *p = (Vdbe *)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetInt(&p->apVar[i-1], iValue); + } + return rc; +} +int sqlite3_bind_null(sqlite3_stmt* p, int i){ + return vdbeUnbind((Vdbe *)p, i); +} +int sqlite3_bind_text( + sqlite3_stmt *pStmt, + int i, + const char *zData, + int nData, + int eCopy +){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pVar; + int rc; + + rc = vdbeUnbind(p, i); + if( rc ){ + return rc; + } + pVar = &p->apVar[i-1]; + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, TEXT_Utf8, eCopy); + if( rc ){ + return rc; + } + rc = sqlite3VdbeSetEncoding(pVar, p->db->enc); + return rc; +} +int sqlite3_bind_text16( + sqlite3_stmt *pStmt, + int i, + const void *zData, + int nData, + int eCopy +){ + Vdbe *p = (Vdbe *)pStmt; + Mem *pVar; + int rc; + + rc = vdbeUnbind(p, i); + if( rc ){ + return rc; + } + Mem *pVar = &p->apVar[i-1]; + + /* There may or may not be a byte order mark at the start of the UTF-16. + ** Either way set 'txt_enc' to the TEXT_Utf16* value indicating the + ** actual byte order used by this string. If the string does happen + ** to contain a BOM, then move zData so that it points to the first + ** byte after the BOM. + */ + txt_enc = sqlite3UtfReadBom(zData, nData); + if( txt_enc ){ + zData = (void *)(((u8 *)zData) + 2); + nData -= 2; + }else{ + txt_enc = SQLITE3_BIGENDIAN?TEXT_Utf16be:TEXT_Utf16le; + } + rc = sqlite3VdbeMemSetStr(pVar, zData, nData, txt_enc, eCopy); + if( rc ){ + return rc; + } + rc = sqlite3VdbeSetEncoding(pVar, p->db->enc); + return rc; +} diff --git a/src/vdbeaux.c b/src/vdbeaux.c index b03e49372b..fd72c25ba5 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -442,7 +442,7 @@ void *sqlite3_user_data(sqlite3_context *p){ ** the internals of the sqlite3_context structure which is only defined in ** this source file. */ -void *sqlite3_get_context(sqlite3_context *p, int nByte){ +void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ assert( p && p->pFunc && p->pFunc->xStep ); if( p->pAgg==0 ){ if( nByte<=NBFS ){ @@ -584,7 +584,7 @@ int sqlite3VdbeList( /* Even though this opcode does not put dynamic strings onto the ** the stack, they may become dynamic if the user calls - ** sqlite3_column_data16(), causing a translation to UTF-16 encoding. + ** sqlite3_column_text16(), causing a translation to UTF-16 encoding. */ if( p->pTos==&p->aStack[4] ){ for(i=0; i<5; i++){ diff --git a/src/vdbemem.c b/src/vdbemem.c new file mode 100644 index 0000000000..309f21960d --- /dev/null +++ b/src/vdbemem.c @@ -0,0 +1,398 @@ +/* +** 2004 May 26 +** +** 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 contains code use to manipulate "Mem" structure. A "Mem" +** stores a single value in the VDBE. Mem is an opaque structure visible +** only within the VDBE. Interface routines refer to a Mem using the +** name sqlite_value +*/ +#include "sqliteInt.h" +#include "os.h" +#include +#include "vdbeInt.h" + +/* +** Given a Mem.flags value, return TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be +** as appropriate. +*/ +#define flagsToEnc(F) \ + (((F)&MEM_Utf8)?TEXT_Utf8: \ + ((F)&MEM_Utf16be)?TEXT_Utf16be:TEXT_Utf16le) + +/* +** If pMem is a string object, this routine sets the encoding of the string +** (to one of UTF-8 or UTF16) and whether or not the string is +** nul-terminated. If pMem is not a string object, then this routine is +** a no-op. +** +** The second argument, "flags" consists of one of MEM_Utf8, MEM_Utf16le +** or MEM_Utf16be, possible ORed with MEM_Term. If necessary this function +** manipulates the value stored by pMem so that it matches the flags passed +** in "flags". +** +** SQLITE_OK is returned if the conversion is successful (or not required). +** SQLITE_NOMEM may be returned if a malloc() fails during conversion +** between formats. +*/ +int sqlite3VdbeSetEncoding(Mem *pMem, int flags){ + u8 enc1; /* Current string encoding (TEXT_Utf* value) */ + u8 enc2; /* Required string encoding (TEXT_Utf* value) */ + + /* If this is not a string, do nothing. */ + if( !(pMem->flags&MEM_Str) ){ + return SQLITE_OK; + } + + enc1 = flagsToEnc(pMem->flags); + enc2 = flagsToEnc(flags); + + if( enc1!=enc2 ){ + if( enc1==TEXT_Utf8 || enc2==TEXT_Utf8 ){ + /* If the current encoding does not match the desired encoding, then + ** we will need to do some translation between encodings. + */ + char *z; + int n; + int rc = sqlite3utfTranslate(pMem->z,pMem->n,enc1,(void **)&z,&n,enc2); + if( rc!=SQLITE_OK ){ + return rc; + } + + /* Result of sqlite3utfTranslate is currently always dynamically + ** allocated and nul terminated. This might be altered as a performance + ** enhancement later. + */ + pMem->z = z; + pMem->n = n; + pMem->flags = (MEM_Str | MEM_Dyn | MEM_Term | flags); + }else{ + /* Must be translating between UTF-16le and UTF-16be. */ + int i; + if( pMem->flags&MEM_Static ){ + Dynamicify(pMem, enc1); + } + for(i=0; in; i+=2){ + char c = pMem->z[i]; + pMem->z[i] = pMem->z[i+1]; + pMem->z[i+1] = c; + } + SetEncodingFlags(pMem, enc2); + } + } + + if( (flags&MEM_Term) && !(pMem->flags&MEM_Term) ){ + /* If we did not do any translation, but currently the string is + ** not nul terminated (and is required to be), then we add the + ** nul terminator now. We never have to do this if we translated + ** the encoding of the string, as the translation functions return + ** nul terminated values. + */ + int f = pMem->flags; + int nulTermLen = 2; /* The number of 0x00 bytes to append */ + if( enc2==MEM_Utf8 ){ + nulTermLen = 1; + } + + if( pMem->n+nulTermLen<=NBFS ){ + /* If the string plus the nul terminator will fit in the Mem.zShort + ** buffer, and it is not already stored there, copy it there. + */ + if( !(f&MEM_Short) ){ + memcpy(pMem->z, pMem->zShort, pMem->n); + if( f&MEM_Dyn ){ + sqliteFree(pMem->z); + } + pMem->z = pMem->zShort; + pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Dyn); + pMem->flags |= MEM_Short; + } + }else{ + /* Otherwise we have to malloc for memory. If the string is already + ** dynamic, use sqliteRealloc(). Otherwise sqliteMalloc() enough + ** space for the string and the nul terminator, and copy the string + ** data there. + */ + if( f&MEM_Dyn ){ + pMem->z = (char *)sqliteRealloc(pMem->z, pMem->n+nulTermLen); + if( !pMem->z ){ + return SQLITE_NOMEM; + } + }else{ + char *z = (char *)sqliteMallocRaw(pMem->n+nulTermLen); + memcpy(z, pMem->z, pMem->n); + pMem->z = z; + pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short); + pMem->flags |= MEM_Dyn; + } + } + + /* pMem->z now points at the string data, with enough space at the end + ** to insert the nul nul terminator. pMem->n has not yet been updated. + */ + memcpy(&pMem->z[pMem->n], "\0\0", nulTermLen); + pMem->n += nulTermLen; + pMem->flags |= MEM_Term; + } + return SQLITE_OK; +} + +static void releaseMem(Mem *p){ + if( p->flags & MEM_Dyn ){ + sqliteFree(p); + } +} + +/* +** Delete any previous value and set the value stored in *pMem to NULL. +*/ +void sqlite3VdbeMemSetNull(Mem *pMem){ + releaseMem(pMem); + pMem->flags = MEM_Null; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type INTEGER. +*/ +void sqlite3VdbeMemSetInt(Mem *pMem, i64 val){ + releaseMem(pMem); + pMem->i = val; + pMem->flags = MEM_Int; +} + +/* +** Delete any previous value and set the value stored in *pMem to val, +** manifest type REAL. +*/ +void sqlite3VdbeMemSetReal(Mem *pMem, double val){ + releaseMem(pMem); + pMem->r = val; + pMem->flags = MEM_Real; +} + +/* +** Copy the contents of memory cell pFrom into pTo. +*/ +int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){ + releaseMem(pTo); + memcpy(pTo, pFrom, sizeof(*pFrom)); + if( pTo->flags&MEM_Short ){ + pTo->z = pTo->zShort; + }else if( pTo->flags&(MEM_Ephem|MEM_Dyn) ){ + pTo->flags = pTo->flags&(~(MEM_Static|MEM_Ephem|MEM_Short|MEM_Dyn)); + if( pTo->n>NBFS ){ + pTo->z = sqliteMalloc(pTo->n); + if( !pTo->z ) return SQLITE_NOMEM; + pTo->flags |= MEM_Dyn; + }else{ + pTo->z = pTo->zShort; + pTo->flags |= MEM_Short; + } + memcpy(pTo->z, pFrom->z, pTo->n); + } + return SQLITE_OK; +} + +int sqlite3VdbeMemSetStr( + Mem *pMem, /* Memory cell to set to string value */ + const char *z, /* String pointer */ + int n, /* Bytes in string, or negative */ + u8 enc, /* Encoding of z */ + int eCopy /* True if this function should make a copy of z */ +){ + Mem tmp; + + releaseMem(pMem); + if( !z ){ + /* If z is NULL, just set *pMem to contain NULL. */ + return SQLITE_OK; + } + + pMem->z = (char *)z; + if( eCopy ){ + pMem->flags = MEM_Ephem|MEM_Str; + }else{ + pMem->flags = MEM_Static|MEM_Str; + } + pMem->flags |= encToFlags(enc); + pMem->n = n; + switch( enc ){ + case 0: + pMem->flags |= MEM_Blob; + break; + + case TEXT_Utf8: + pMem->flags |= MEM_Utf8; + if( n<0 ){ + pMem->n = strlen(z)+1; + pMem->flags |= MEM_Term; + }else if( z[pMem->n-1]==0 ){ + pMem->flags |= MEM_Term; + } + break; + + case TEXT_Utf16le: + case TEXT_Utf16be: + pMem->flags |= (enc==TEXT_Utf16le?MEM_Utf16le:MEM_Utf16be); + if( n<0 ){ + pMem->n = sqlite3utf16ByteLen(z,-1)+1; + pMem->flags |= MEM_Term; + }else if( z[pMem->n-1]==0 && z[pMem->n-2]==0 ){ + pMem->flags |= MEM_Term; + } + break; + + default: + assert(0); + } + Deephemeralize(pMem); +} + +int sqlite3VdbeMemNulTerminate(Mem *pMem){ + int nulTermLen; + int f = pMem->flags; + + assert( pMem->flags&MEM_Str && !pMem->flags&MEM_Term ); + assert( flagsToEnc(pMem->flags) ); + + nulTermLen = (flagsToEnc(f)==TEXT_Utf8?1:2); + + if( pMem->n+nulTermLen<=NBFS ){ + /* If the string plus the nul terminator will fit in the Mem.zShort + ** buffer, and it is not already stored there, copy it there. + */ + if( !(f&MEM_Short) ){ + memcpy(pMem->z, pMem->zShort, pMem->n); + if( f&MEM_Dyn ){ + sqliteFree(pMem->z); + } + pMem->z = pMem->zShort; + pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Dyn); + pMem->flags |= MEM_Short; + } + }else{ + /* Otherwise we have to malloc for memory. If the string is already + ** dynamic, use sqliteRealloc(). Otherwise sqliteMalloc() enough + ** space for the string and the nul terminator, and copy the string + ** data there. + */ + if( f&MEM_Dyn ){ + pMem->z = (char *)sqliteRealloc(pMem->z, pMem->n+nulTermLen); + if( !pMem->z ){ + return SQLITE_NOMEM; + } + }else{ + char *z = (char *)sqliteMalloc(pMem->n+nulTermLen); + memcpy(z, pMem->z, pMem->n); + pMem->z = z; + pMem->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short); + pMem->flags |= MEM_Dyn; + } + } + + /* pMem->z now points at the string data, with enough space at the end + ** to insert the nul nul terminator. pMem->n has not yet been updated. + */ + memcpy(&pMem->z[pMem->n], "\0\0", nulTermLen); + pMem->n += nulTermLen; + pMem->flags |= MEM_Term; +} + +/* +** Compare the values contained by the two memory cells, returning +** negative, zero or positive if pMem1 is less than, equal to, or greater +** than pMem2. Sorting order is NULL's first, followed by numbers (integers +** and reals) sorted numerically, followed by text ordered by the collating +** sequence pColl and finally blob's ordered by memcmp(). +** +** Two NULL values are considered equal by this function. +*/ +int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ + int rc; + int f1, f2; + int combined_flags; + + /* Interchange pMem1 and pMem2 if the collating sequence specifies + ** DESC order. + */ + f1 = pMem1->flags; + f2 = pMem2->flags; + combined_flags = f1|f2; + + /* If one value is NULL, it is less than the other. If both values + ** are NULL, return 0. + */ + if( combined_flags&MEM_Null ){ + return (f2&MEM_Null) - (f1&MEM_Null); + } + + /* If one value is a number and the other is not, the number is less. + ** If both are numbers, compare as reals if one is a real, or as integers + ** if both values are integers. + */ + if( combined_flags&(MEM_Int|MEM_Real) ){ + if( !(f1&(MEM_Int|MEM_Real)) ){ + return 1; + } + if( !(f2&(MEM_Int|MEM_Real)) ){ + return -1; + } + if( (f1 & f2 & MEM_Int)==0 ){ + double r1, r2; + if( (f1&MEM_Real)==0 ){ + r1 = pMem1->i; + }else{ + r1 = pMem1->r; + } + if( (f2&MEM_Real)==0 ){ + r2 = pMem2->i; + }else{ + r2 = pMem2->r; + } + if( r1r2 ) return 1; + return 0; + }else{ + assert( f1&MEM_Int ); + assert( f2&MEM_Int ); + if( pMem1->i < pMem2->i ) return -1; + if( pMem1->i > pMem2->i ) return 1; + return 0; + } + } + + /* If one value is a string and the other is a blob, the string is less. + ** If both are strings, compare using the collating functions. + */ + if( combined_flags&MEM_Str ){ + if( (f1 & MEM_Str)==0 ){ + return 1; + } + if( (f2 & MEM_Str)==0 ){ + return -1; + } + if( pColl && pColl->xCmp ){ + return pColl->xCmp(pColl->pUser, pMem1->n, pMem1->z, pMem2->n, pMem2->z); + }else{ + /* If no collating sequence is defined, fall through into the + ** blob case below and use memcmp() for the comparison. */ + } + } + + /* Both values must be blobs. Compare using memcmp(). + */ + rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n); + if( rc==0 ){ + rc = pMem1->n - pMem2->n; + } + return rc; +}