diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/date.c | 8 | ||||
-rw-r--r-- | src/func.c | 45 | ||||
-rw-r--r-- | src/legacy.c | 6 | ||||
-rw-r--r-- | src/md5.c | 9 | ||||
-rw-r--r-- | src/sqlite.h.in | 658 | ||||
-rw-r--r-- | src/tclsqlite.c | 4 | ||||
-rw-r--r-- | src/test1.c | 32 | ||||
-rw-r--r-- | src/test4.c | 7 | ||||
-rw-r--r-- | src/vdbe.c | 974 | ||||
-rw-r--r-- | src/vdbeInt.h | 31 | ||||
-rw-r--r-- | src/vdbeapi.c | 503 | ||||
-rw-r--r-- | src/vdbeaux.c | 4 | ||||
-rw-r--r-- | src/vdbemem.c | 398 |
13 files changed, 1141 insertions, 1538 deletions
diff --git a/src/date.c b/src/date.c index 3a15ba163..42f42f22d 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<argc; i++){ if( SQLITE3_NULL==sqlite3_value_type(argv[i]) || - parseModifier(sqlite3_value_data(argv[i]), p) ) return 1; + parseModifier(sqlite3_value_text(argv[i]), p) ) return 1; } return 0; } @@ -761,7 +761,7 @@ static void strftimeFunc( DateTime x; int n, i, j; char *z; - const char *zFmt = sqlite3_value_data(argv[0]); + const char *zFmt = sqlite3_value_text(argv[0]); char zBuf[100]; if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return; for(i=0, n=1; zFmt[i]; i++, n++){ diff --git a/src/func.c b/src/func.c index 7aaee79a3..b9f56ef7f 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.57 2004/05/26 16:54:43 drh Exp $ +** $Id: func.c,v 1.58 2004/05/26 23:25:31 drh Exp $ */ #include <ctype.h> #include <math.h> @@ -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 655f2bb7b..664705ba0 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; i<nCol; i++){ - azVals[i] = (char *)sqlite3_column_data(pStmt, i); + azVals[i] = (char *)sqlite3_column_text(pStmt, i); } } if( xCallback(pArg, nCol, azVals, azCols) ){ @@ -133,5 +133,3 @@ exec_out: return rc; } - - @@ -360,13 +360,13 @@ static void md5step(sqlite3_context *context, int argc, sqlite3_value **argv){ MD5Context *p; int i; if( argc<1 ) return; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); if( p==0 ) return; if( sqlite3_aggregate_count(context)==1 ){ MD5Init(p); } for(i=0; i<argc; i++){ - const char *zData = sqlite3_value_data(argv[i]); + const char *zData = sqlite3_value_text(argv[i]); if( zData ){ MD5Update(p, zData, strlen(zData)); } @@ -376,7 +376,7 @@ static void md5finalize(sqlite3_context *context){ MD5Context *p; unsigned char digest[16]; char zBuf[33]; - p = sqlite3_get_context(context, sizeof(*p)); + p = sqlite3_aggregate_context(context, sizeof(*p)); MD5Final(digest,p); DigestToBase16(digest, zBuf); sqlite3_result_text(context, zBuf, -1, 1); @@ -384,6 +384,3 @@ static void md5finalize(sqlite3_context *context){ void Md5_Register(sqlite *db){ sqlite3_create_function(db, "md5sum", -1, 0, 0, 0, 0, md5step, md5finalize); } - - - diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 027ba7346..444ba5a56 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.81 2004/05/26 16:54:44 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.82 2004/05/26 23:25:31 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -330,12 +330,14 @@ int sqlite3_get_table( void sqlite3_free_table(char **result); /* -** The following routines are wrappers around sqlite3_exec() and -** sqlite3_get_table(). The only difference between the routines that -** follow and the originals is that the second argument to the -** routines that follow is really a printf()-style format -** string describing the SQL to be executed. Arguments to the format -** string appear at the end of the argument list. +** The following routines are variants of the "sprintf()" from the +** standard C library. The resulting string is written into memory +** obtained from malloc() so that there is never a possiblity of buffer +** overflow. These routines also implement some additional formatting +** options that are useful for constructing SQL statements. +** +** The strings returned by these routines should be freed by calling +** sqlite3_free(). ** ** All of the usual printf formatting options apply. In addition, there ** is a "%q" option. %q works like %s in that it substitutes a null-terminated @@ -367,50 +369,9 @@ void sqlite3_free_table(char **result); ** should always use %q instead of %s when inserting text into a string ** literal. */ -int sqlite3_exec_printf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - sqlite_callback, /* Callback function */ - void *, /* 1st argument to callback function */ - char **errmsg, /* Error msg written here */ - ... /* Arguments to the format string. */ -); -int sqlite3_exec_vprintf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - sqlite_callback, /* Callback function */ - void *, /* 1st argument to callback function */ - char **errmsg, /* Error msg written here */ - va_list ap /* Arguments to the format string. */ -); -int sqlite3_get_table_printf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg, /* Error msg written here */ - ... /* Arguments to the format string */ -); -int sqlite3_get_table_vprintf( - sqlite*, /* An open database */ - const char *sqlFormat, /* printf-style format string for the SQL */ - char ***resultp, /* Result written to a char *[] that this points to */ - int *nrow, /* Number of result rows written here */ - int *ncolumn, /* Number of result columns written here */ - char **errmsg, /* Error msg written here */ - va_list ap /* Arguments to the format string */ -); char *sqlite3_mprintf(const char*,...); char *sqlite3_vmprintf(const char*, va_list); - -/* -** Windows systems should call this routine to free memory that -** is returned in the in the errmsg parameter of sqlite3_open() when -** SQLite is a DLL. For some reason, it does not work to call free() -** directly. -*/ -void sqlite3_freemem(void *p); +void sqlite3_free(char *z); /* ** Windows systems need functions to call to return the sqlite3_version @@ -533,77 +494,17 @@ void sqlite3_progress_handler(sqlite*, int, int(*)(void*), void*); void *sqlite3_commit_hook(sqlite*, int(*)(void*), void*); /* -** Open an encrypted SQLite database. If pKey==0 or nKey==0, this routine -** is the same as sqlite3_open(). -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -sqlite *sqlite3_open_encrypted( - const char *zFilename, /* Name of the encrypted database */ - const void *pKey, /* Pointer to the key */ - int nKey, /* Number of bytes in the key */ - int *pErrcode, /* Write error code here */ - char **pzErrmsg /* Write error message here */ -); - -/* -** Change the key on an open database. If the current database is not -** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the -** database is decrypted. -** -** The code to implement this API is not available in the public release -** of SQLite. -*/ -int sqlite_rekey( - sqlite *db, /* Database to be rekeyed */ - const void *pKey, int nKey /* The new key */ -); - -/* -** Encode a binary buffer "in" of size n bytes so that it contains -** no instances of characters '\'' or '\000'. The output is -** null-terminated and can be used as a string value in an INSERT -** or UPDATE statement. Use sqlite_decode_binary() to convert the -** string back into its original binary. -** -** The result is written into a preallocated output buffer "out". -** "out" must be able to hold at least 2 +(257*n)/254 bytes. -** In other words, the output will be expanded by as much as 3 -** bytes for every 254 bytes of input plus 2 bytes of fixed overhead. -** (This is approximately 2 + 1.0118*n or about a 1.2% size increase.) -** -** The return value is the number of characters in the encoded -** string, excluding the "\000" terminator. -** -** If out==NULL then no output is generated but the routine still returns -** the number of characters that would have been generated if out had -** not been NULL. -*/ -int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out); - -/* -** Decode the string "in" into binary data and write it into "out". -** This routine reverses the encoding created by sqlite_encode_binary(). -** The output will always be a few bytes less than the input. The number -** of bytes of output is returned. If the input is not a well-formed -** encoding, -1 is returned. -** -** The "in" and "out" parameters may point to the same buffer in order -** to decode a string in place. -*/ -int sqlite_decode_binary(const unsigned char *in, unsigned char *out); - -/* -** Open the sqlite database file "filename", where "filename" is UTF-8 -** encoded. An sqlite3* handle is returned in *ppDb, even if an error -** occurs. If the database is opened (or created) successfully, then -** SQLITE_OK is returned. Otherwise an error code is returned and the -** sqlite3_errmsg() function may be used to obtain an English language -** explanation of the error. +** Open the sqlite database file "filename". The "filename" is UTF-8 +** encoded for sqlite3_open() and UTF-16 encoded in the native byte order +** for sqlite3_open16(). An sqlite3* handle is returned in *ppDb, even +** if an error occurs. If the database is opened (or created) successfully, +** then SQLITE_OK is returned. Otherwise an error code is returned. The +** sqlite3_errmsg() or sqlite3_errmsg16() routines can be used to obtain +** an English language description of the error. ** -** If the database file does not exist, then a new database is created -** using UTF-8 text encoding. +** If the database file does not exist, then a new database is created. +** The encoding for the database is UTF-8 if sqlite3_open() is called and +** UTF-16 if sqlite3_open16 is used. ** ** Whether or not an error occurs when it is opened, resources associated ** with the sqlite3* handle should be released by passing it to @@ -614,22 +515,6 @@ int sqlite3_open( sqlite3 **ppDb, /* OUT: SQLite db handle */ const char **args /* Null terminated array of option strings */ ); - -/* -** Open the sqlite database file "filename", where "filename" is native -** byte order UTF-16 encoded. An sqlite3* handle is returned in *ppDb, even -** if an error occurs. If the database is opened (or created) successfully, -** then SQLITE_OK is returned. Otherwise an error code is returned and the -** sqlite3_errmsg() function may be used to obtain an English language -** explanation of the error. -** -** If the database file does not exist, then a new database is created -** using UTF-16 text encoding in the machines native byte order. -** -** Whether or not an error occurs when it is opened, resources associated -** with the sqlite3* handle should be released by passing it to -** sqlite3_close() when it is no longer required. -*/ int sqlite3_open16( const void *filename, /* Database filename (UTF-16) */ sqlite3 **ppDb, /* OUT: SQLite db handle */ @@ -720,6 +605,35 @@ int sqlite3_prepare16( ); /* +** In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(), +** one or more literals can be replace by a wildcard "?" or ":N:" where +** N is an integer. These value of these wildcard literals can be set +** using the routines listed below. +** +** In every case, the first parameter is a pointer to the sqlite3_stmt +** structure returned from sqlite3_prepare(). The second parameter is the +** index of the wildcard. The first "?" has an index of 1. ":N:" wildcards +** use the index N. +** +** When the eCopy parameter is true, a copy of the value is made into +** memory obtained and managed by SQLite. When eCopy is false, SQLite +** assumes that the value is a constant and just stores a pointer to the +** value without making a copy. +** +** The sqlite3_bind_* routine must be called before sqlite3_step() after +** an sqlite3_prepare() or sqlite3_reset(). Unbound wildcards are interpreted +** as NULL. +*/ +void sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, int eCopy); +void sqlite3_bind_double(sqlite3_stmt*, int, double); +void sqlite3_bind_int(sqlite3_stmt*, int, int); +void sqlite3_bind_int64(sqlite3_stmt*, int, long long int); +void sqlite3_bind_null(sqlite3_stmt*, int); +void sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, int eCopy); +void sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int n, int eCopy); +void sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*); + +/* ** Return the number of columns in the result set returned by the compiled ** SQL statement. This routine returns 0 if pStmt is an SQL statement ** that does not return data (for example an UPDATE). @@ -729,15 +643,10 @@ int sqlite3_column_count(sqlite3_stmt *pStmt); /* ** The first parameter is a compiled SQL statement. This function returns ** the column heading for the Nth column of that statement, where N is the -** second function parameter. The string returned is UTF-8 encoded. +** second function parameter. The string returned is UTF-8 for +** sqlite3_column_name() and UTF-16 for sqlite3_column_name16(). */ const char *sqlite3_column_name(sqlite3_stmt*,int); - -/* -** The first parameter is a compiled SQL statement. This function returns -** the column heading for the Nth column of that statement, where N is the -** second function parameter. The string returned is UTF-16 encoded. -*/ const void *sqlite3_column_name16(sqlite3_stmt*,int); /* @@ -768,131 +677,18 @@ const char *sqlite3_column_decltype(sqlite3_stmt *, int i); ** column, then a NULL pointer is returned. The returned string is always ** UTF-16 encoded. For example, in the database schema: ** -** CREATE TABLE t1(c1 VARINT); +** CREATE TABLE t1(c1 INTEGER); ** ** And the following statement compiled: ** ** SELECT c1 + 1, 0 FROM t1; ** -** Then this routine would return the string "VARIANT" for the second +** Then this routine would return the string "INTEGER" for the second ** result column (i==1), and a NULL pointer for the first result column ** (i==0). */ const void *sqlite3_column_decltype16(sqlite3_stmt*,int); -/* -** This routine is used to bind a 32-bit integer value to a variable -** in an SQL statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously -** obtained from a call to sqlite3_prepare(). The second parameter "i" -** determines the parameter to bind the value "iValue" to. -*/ -int sqlite3_bind_int32(sqlite3_stmt*, int i, int iValue); - -/* -** This routine is used to bind a 64-bit integer value to a variable -** in an SQL statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously -** obtained from a call to sqlite3_prepare(). The second parameter "i" -** determines the parameter to bind the value "iValue" to. -*/ -int sqlite3_bind_int64(sqlite3_stmt*, int i, long long int iValue); - -/* -** This routine is used to bind a real (floating point) value to a variable -** in an SQL statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_prepare(). The second parameter "i" determines -** the parameter to bind the value "iValue" to. Internally, SQLite will -** manipulate the value as a 64-bit IEEE float. -*/ -int sqlite3_bind_double(sqlite3_stmt*, int i, double iValue); - -/* -** This routine is used to bind a NULL value to a variable in an SQL -** statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_prepare(). The second parameter "i" determines -** the parameter to bind the NULL value to. -*/ -int sqlite3_bind_null(sqlite3_stmt*, int i); - -/* -** This routine is used to bind a UTF-8 string value to a variable in an -** SQL statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_prepare(). The second parameter "i" determines -** the parameter to bind the value to. Parameter three "z" is a pointer -** to the UTF-8 string. -** -** The fourth "n" parameter is the number of bytes (not characters) in the -** string pointed to by "z". "n" may or may not include any nul terminator -** character. If "n" is less than zero, then SQLite assumes that "z" is -** a nul terminated string. -** -** If paramater "eCopy" is true, then SQLite makes a copy of the string -** pointed to by "z". If "eCopy" is false, then SQLite stores a pointer to -** the original string data. In this case the caller must ensure that the -** string data remains stable until after the SQL statement has been -** finalised or another value bound to variable "i". -*/ -int sqlite3_bind_text(sqlite3_stmt*, int i, const char* z, int n, int eCopy); - -/* -** This routine is used to bind a UTF-16 string value to a variable in an -** SQL statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_prepare(). The second parameter "i" determines -** the parameter to bind the value to. Parameter three "z" is a pointer to -** the UTF-16 string. If the string does not begin with a byte-order-mark, -** it is assumed to be encoded in the native byte order of the machine. -** -** The fourth "n" parameter is the number of bytes (not characters) in the -** string pointed to by "z". "n" may or may not include any nul terminator -** character. If "n" is less than zero, then SQLite assumes that "z" is -** terminated by a pair of 0x00 characters. -** -** If paramater "eCopy" is true, then SQLite makes a copy of the string -** pointed to by "z". If "eCopy" is false, then SQLite stores a pointer to -** the original string data. In this case the caller must ensure that the -** string data remains stable until after the SQL statement has been -** finalised or another value bound to variable "i". -*/ -int sqlite3_bind_text16(sqlite3_stmt*, int i, const void *z, int, int eCopy); - -/* -** This routine is used to bind a blob value to a variable in an -** SQL statement compiled by sqlite3_prepare(). See comments for -** sqlite3_prepare() for more details on SQL statement variables. -** -** The first argument is a pointer to an SQL statement previously obtained -** from a call to sqlite3_prepare(). The second parameter "i" determines -** the parameter to bind the value to. Parameter three "z" is a pointer to -** the blob of data. -** -** The fourth "n" parameter is the number of bytes in the blob pointed to -** by "z". "n" may not be less than zero. -** -** If paramater "eCopy" is true, then SQLite makes a copy of the blob -** pointed to by "z". If "eCopy" is false, then SQLite stores a pointer to -** the original blob data. In this case the caller must ensure that the -** blob data remains stable until after the SQL statement has been -** finalised or another value bound to variable "i". -*/ -int sqlite3_bind_blob(sqlite3_stmt*, int i, const void *z, int n, int eCopy); - /* ** After an SQL query has been compiled with a call to either ** sqlite3_prepare() or sqlite3_prepare16(), then this function must be @@ -938,108 +734,82 @@ int sqlite3_step(sqlite3_stmt*); */ int sqlite3_data_count(sqlite3_stmt *pStmt); -#define SQLITE3_INTEGER 1 -#define SQLITE3_FLOAT 2 -#define SQLITE3_TEXT 3 -#define SQLITE3_BLOB 4 -#define SQLITE3_NULL 5 - -/* -** 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 type of the Nth column of the current row, where -** N is the second function parameter. -** -** The value type is one of SQLITE3_INTEGER, SQLITE3_FLOAT, SQLITE3_TEXT, -** SQLITE3_BLOB and SQLITE3_NULL. -*/ -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); +** Values are stored in the database in one of the following fundamental +** types. +*/ +#define SQLITE_INTEGER 1 +#define SQLITE_FLOAT 2 +#define SQLITE_TEXT 3 +#define SQLITE_BLOB 4 +#define SQLITE_NULL 5 + +/* +** The next group of routines returns information about the information +** in a single column of the current result row of a query. In every +** case the first parameter is a pointer to the SQL statement that is being +** executed (the sqlite_stmt* that was returned from sqlite3_prepare()) and +** the second argument is the index of the column for which information +** should be returned. iCol is zero-indexed. The left-most column as an +** index of 0. +** +** If the SQL statement is not currently point to a valid row, or if the +** the colulmn index is out of range, the result is undefined. +** +** These routines attempt to convert the value where appropriate. For +** example, if the internal representation is FLOAT and a text result +** is requested, sprintf() is used internally to do the conversion +** automatically. The following table details the conversions that +** are applied: +** +** Internal Type Requested Type Conversion +** ------------- -------------- -------------------------- +** NULL INTEGER Result is 0 +** NULL FLOAT Result is 0.0 +** NULL TEXT Result is an empty string +** NULL BLOB Result is a zero-length BLOB +** INTEGER FLOAT Convert from integer to float +** INTEGER TEXT ASCII rendering of the integer +** INTEGER BLOB Same as for INTEGER->TEXT +** 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. +*/ +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,79 +901,25 @@ 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 ** is called for a particular aggregate, a new structure of size nBytes @@ -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. +** User-defined functions invoke the following routines in order to +** set their return value. */ -void sqlite3_result_int32(sqlite3_context*, int); -void sqlite3_result_int64(sqlite3_context*, long long int); +void sqlite3_result_blob(sqlite3_context*, const void*, int n, int eCopy); 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_error(sqlite3_context*, const char*, int); +void sqlite3_result_error16(sqlite3_context*, const void*, int); +void sqlite3_result_int(sqlite3_context*, int); +void sqlite3_result_int64(sqlite3_context*, long long int); 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. -*/ -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_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_value(sqlite3_context*, sqlite3_value*); #ifdef __cplusplus } /* End of the 'extern "C"' block */ diff --git a/src/tclsqlite.c b/src/tclsqlite.c index a1a1a44c9..33355ba2b 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 e695cce5f..c09ced4cd 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; i<argc; i++){ if( SQLITE3_NULL!=sqlite3_value_type(argv[i]) ){ - sqlite3_result_text(context, sqlite3_value_data(argv[i]), -1, 1); + sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1, 1); break; } } @@ -373,7 +373,7 @@ static void sqlite3ExecFunc( struct dstr x; memset(&x, 0, sizeof(x)); sqlite3_exec((sqlite*)sqlite3_user_data(context), - sqlite3_value_data(argv[0]), + sqlite3_value_text(argv[0]), execFuncCallback, &x, 0); sqlite3_result_text(context, x.z, x.nUsed, 1); sqliteFree(x.z); @@ -423,14 +423,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); } @@ -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 054e578af..46d6e3c4f 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; i<sqlite3_data_count(p->pStmt); i++){ - p->argv[i] = sqlite3_column_data(p->pStmt, i); + p->argv[i] = sqlite3_column_text(p->pStmt, i); } for(i=0; i<p->argc; 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 2b8e2822e..c5f75a9da 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; } @@ -240,23 +126,11 @@ static int encToFlags(u8 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; @@ -345,125 +219,6 @@ static int hardDeephem(Mem *pStack){ } /* -** 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; i<pMem->n; 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; i<pOp->p1; 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; i<n; i++, pArg++){ SetEncodingFlags(pArg, db->enc); - MemSetTypeFlags(pArg); apVal[i] = pArg; } @@ -5636,9 +4727,8 @@ case OP_AggFunc: { assert( apVal || n==0 ); for(i=0; i<n; i++, pRec++){ - apVal[i] = pRec; - SetEncodingFlags(pRec, db->enc); - MemSetTypeFlags(pRec); + apVal[i] = pRec; + SetEncodingFlags(pRec, db->enc); } i = pTos->i; assert( i>=0 && i<p->agg.nMem ); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 733b333f6..10b32f9ea 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 000000000..1a5e86c65 --- /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 b03e49372..fd72c25ba 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 000000000..309f21960 --- /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 <ctype.h> +#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; i<pMem->n; 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( r1<r2 ) return -1; + if( r1>r2 ) 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; +} |