mirror of https://github.com/sqlite/sqlite
Use the new API for returning values and errors from user functions. (CVS 1453)
FossilOrigin-Name: 4eccae03b4a7f37804fea30416579787c3584bb2
This commit is contained in:
parent
88208050b6
commit
7e18c259fe
28
manifest
28
manifest
|
@ -1,5 +1,5 @@
|
|||
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
|
||||
|
@ -28,16 +28,16 @@ F src/btree.c 51dfa34da5f42762b228d7360cf3273ee403bce8
|
|||
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
|
||||
|
@ -54,11 +54,11 @@ F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53
|
|||
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
|
||||
|
@ -69,10 +69,10 @@ F src/update.c 1a5e9182596f3ea8c7a141e308a3d2a7e5689fee
|
|||
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
|
||||
|
@ -202,7 +202,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
|||
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
|
||||
|
|
|
@ -1 +1 @@
|
|||
b77c268ebebd5401c3f519a72cfb81438207368c
|
||||
4eccae03b4a7f37804fea30416579787c3584bb2
|
12
src/date.c
12
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.21 2004/05/24 12:39:02 danielk1977 Exp $
|
||||
** $Id: date.c,v 1.22 2004/05/25 11:47:25 danielk1977 Exp $
|
||||
**
|
||||
** NOTES:
|
||||
**
|
||||
|
@ -668,7 +668,7 @@ static void juliandayFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
DateTime x;
|
||||
if( isDate(argc, argv, &x)==0 ){
|
||||
computeJD(&x);
|
||||
sqlite3_set_result_double(context, x.rJD);
|
||||
sqlite3_result_double(context, x.rJD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,7 +684,7 @@ static void datetimeFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -699,7 +699,7 @@ static void timeFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,7 +714,7 @@ static void dateFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -834,7 +834,7 @@ static void strftimeFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
}
|
||||
}
|
||||
z[j] = 0;
|
||||
sqlite3_set_result_string(context, z, -1);
|
||||
sqlite3_result_text(context, z, -1, 1);
|
||||
if( z!=zBuf ){
|
||||
sqliteFree(z);
|
||||
}
|
||||
|
|
85
src/func.c
85
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.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>
|
||||
|
@ -53,7 +53,7 @@ static void minmaxFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
zBest = zArg;
|
||||
}
|
||||
}
|
||||
sqlite3_set_result_string(context, zBest, -1);
|
||||
sqlite3_result_text(context, zBest, -1, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -69,7 +69,7 @@ static void typeofFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -87,7 +87,7 @@ static void lengthFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
#else
|
||||
len = strlen(z);
|
||||
#endif
|
||||
sqlite3_set_result_int(context, len);
|
||||
sqlite3_result_int32(context, len);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -99,7 +99,7 @@ static void absFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -145,7 +145,7 @@ static void substrFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -165,7 +165,7 @@ static void roundFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -174,22 +174,28 @@ static void roundFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -201,7 +207,7 @@ static void ifnullFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +219,7 @@ static void ifnullFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -226,7 +232,7 @@ static void last_insert_rowid(
|
|||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -235,7 +241,7 @@ static void last_insert_rowid(
|
|||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -249,7 +255,7 @@ static void last_statement_change_count(
|
|||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -269,7 +275,7 @@ static void likeFunc(
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,7 +292,7 @@ static void globFunc(sqlite_func *context, int arg, sqlite3_value **argv){
|
|||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -299,7 +305,7 @@ static void nullifFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,7 +314,7 @@ static void nullifFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
** 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -326,9 +332,9 @@ static void quoteFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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;
|
||||
|
@ -344,7 +350,7 @@ static void quoteFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
}
|
||||
z[j++] = '\'';
|
||||
z[j] = 0;
|
||||
sqlite3_set_result_string(context, z, j);
|
||||
sqlite3_result_text(context, z, j, 1);
|
||||
sqliteFree(z);
|
||||
}
|
||||
}
|
||||
|
@ -382,9 +388,9 @@ static void soundexFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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
|
||||
|
@ -428,7 +434,7 @@ static void randStr(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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
|
||||
|
||||
|
@ -457,13 +463,13 @@ static void sumStep(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,7 +533,7 @@ static void countStep(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -552,13 +558,21 @@ static void minmaxStep(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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){
|
||||
|
@ -568,15 +582,14 @@ 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:
|
||||
|
|
|
@ -379,7 +379,7 @@ static void md5finalize(sqlite_func *context){
|
|||
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);
|
||||
|
|
124
src/sqlite.h.in
124
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.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_
|
||||
|
@ -464,36 +464,6 @@ int sqlite3_function_type(
|
|||
#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
|
||||
|
@ -1412,6 +1382,98 @@ long long int sqlite3_value_int(sqlite3_value*);
|
|||
*/
|
||||
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
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** 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 */
|
||||
|
||||
|
@ -396,9 +396,9 @@ static void tclSqlFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
}
|
||||
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
|
||||
|
|
20
src/test1.c
20
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.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"
|
||||
|
@ -311,7 +311,7 @@ static void ifnullFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ static void sqlite3ExecFunc(
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -441,7 +441,7 @@ static void countStep(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -658,19 +658,19 @@ static void testFunc(sqlite_func *context, int argc, sqlite3_value **argv){
|
|||
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;
|
||||
|
|
117
src/vdbe.c
117
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.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"
|
||||
|
@ -69,14 +69,109 @@ int sqlite3_search_count = 0;
|
|||
*/
|
||||
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 */
|
||||
|
@ -2012,6 +2107,7 @@ case OP_Callback: {
|
|||
for(i=0; i<pOp->p1; i++){
|
||||
Mem *pVal = &pTos[0-i];
|
||||
SetEncodingFlags(pVal, db->enc);
|
||||
MemNulTerminate(pVal);
|
||||
}
|
||||
|
||||
p->resOnStack = 1;
|
||||
|
@ -2274,14 +2370,14 @@ case OP_Function: {
|
|||
(*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);
|
||||
|
@ -2289,7 +2385,6 @@ case OP_Function: {
|
|||
}
|
||||
|
||||
if( pTos->flags&MEM_Str ){
|
||||
SetEncodingFlags(pTos, TEXT_Utf8);
|
||||
SetEncoding(pTos, encToFlags(db->enc)|MEM_Term);
|
||||
}
|
||||
|
||||
|
|
|
@ -117,8 +117,15 @@ struct Sorter {
|
|||
#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 */
|
||||
|
@ -130,6 +137,33 @@ 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.
|
||||
*/
|
||||
#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.
|
||||
**
|
||||
|
@ -147,7 +181,6 @@ typedef struct Mem Mem;
|
|||
#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 */
|
||||
|
||||
|
@ -361,9 +394,10 @@ int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
|||
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 *);
|
||||
|
|
328
src/vdbeaux.c
328
src/vdbeaux.c
|
@ -424,83 +424,11 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
|
|||
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;
|
||||
}
|
||||
|
@ -1461,33 +1389,6 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
|
|||
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
|
||||
|
@ -1753,3 +1654,230 @@ int sqlite3VdbeIdxKeyCompare(
|
|||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue