-C Add\smanifest\stype\saware\sversions\sof\sthe\smin()\sand\smax()\saggregates.\s(CVS\s1452)
-D 2004-05-25T01:13:21
+C Use\sthe\snew\sAPI\sfor\sreturning\svalues\sand\serrors\sfrom\suser\sfunctions.\s(CVS\s1453)
+D 2004-05-25T11:47:25
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F src/btree.h b65140b5ae891f30d2a39e64b9f0343225553545
F src/build.c 35cbeb439b49cca5eb5e8a1de010a5194f4523e8
F src/copy.c 4d2038602fd0549d80c59bda27d96f13ea9b5e29
-F src/date.c 64fd7169c7d599ec8eaa99121d59e27ddf3d783d
+F src/date.c b754dc0e1a84b408de0ccc727c792d46ccb66a69
F src/delete.c 2e1dda38345416a1ea1c0a6468589a7472334dac
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
F src/expr.c 5b283e68bd6df365b7c2ad10bd04cc54c2b4b07c
-F src/func.c 7eb4356a9e3155d6783d84fc5d6b324031877572
+F src/func.c c811d2b77f1f1d88db759cbd60b382463f5a3ae3
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
F src/insert.c e510d62d23b4de4d901e7ccbbe7833b7fb3b9570
F src/main.c 8279e1160810410bb9ad6608f87b0140db5b1ce0
-F src/md5.c 84c69162ad4c9b8399b522a259c09e256edaf88a
+F src/md5.c 8344ab774bed1bcf2f2fd4e130cc48536f37c414
F src/os.h ab42f4a7c4c716f26b988e759b6e12085a3bfc67
F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f
F src/os_mac.c b823874690615ace0dd520d3ad1fe8bfd864b7e0
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c 7d77a8bed7eeac23216d42fc1be006fb4352fcdc
F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f
-F src/sqlite.h.in 3dfba192557c211779fdd48fd25b437b339eabcd
+F src/sqlite.h.in 5c9a7d2a4c438da8389382a4ecf145cad73a9238
F src/sqliteInt.h 3ba18f1bbe85c69db1b4882ba899681b0bbac2ae
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
-F src/tclsqlite.c c8b511645f98051f41b5e0d6c3a99feeed9aeeec
-F src/test1.c 045cdd926a8157cd24c6112c2743236063f1bf3e
+F src/tclsqlite.c 0c0600409dfc297ef026ca9c8dbdf8754e54d0c4
+F src/test1.c ae2886e9c130f0dcd49f78bd78ffa37c2cb2e7d0
F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968
F src/test4.c b9947c319a5c023c10c1e953e6610abd571c2283
F src/utf.c 1d38da85bffb928fb0d9f301e7db913a6df486ce
F src/util.c 4c0adcbc9ce6678dd046931253e45d623c6d279f
F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
-F src/vdbe.c 11bb4758ae692888ee2a2566be9e0119b489dff3
+F src/vdbe.c bf205ee831161cffc924c71307e24eb61b237230
F src/vdbe.h 391d5642a83af686f35c228fcd36cb4456d68f44
-F src/vdbeInt.h 4dfeaaf7ca34859553d62f391bfb6b6fe4be425e
-F src/vdbeaux.c 588e7df730b5d3f6cbe1f44203c91b7be0042ce5
+F src/vdbeInt.h a9a105b9232d7305b41ab36eadd0355079ff01c3
+F src/vdbeaux.c dc4fdfce9cad48d47328d7733df2ee975da6c0a0
F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 5c28ed5e9b5a3ecb3081ce0c5c9450d6ae8dc77d
-R 8308cdc960f78d11f007d3b61876bd79
+P b77c268ebebd5401c3f519a72cfb81438207368c
+R 4e71bf50ae3412040cd39e61cbbbc2a7
U danielk1977
-Z 39c12ff09c771deaa84ed1f3b56e6995
+Z c2a413dbfbef432d165e1d1b259db6f9
-b77c268ebebd5401c3f519a72cfb81438207368c
\ No newline at end of file
+4eccae03b4a7f37804fea30416579787c3584bb2
\ No newline at end of file
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: date.c,v 1.21 2004/05/24 12:39:02 danielk1977 Exp $
+** $Id: date.c,v 1.22 2004/05/25 11:47:25 danielk1977 Exp $
**
** NOTES:
**
DateTime x;
if( isDate(argc, argv, &x)==0 ){
computeJD(&x);
- sqlite3_set_result_double(context, x.rJD);
+ sqlite3_result_double(context, x.rJD);
}
}
computeYMD_HMS(&x);
sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
(int)(x.s));
- sqlite3_set_result_string(context, zBuf, -1);
+ sqlite3_result_text(context, zBuf, -1, 1);
}
}
char zBuf[100];
computeHMS(&x);
sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
- sqlite3_set_result_string(context, zBuf, -1);
+ sqlite3_result_text(context, zBuf, -1, 1);
}
}
char zBuf[100];
computeYMD(&x);
sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
- sqlite3_set_result_string(context, zBuf, -1);
+ sqlite3_result_text(context, zBuf, -1, 1);
}
}
}
}
z[j] = 0;
- sqlite3_set_result_string(context, z, -1);
+ sqlite3_result_text(context, z, -1, 1);
if( z!=zBuf ){
sqliteFree(z);
}
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.53 2004/05/25 01:13:21 danielk1977 Exp $
+** $Id: func.c,v 1.54 2004/05/25 11:47:25 danielk1977 Exp $
*/
#include <ctype.h>
#include <math.h>
zBest = zArg;
}
}
- sqlite3_set_result_string(context, zBest, -1);
+ sqlite3_result_text(context, zBest, -1, 1);
}
/*
case SQLITE3_FLOAT: z = "real" ; break;
case SQLITE3_BLOB: z = "blob" ; break;
}
- sqlite3_set_result_string(context, z, -1);
+ sqlite3_result_text(context, z, -1, 0);
}
/*
#else
len = strlen(z);
#endif
- sqlite3_set_result_int(context, len);
+ sqlite3_result_int32(context, len);
}
/*
z = sqlite3_value_data(argv[0]);
if( z==0 ) return;
if( z[0]=='-' && isdigit(z[1]) ) z++;
- sqlite3_set_result_string(context, z, -1);
+ sqlite3_result_text(context, z, -1, 1);
}
/*
while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; }
#endif
if( p2<0 ) p2 = 0;
- sqlite3_set_result_string(context, &z[p1], p2);
+ sqlite3_result_text(context, &z[p1], p2, 1);
}
/*
if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return;
r = sqlite3_value_float(argv[0]);
sprintf(zBuf,"%.*f",n,r);
- sqlite3_set_result_string(context, zBuf, -1);
+ sqlite3_result_text(context, zBuf, -1, 1);
}
/*
static void upperFunc(sqlite_func *context, int argc, sqlite3_value **argv){
char *z;
int i;
- if( argc<1 ) return;
- z = sqlite3_set_result_string(context, sqlite3_value_data(argv[0]), -1);
+ 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]));
for(i=0; z[i]; i++){
if( islower(z[i]) ) z[i] = toupper(z[i]);
}
+ sqlite3_result_text(context, z, -1, 1);
+ sqliteFree(z);
}
static void lowerFunc(sqlite_func *context, int argc, sqlite3_value **argv){
char *z;
int i;
- if( argc<1 ) return;
- z = sqlite3_set_result_string(context, sqlite3_value_data(argv[0]), -1);
+ 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]));
for(i=0; z[i]; i++){
if( isupper(z[i]) ) z[i] = tolower(z[i]);
}
+ sqlite3_result_text(context, z, -1, 1);
+ sqliteFree(z);
}
/*
int i;
for(i=0; i<argc; i++){
if( SQLITE3_NULL!=sqlite3_value_type(argv[i]) ){
- sqlite3_set_result_string(context, sqlite3_value_data(argv[i]), -1);
+ sqlite3_result_text(context, sqlite3_value_data(argv[i]), -1, 1);
break;
}
}
static void randomFunc(sqlite_func *context, int argc, sqlite3_value **argv){
int r;
sqlite3Randomness(sizeof(r), &r);
- sqlite3_set_result_int(context, r);
+ sqlite3_result_int32(context, r);
}
/*
sqlite3_value **argv
){
sqlite *db = sqlite3_user_data(context);
- sqlite3_set_result_int(context, sqlite3_last_insert_rowid(db));
+ sqlite3_result_int32(context, sqlite3_last_insert_rowid(db));
}
/*
*/
static void change_count(sqlite_func *context, int arg, sqlite3_value **argv){
sqlite *db = sqlite3_user_data(context);
- sqlite3_set_result_int(context, sqlite3_changes(db));
+ sqlite3_result_int32(context, sqlite3_changes(db));
}
/*
sqlite3_value **argv
){
sqlite *db = sqlite3_user_data(context);
- sqlite3_set_result_int(context, sqlite3_last_statement_changes(db));
+ sqlite3_result_int32(context, sqlite3_last_statement_changes(db));
}
/*
const unsigned char *zA = sqlite3_value_data(argv[0]);
const unsigned char *zB = sqlite3_value_data(argv[1]);
if( zA && zB ){
- sqlite3_set_result_int(context, sqlite3LikeCompare(zA, zB));
+ sqlite3_result_int32(context, sqlite3LikeCompare(zA, zB));
}
}
const unsigned char *zA = sqlite3_value_data(argv[0]);
const unsigned char *zB = sqlite3_value_data(argv[1]);
if( zA && zB ){
- sqlite3_set_result_int(context, sqlite3GlobCompare(zA, zB));
+ sqlite3_result_int32(context, sqlite3GlobCompare(zA, zB));
}
}
const unsigned char *zX = sqlite3_value_data(argv[0]);
const unsigned char *zY = sqlite3_value_data(argv[1]);
if( zX!=0 && sqlite3Compare(zX, zY)!=0 ){
- sqlite3_set_result_string(context, zX, -1);
+ sqlite3_result_text(context, zX, -1, 1);
}
}
** of the SQLite library that is running.
*/
static void versionFunc(sqlite_func *context, int argc, sqlite3_value **argv){
- sqlite3_set_result_string(context, sqlite3_version, -1);
+ sqlite3_result_text(context, sqlite3_version, -1, 0);
}
/*
const char *zArg = sqlite3_value_data(argv[0]);
if( argc<1 ) return;
if( zArg==0 ){
- sqlite3_set_result_string(context, "NULL", 4);
+ sqlite3_result_text(context, "NULL", 4, 0);
}else if( sqlite3IsNumber(zArg, 0, TEXT_Utf8) ){
- sqlite3_set_result_string(context, zArg, -1);
+ sqlite3_result_text(context, zArg, -1, 1);
}else{
int i,j,n;
char *z;
}
z[j++] = '\'';
z[j] = 0;
- sqlite3_set_result_string(context, z, j);
+ sqlite3_result_text(context, z, j, 1);
sqliteFree(z);
}
}
zResult[j++] = '0';
}
zResult[j] = 0;
- sqlite3_set_result_string(context, zResult, 4);
+ sqlite3_result_text(context, zResult, 4, 1);
}else{
- sqlite3_set_result_string(context, "?000", 4);
+ sqlite3_result_text(context, "?000", 4, 0);
}
}
#endif
zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
}
zBuf[n] = 0;
- sqlite3_set_result_string(context, zBuf, n);
+ sqlite3_result_text(context, zBuf, n, 1);
}
#endif
static void sumFinalize(sqlite_func *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
- sqlite3_set_result_double(context, p ? p->sum : 0.0);
+ sqlite3_result_double(context, p ? p->sum : 0.0);
}
static void avgFinalize(sqlite_func *context){
SumCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p && p->cnt>0 ){
- sqlite3_set_result_double(context, p->sum/(double)p->cnt);
+ sqlite3_result_double(context, p->sum/(double)p->cnt);
}
}
static void countFinalize(sqlite_func *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
- sqlite3_set_result_int(context, p ? p->n : 0);
+ sqlite3_result_int32(context, p ? p->n : 0);
}
/*
if( SQLITE3_NULL==sqlite3_value_type(argv[0]) ) return;
if( pBest->flags ){
+ /* This step function is used for both the min() and max() aggregates,
+ ** the only difference between the two being that the sense of the
+ ** comparison is inverted. For the max() aggregate, the
+ ** sqlite3_user_data() function returns (void *)-1. For min() it
+ ** returns (void *)db, where db is the sqlite3* database pointer.
+ ** Therefore the next statement sets variable 'max' to 1 for the max()
+ ** aggregate, or 0 for min().
+ */
max = ((sqlite3_user_data(context)==(void *)-1)?1:0);
cmp = sqlite3MemCompare(pBest, pArg, 0);
if( (max && cmp<0) || (!max && cmp>0) ){
- sqlite3MemCopy(pBest, pArg);
+ sqlite3VdbeMemCopy(pBest, pArg);
}
}else{
- sqlite3MemCopy(pBest, pArg);
+ sqlite3VdbeMemCopy(pBest, pArg);
}
}
static void minMaxFinalize(sqlite_func *context){
if( pRes->flags ){
switch( sqlite3_value_type(pRes) ){
case SQLITE3_INTEGER:
- sqlite3_set_result_int(context, sqlite3_value_int(pRes));
+ sqlite3_result_int32(context, sqlite3_value_int(pRes));
break;
case SQLITE3_FLOAT:
- sqlite3_set_result_double(context, sqlite3_value_float(pRes));
+ sqlite3_result_double(context, sqlite3_value_float(pRes));
case SQLITE3_TEXT:
case SQLITE3_BLOB:
- sqlite3_set_result_string(context,
- sqlite3_value_data(pRes),
- sqlite3_value_bytes(pRes));
+ sqlite3_result_text(context,
+ sqlite3_value_data(pRes), sqlite3_value_bytes(pRes), 1);
break;
case SQLITE3_NULL:
default:
p = sqlite3_aggregate_context(context, sizeof(*p));
MD5Final(digest,p);
DigestToBase16(digest, zBuf);
- sqlite3_set_result_string(context, zBuf, strlen(zBuf));
+ sqlite3_result_text(context, zBuf, -1, 1);
}
void Md5_Register(sqlite *db){
sqlite3_create_aggregate(db, "md5sum", -1, md5step, md5finalize, 0);
** This header file defines the interface that the SQLite library
** presents to client programs.
**
-** @(#) $Id: sqlite.h.in,v 1.74 2004/05/24 23:48:27 danielk1977 Exp $
+** @(#) $Id: sqlite.h.in,v 1.75 2004/05/25 11:47:26 danielk1977 Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#define SQLITE_TEXT (-2)
#define SQLITE_ARGS (-3)
-/*
-** The user function implementations call one of the following four routines
-** in order to return their results. The first parameter to each of these
-** routines is a copy of the first argument to xFunc() or xFinialize().
-** The second parameter to these routines is the result to be returned.
-** A NULL can be passed as the second parameter to sqlite3_set_result_string()
-** in order to return a NULL result.
-**
-** The 3rd argument to _string and _error is the number of characters to
-** take from the string. If this argument is negative, then all characters
-** up to and including the first '\000' are used.
-**
-** The sqlite3_set_result_string() function allocates a buffer to hold the
-** result and returns a pointer to this buffer. The calling routine
-** (that is, the implmentation of a user function) can alter the content
-** of this buffer if desired.
-*/
-char *sqlite3_set_result_string(sqlite_func*,const char*,int);
-void sqlite3_set_result_int(sqlite_func*,int);
-void sqlite3_set_result_double(sqlite_func*,double);
-void sqlite3_set_result_error(sqlite_func*,const char*,int);
-
-/*
-** The pUserData parameter to the sqlite3_create_function() and
-** sqlite3_create_aggregate() routines used to register user functions
-** is available to the implementation of the function using this
-** call.
-*/
-void *sqlite3_user_data(sqlite_func*);
-
/*
** Aggregate functions use the following routine to allocate
** a structure for storing their state. The first time this routine
*/
double sqlite3_value_float(sqlite3_value*);
+typedef sqlite_func sqlite3_context;
+
+void *sqlite3_get_context(sqlite3_context*, int nbyte);
+
+/*
+** The pUserData parameter to the sqlite3_create_function() and
+** sqlite3_create_aggregate() routines used to register user functions
+** is available to the implementation of the function using this
+** call.
+*/
+void *sqlite3_user_data(sqlite3_context*);
+
+/*
+** The following three functions may be called from within a user-defined
+** function callback or a user-defined aggregate finalizer callback. The
+** result of the user-defined function or aggregate is set to the value of
+** the second parameter. Any value previously set as the return value via
+** an sqlite3_result_*() call is overwritten.
+**
+** The first parameter to each of these routines must be a copy of the
+** sqlite3_context* pointer passed to the user-defined function or
+** aggregate finalizer function.
+*/
+void sqlite3_result_int32(sqlite3_context*, int);
+void sqlite3_result_int64(sqlite3_context*, long long int);
+void sqlite3_result_double(sqlite3_context*, double);
+
+/*
+** This function may be called from within a user-defined function callback
+** or a user-defined aggregate finalizer callback. The result of the
+** user-defined function or aggregate is set to NULL. Any value previously
+** set as the return value via an sqlite3_result_*() call is overwritten.
+**
+** The parameter to this routine must be a copy of the sqlite3_context*
+** pointer passed to the user-defined function or aggregate finalizer
+** function.
+*/
+void sqlite3_result_null(sqlite3_context*);
+
+/*
+** The following two functions may be called from within a user-defined or
+** a user-defined aggregate finalizer callback to return a text value.
+** The second parameter is a pointer to the string, encoded in UTF-8
+** for sqlite3_result_text() and UTF-16 (machine byte order) for
+** sqlite3_result_text16().
+**
+** If the third parameter, n, is positive, it is the number of bytes (not
+** characters) in the string data. A negative n value indicates that the
+** string may be read up to the nul terminator character.
+**
+** If the fourth parameter is non-zero, then a copy is made of the string.
+** Otherwise, SQLite stores a pointer to the original string data.
+**
+** The first parameter to this routine must be a copy of the
+** sqlite3_context* pointer passed to the user-defined function or
+** aggregate finalizer function.
+*/
+void sqlite3_result_text(sqlite3_context*, const char*, int n, int eCopy);
+void sqlite3_result_text16(sqlite3_context*, const void*, int n, int eCopy);
+
+/*
+** The following function may be called from within a user-defined or a
+** user-defined aggregate finalizer callback to return a blob value. The
+** second parameter is a pointer to the blob of data. The third parameter
+** is the number of bytes of data in the blob.
+**
+** If the fourth parameter is non-zero, then a copy is made of the blob.
+** Otherwise, SQLite stores a pointer to the original blob data.
+**
+** The first parameter to this routine must be a copy of the
+** sqlite3_context* pointer passed to the user-defined function or
+** aggregate finalizer function.
+*/
+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);
+
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
#endif
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.67 2004/05/24 12:39:02 danielk1977 Exp $
+** $Id: tclsqlite.c,v 1.68 2004/05/25 11:47:26 danielk1977 Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
}
rc = Tcl_Eval(p->interp, Tcl_DStringValue(&cmd));
if( rc ){
- sqlite3_set_result_error(context, Tcl_GetStringResult(p->interp), -1);
+ sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
}else{
- sqlite3_set_result_string(context, Tcl_GetStringResult(p->interp), -1);
+ sqlite3_result_text(context, Tcl_GetStringResult(p->interp), -1, 1);
}
}
#ifndef SQLITE_OMIT_AUTHORIZATION
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test1.c,v 1.49 2004/05/24 23:48:27 danielk1977 Exp $
+** $Id: test1.c,v 1.50 2004/05/25 11:47:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
int i;
for(i=0; i<argc; i++){
if( SQLITE3_NULL!=sqlite3_value_type(argv[i]) ){
- sqlite3_set_result_string(context, sqlite3_value_data(argv[i]), -1);
+ sqlite3_result_text(context, sqlite3_value_data(argv[i]), -1, 1);
break;
}
}
sqlite3_exec((sqlite*)sqlite3_user_data(context),
sqlite3_value_data(argv[0]),
execFuncCallback, &x, 0);
- sqlite3_set_result_string(context, x.z, x.nUsed);
+ sqlite3_result_text(context, x.z, x.nUsed, 1);
sqliteFree(x.z);
}
static void countFinalize(sqlite_func *context){
CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p));
- sqlite3_set_result_int(context, p ? p->n : 0);
+ sqlite3_result_int32(context, p ? p->n : 0);
}
/*
const char *zArg0 = sqlite3_value_data(argv[0]);
const char *zArg1 = sqlite3_value_data(argv[1]);
if( zArg0==0 ){
- sqlite3_set_result_error(context, "first argument to test function "
+ sqlite3_result_error(context, "first argument to test function "
"may not be NULL", -1);
}else if( sqlite3StrICmp(zArg0,"string")==0 ){
- sqlite3_set_result_string(context, zArg1, -1);
+ sqlite3_result_text(context, zArg1, -1, 1);
}else if( zArg1==0 ){
- sqlite3_set_result_error(context, "2nd argument may not be NULL if the "
+ sqlite3_result_error(context, "2nd argument may not be NULL if the "
"first argument is not \"string\"", -1);
}else if( sqlite3StrICmp(zArg0,"int")==0 ){
- sqlite3_set_result_int(context, atoi(zArg1));
+ sqlite3_result_int32(context, atoi(zArg1));
}else if( sqlite3StrICmp(zArg0,"double")==0 ){
- sqlite3_set_result_double(context, sqlite3AtoF(zArg1, 0));
+ sqlite3_result_double(context, sqlite3AtoF(zArg1, 0));
}else{
- sqlite3_set_result_error(context,"first argument should be one of: "
+ sqlite3_result_error(context,"first argument should be one of: "
"string int double", -1);
}
argc -= 2;
** 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.327 2004/05/24 23:48:27 danielk1977 Exp $
+** $Id: vdbe.c,v 1.328 2004/05/25 11:47:26 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
*/
int sqlite3_interrupt_count = 0;
+/*
+** This macro takes a single parameter, a pointer to a Mem structure.
+** It returns the string encoding for the Mem structure, one of TEXT_Utf8
+** 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 || 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)->i: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
/*
-** NulTermify
-** Stringify
-** Integerify
-** Realify
-** SetEncoding
-** Release
+** MemStr(Mem *pMem)
+** MemBlob(Mem *pMem)
+** MemBloblen(Mem *pMem)
+**
+** MemType(Mem *pMem)
+**
+** MemSetBlob
+** MemSetStr
+**
+** MemSetEnc
+** MemSetType
+**
+** MemCopy
*/
struct MemRecord {
char *zData; /* Serialized record */
for(i=0; i<pOp->p1; i++){
Mem *pVal = &pTos[0-i];
SetEncodingFlags(pVal, db->enc);
+ MemNulTerminate(pVal);
}
p->resOnStack = 1;
(*ctx.pFunc->xFunc)(&ctx, n, apVal);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
popStack(&pTos, n);
+
+ /* Copy the result of the function to the top of the stack */
pTos++;
*pTos = ctx.s;
- if( pTos->flags & MEM_Str ){
- pTos->flags |= MEM_Term;
- }
if( pTos->flags & MEM_Short ){
pTos->z = pTos->zShort;
}
+ /* If the function returned an error, throw an exception */
if( ctx.isError ){
sqlite3SetString(&p->zErrMsg,
(pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0);
}
if( pTos->flags&MEM_Str ){
- SetEncodingFlags(pTos, TEXT_Utf8);
SetEncoding(pTos, encToFlags(db->enc)|MEM_Term);
}
#define NBFS 32
/*
-** A single level of the stack or a single memory cell
-** is an instance of the following structure.
+** Internally, the vdbe manipulates nearly all SQL values as Mem
+** structures. Each Mem struct may cache multiple representations (string,
+** integer etc.) of the same value. A value (and therefore Mem structure)
+** has the following properties:
+**
+** Each value has a manifest type. The manifest type of the value stored
+** in a Mem struct is returned by the MemType(Mem*) macro. The type is
+** one of SQLITE3_NULL, SQLITE3_INTEGER, SQLITE3_REAL, SQLITE3_TEXT or
+** SQLITE3_BLOB.
*/
struct Mem {
i64 i; /* Integer value */
};
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.
+*/
+#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) ( \
+ ((p)->flags&MEM_Str) && \
+ !((p)->flags&MEM_Term) && \
+ sqlite3VdbeMemNulTerminate(p) )
+
/*
** Allowed values for Mem.flags.
**
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
-#define MEM_Struct 0x0020 /* Value is some kind of struct */
#define MEM_Term 0x0200 /* String has a nul terminator character */
int sqlite3VdbeIdxKeyCompare(Cursor*, int , const unsigned char*, int*);
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
-int sqlite3MemCopy(Mem*, const Mem*);
int sqlite3VdbeKeyCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeRowCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeSetEncoding(Mem *, u8);
+int sqlite3VdbeMemCopy(Mem*, const Mem*);
+int sqlite3VdbeMemNulTerminate(Mem *);
return &p->aOp[addr];
}
-/*
-** The following group or routines are employed by installable functions
-** to return their results.
-**
-** The sqlite3_set_result_string() routine can be used to return a string
-** value or to return a NULL. To return a NULL, pass in NULL for zResult.
-** A copy is made of the string before this routine returns so it is safe
-** to pass in an ephemeral string.
-**
-** sqlite3_set_result_error() works like sqlite3_set_result_string() except
-** that it signals a fatal error. The string argument, if any, is the
-** error message. If the argument is NULL a generic substitute error message
-** is used.
-**
-** The sqlite3_set_result_int() and sqlite3_set_result_double() set the return
-** value of the user function to an integer or a double.
-**
-** These routines are defined here in vdbe.c because they depend on knowing
-** the internals of the sqlite_func structure which is only defined in
-** this source file.
-*/
-char *sqlite3_set_result_string(sqlite_func *p, const char *zResult, int n){
- assert( !p->isStep );
- if( p->s.flags & MEM_Dyn ){
- sqliteFree(p->s.z);
- }
- if( zResult==0 ){
- p->s.flags = MEM_Null;
- n = 0;
- p->s.z = 0;
- p->s.n = 0;
- }else{
- if( n<0 ) n = strlen(zResult);
- if( n<NBFS-1 ){
- memcpy(p->s.zShort, zResult, n);
- p->s.zShort[n] = 0;
- p->s.flags = MEM_Utf8 | MEM_Str | MEM_Short;
- p->s.z = p->s.zShort;
- }else{
- p->s.z = sqliteMallocRaw( n+1 );
- if( p->s.z ){
- memcpy(p->s.z, zResult, n);
- p->s.z[n] = 0;
- }
- p->s.flags = MEM_Utf8 | MEM_Str | MEM_Dyn;
- }
- p->s.n = n+1;
- }
- return p->s.z;
-}
-void sqlite3_set_result_int(sqlite_func *p, int iResult){
- assert( !p->isStep );
- if( p->s.flags & MEM_Dyn ){
- sqliteFree(p->s.z);
- }
- p->s.i = iResult;
- p->s.flags = MEM_Int;
-}
-void sqlite3_set_result_double(sqlite_func *p, double rResult){
- assert( !p->isStep );
- if( p->s.flags & MEM_Dyn ){
- sqliteFree(p->s.z);
- }
- p->s.r = rResult;
- p->s.flags = MEM_Real;
-}
-void sqlite3_set_result_error(sqlite_func *p, const char *zMsg, int n){
- assert( !p->isStep );
- sqlite3_set_result_string(p, zMsg, n);
- p->isError = 1;
-}
-
/*
** Extract the user data from a sqlite_func structure and return a
** pointer to it.
*/
-void *sqlite3_user_data(sqlite_func *p){
+void *sqlite3_user_data(sqlite3_context *p){
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
return rc;
}
-/*
-** Copy the contents of memory cell pFrom into pTo.
-*/
-int sqlite3MemCopy(Mem *pTo, const Mem *pFrom){
- if( pTo->flags&MEM_Dyn ){
- sqliteFree(pTo->z);
- }
-
- 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;
-}
-
/*
** The following is the comparison function for (non-integer)
** keys in the btrees. This function returns negative, zero, or
}
return SQLITE_OK;
}
+
+/*
+** Parameter "enc" is one of TEXT_Utf8, TEXT_Utf16le or TEXT_Utf16be.
+** Return the corresponding MEM_Utf* value.
+*/
+static int encToFlags(u8 enc){
+ switch( enc ){
+ case TEXT_Utf8: return MEM_Utf8;
+ case TEXT_Utf16be: return MEM_Utf16be;
+ case TEXT_Utf16le: return MEM_Utf16le;
+ }
+ assert(0);
+}
+static u8 flagsToEnc(int flags){
+ switch( flags&(MEM_Utf8|MEM_Utf16be|MEM_Utf16le) ){
+ case MEM_Utf8: return TEXT_Utf8;
+ case MEM_Utf16le: return TEXT_Utf16le;
+ case MEM_Utf16be: return TEXT_Utf16be;
+ }
+ return 0;
+}
+
+/*
+** Delete any previous value and set the value stored in *pMem to NULL.
+*/
+void sqlite3VdbeMemSetNull(Mem *pMem){
+ if( pMem->flags&MEM_Dyn ){
+ sqliteFree(pMem->z);
+ }
+ 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){
+ MemSetNull(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){
+ MemSetNull(pMem);
+ pMem->r = val;
+ pMem->flags = MEM_Real;
+}
+
+/*
+** Copy the contents of memory cell pFrom into pTo.
+*/
+int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
+ if( pTo->flags&MEM_Dyn ){
+ sqliteFree(pTo->z);
+ }
+
+ 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;
+
+ if( !z ){
+ /* If z is NULL, just set *pMem to contain NULL. */
+ MemSetNull(pMem);
+ return SQLITE_OK;
+ }
+
+ tmp.z = (char *)z;
+ if( eCopy ){
+ tmp.flags = MEM_Ephem|MEM_Str;
+ }else{
+ tmp.flags = MEM_Static|MEM_Str;
+ }
+ tmp.flags |= encToFlags(enc);
+ tmp.n = n;
+ switch( enc ){
+ case 0:
+ tmp.flags |= MEM_Blob;
+ break;
+
+ case TEXT_Utf8:
+ tmp.flags |= MEM_Utf8;
+ if( n<0 ) tmp.n = strlen(z)+1;
+ tmp.flags |= ((tmp.z[tmp.n-1])?0:MEM_Term);
+ break;
+
+ case TEXT_Utf16le:
+ case TEXT_Utf16be:
+ tmp.flags |= (enc==TEXT_Utf16le?MEM_Utf16le:MEM_Utf16be);
+ if( n<0 ) tmp.n = sqlite3utf16ByteLen(z,-1)+1;
+ tmp.flags |= ((tmp.z[tmp.n-1]||tmp.z[tmp.n-2])?0:MEM_Term);
+ break;
+
+ default:
+ assert(0);
+ }
+ return sqlite3VdbeMemCopy(pMem, &tmp);
+}
+
+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;
+}
+
+/*
+** The following nine routines, named sqlite3_result_*(), are used to
+** return values or errors from user-defined functions and aggregate
+** operations. They are commented in the header file sqlite.h (sqlite.h.in)
+*/
+void sqlite3_result_int32(sqlite3_context *pCtx, int iVal){
+ MemSetInt(&pCtx->s, iVal);
+}
+void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
+ MemSetInt(&pCtx->s, iVal);
+}
+void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
+ MemSetReal(&pCtx->s, rVal);
+}
+void sqlite3_result_null(sqlite3_context *pCtx){
+ MemSetNull(&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_blob(
+ sqlite3_context *pCtx,
+ const void *z,
+ int n,
+ int eCopy
+){
+ assert( n>0 );
+ MemSetStr(&pCtx->s, z, n, 0, eCopy);
+}
+void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
+ pCtx->isError = 1;
+ MemSetStr(&pCtx->s, z, n, TEXT_Utf8, 1);
+}
+void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
+ pCtx->isError = 1;
+ MemSetStr(&pCtx->s, z, n, TEXT_Utf16, 1);
+}
+