Use the new API for returning values and errors from user functions. (CVS 1453)

FossilOrigin-Name: 4eccae03b4a7f37804fea30416579787c3584bb2
This commit is contained in:
danielk1977 2004-05-25 11:47:24 +00:00
parent 88208050b6
commit 7e18c259fe
11 changed files with 549 additions and 217 deletions

View File

@ -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

View File

@ -1 +1 @@
b77c268ebebd5401c3f519a72cfb81438207368c
4eccae03b4a7f37804fea30416579787c3584bb2

View File

@ -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);
}

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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 *);

View File

@ -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);
}