diff options
author | drh <drh@noemail.net> | 2004-05-26 16:54:42 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2004-05-26 16:54:42 +0000 |
commit | f9b596ebc05ff3365bed6b8dafb02d251c652889 (patch) | |
tree | db56a7ae7dafee19f1d8fe3f947333c0914a7e0e /src | |
parent | b77f5dadbf3e34d9724c836c6871955b59694123 (diff) | |
download | sqlite-f9b596ebc05ff3365bed6b8dafb02d251c652889.tar.gz sqlite-f9b596ebc05ff3365bed6b8dafb02d251c652889.zip |
Remove dataType and includeTypes flags from function definitions. Added new
P3_FUNCDEF type for P3 arguments on opcodes. Fixes to several user functions.
28 tests fail now. (CVS 1464)
FossilOrigin-Name: 36e031625995b2f7baf7654d771ca8fb764a0085
Diffstat (limited to 'src')
-rw-r--r-- | src/date.c | 49 | ||||
-rw-r--r-- | src/expr.c | 28 | ||||
-rw-r--r-- | src/func.c | 312 | ||||
-rw-r--r-- | src/main.c | 20 | ||||
-rw-r--r-- | src/select.c | 6 | ||||
-rw-r--r-- | src/sqlite.h.in | 29 | ||||
-rw-r--r-- | src/sqliteInt.h | 45 | ||||
-rw-r--r-- | src/tclsqlite.c | 6 | ||||
-rw-r--r-- | src/vdbe.c | 5 | ||||
-rw-r--r-- | src/vdbe.h | 7 | ||||
-rw-r--r-- | src/vdbeaux.c | 17 |
11 files changed, 252 insertions, 272 deletions
diff --git a/src/date.c b/src/date.c index 935b08690..3a15ba163 100644 --- a/src/date.c +++ b/src/date.c @@ -16,7 +16,7 @@ ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: date.c,v 1.24 2004/05/26 06:18:37 danielk1977 Exp $ +** $Id: date.c,v 1.25 2004/05/26 16:54:42 drh Exp $ ** ** NOTES: ** @@ -664,7 +664,11 @@ static int isDate(int argc, sqlite3_value **argv, DateTime *p){ ** ** Return the julian day number of the date specified in the arguments */ -static void juliandayFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void juliandayFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ DateTime x; if( isDate(argc, argv, &x)==0 ){ computeJD(&x); @@ -677,7 +681,11 @@ static void juliandayFunc(sqlite3_context *context, int argc, sqlite3_value **ar ** ** Return YYYY-MM-DD HH:MM:SS */ -static void datetimeFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void datetimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; @@ -693,7 +701,11 @@ static void datetimeFunc(sqlite3_context *context, int argc, sqlite3_value **arg ** ** Return HH:MM:SS */ -static void timeFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void timeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; @@ -708,7 +720,11 @@ static void timeFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ ** ** Return YYYY-MM-DD */ -static void dateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void dateFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; @@ -737,7 +753,11 @@ static void dateFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ ** %Y year 0000-9999 ** %% % */ -static void strftimeFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void strftimeFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ DateTime x; int n, i, j; char *z; @@ -852,15 +872,14 @@ void sqlite3RegisterDateTimeFunctions(sqlite *db){ static struct { char *zName; int nArg; - int dataType; void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } aFuncs[] = { #ifndef SQLITE_OMIT_DATETIME_FUNCS - { "julianday", -1, SQLITE_NUMERIC, juliandayFunc }, - { "date", -1, SQLITE_TEXT, dateFunc }, - { "time", -1, SQLITE_TEXT, timeFunc }, - { "datetime", -1, SQLITE_TEXT, datetimeFunc }, - { "strftime", -1, SQLITE_TEXT, strftimeFunc }, + { "julianday", -1, juliandayFunc }, + { "date", -1, dateFunc }, + { "time", -1, timeFunc }, + { "datetime", -1, datetimeFunc }, + { "strftime", -1, strftimeFunc }, #endif }; int i; @@ -868,11 +887,5 @@ void sqlite3RegisterDateTimeFunctions(sqlite *db){ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, 0, 0, 0, aFuncs[i].xFunc, 0, 0); - if( aFuncs[i].xFunc ){ - sqlite3_function_type(db, aFuncs[i].zName, aFuncs[i].dataType); - } } } - - - diff --git a/src/expr.c b/src/expr.c index c774f73a5..8a97ca9e0 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.127 2004/05/21 13:39:51 drh Exp $ +** $Id: expr.c,v 1.128 2004/05/26 16:54:43 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -503,7 +503,6 @@ int sqlite3IsRowid(const char *z){ ** pExpr->iTable Set to the cursor number for the table obtained ** from pSrcList. ** pExpr->iColumn Set to the column number within the table. -** pExpr->dataType Set to the appropriate data type for the column. ** pExpr->op Set to TK_COLUMN. ** pExpr->pLeft Any expression this points to is deleted ** pExpr->pRight Any expression this points to is deleted. @@ -1224,13 +1223,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ getFunctionName(pExpr, &zId, &nId); pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, 0); assert( pDef!=0 ); - nExpr = sqlite3ExprCodeExprList(pParse, pList, pDef->includeTypes); + nExpr = sqlite3ExprCodeExprList(pParse, pList); /* FIX ME: The following is a temporary hack. */ if( 0==sqlite3StrNICmp(zId, "classof", nId) ){ assert( nExpr==1 ); sqlite3VdbeAddOp(v, OP_Class, nExpr, 0); }else{ - sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_POINTER); + sqlite3VdbeOp3(v, OP_Function, nExpr, 0, (char*)pDef, P3_FUNCDEF); } break; } @@ -1346,16 +1345,13 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){ /* ** Generate code that pushes the value of every element of the given -** expression list onto the stack. If the includeTypes flag is true, -** then also push a string that is the datatype of each element onto -** the stack after the value. +** expression list onto the stack. ** ** Return the number of elements pushed onto the stack. */ int sqlite3ExprCodeExprList( Parse *pParse, /* Parsing context */ - ExprList *pList, /* The expression list to be coded */ - int includeTypes /* TRUE to put datatypes on the stack too */ + ExprList *pList /* The expression list to be coded */ ){ struct ExprList_item *pItem; int i, n; @@ -1365,12 +1361,8 @@ int sqlite3ExprCodeExprList( n = pList->nExpr; for(pItem=pList->a, i=0; i<n; i++, pItem++){ sqlite3ExprCode(pParse, pItem->pExpr); - if( includeTypes ){ - /** DEPRECATED. This will go away with the new function interface **/ - sqlite3VdbeOp3(v, OP_String, 0, 0, "numeric", P3_STATIC); - } } - return includeTypes ? n*2 : n; + return n; } /* @@ -1714,11 +1706,13 @@ FuncDef *sqlite3FindFunction( assert( createFlag==0 ); return pMaybe; } - if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)))!=0 ){ + if( p==0 && createFlag && (p = sqliteMalloc(sizeof(*p)+nName+1))!=0 ){ p->nArg = nArg; p->pNext = pFirst; - p->dataType = pFirst ? pFirst->dataType : SQLITE_NUMERIC; - sqlite3HashInsert(&db->aFunc, zName, nName, (void*)p); + p->zName = (char*)&p[1]; + memcpy(p->zName, zName, nName); + p->zName[nName] = 0; + sqlite3HashInsert(&db->aFunc, p->zName, nName, (void*)p); } return p; } diff --git a/src/func.c b/src/func.c index 65789a6fb..7aaee79a3 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.56 2004/05/26 06:18:37 danielk1977 Exp $ +** $Id: func.c,v 1.57 2004/05/26 16:54:43 drh Exp $ */ #include <ctype.h> #include <math.h> @@ -29,45 +29,41 @@ /* ** Implementation of the non-aggregate min() and max() functions */ -static void minmaxFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ - const char *zBest; +static void minmaxFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ int i; - int (*xCompare)(const char*, const char*); int mask; /* 0 for min() or 0xffffffff for max() */ - const char *zArg; + int iBest; if( argc==0 ) return; mask = (int)sqlite3_user_data(context); - zBest = sqlite3_value_data(argv[0]); - if( zBest==0 ) return; - zArg = sqlite3_value_data(argv[1]); - if( zArg[0]=='n' ){ - xCompare = sqlite3Compare; - }else{ - xCompare = strcmp; - } - for(i=2; i<argc; i+=2){ - zArg = sqlite3_value_data(argv[i]); - if( zArg==0 ) return; - if( (xCompare(zArg, zBest)^mask)<0 ){ - zBest = zArg; + iBest = 0; + for(i=1; i<argc; i++){ + if( (sqlite3MemCompare(argv[iBest], argv[i], 0)^mask)<0 ){ + iBest = i; } } - sqlite3_result_text(context, zBest, -1, 1); + sqlite3_result(context, argv[iBest]); } /* ** Return the type of the argument. */ -static void typeofFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void typeofFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ const char *z = 0; - assert( argc==2 ); switch( sqlite3_value_type(argv[0]) ){ - case SQLITE3_NULL: z = "null" ; break; - case SQLITE3_INTEGER: z = "integer" ; break; - case SQLITE3_TEXT: z = "text" ; break; - case SQLITE3_FLOAT: z = "real" ; break; - case SQLITE3_BLOB: z = "blob" ; break; + case SQLITE3_NULL: z = "null"; break; + case SQLITE3_INTEGER: z = "integer"; break; + case SQLITE3_TEXT: z = "text"; break; + case SQLITE3_FLOAT: z = "real"; break; + case SQLITE3_BLOB: z = "blob"; break; } sqlite3_result_text(context, z, -1, 0); } @@ -75,19 +71,33 @@ static void typeofFunc(sqlite3_context *context, int argc, sqlite3_value **argv) /* ** Implementation of the length() function */ -static void lengthFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void lengthFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ const char *z; int len; assert( argc==1 ); - z = sqlite3_value_data(argv[0]); - if( z==0 ) return; -#ifdef SQLITE_UTF8 - for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } -#else - len = strlen(z); -#endif - sqlite3_result_int32(context, len); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE3_BLOB: + case SQLITE3_INTEGER: + case SQLITE3_FLOAT: { + sqlite3_result_int32(context, sqlite3_value_bytes(argv[0])); + break; + } + case SQLITE3_TEXT: { + const char *z = sqlite3_value_data(argv[0]); + for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } + sqlite3_result_int32(context, len); + break; + } + default: { + sqlite3_result_null(context); + break; + } + } } /* @@ -96,32 +106,41 @@ static void lengthFunc(sqlite3_context *context, int argc, sqlite3_value **argv) static void absFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *z; assert( argc==1 ); - z = sqlite3_value_data(argv[0]); - if( z==0 ) return; - if( z[0]=='-' && isdigit(z[1]) ) z++; - sqlite3_result_text(context, z, -1, 1); + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE3_INTEGER: { + sqlite3_result_int64(context, -sqlite3_value_int(argv[0])); + break; + } + case SQLITE3_NULL: { + sqlite3_result_null(context); + break; + } + default: { + sqlite3_result_double(context, -sqlite3_value_float(argv[0])); + break; + } + } } /* ** Implementation of the substr() function */ -static void substrFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void substrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ const char *z; -#ifdef SQLITE_UTF8 const char *z2; int i; -#endif int p1, p2, len; + assert( argc==3 ); z = sqlite3_value_data(argv[0]); if( z==0 ) return; p1 = sqlite3_value_int(argv[1]); p2 = sqlite3_value_int(argv[2]); -#ifdef SQLITE_UTF8 for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z2)!=0x80 ) len++; } -#else - len = strlen(z); -#endif if( p1<0 ){ p1 += len; if( p1<0 ){ @@ -134,7 +153,6 @@ static void substrFunc(sqlite3_context *context, int argc, sqlite3_value **argv) if( p1+p2>len ){ p2 = len-p1; } -#ifdef SQLITE_UTF8 for(i=0; i<p1 && z[i]; i++){ if( (z[i]&0xc0)==0x80 ) p1++; } @@ -143,7 +161,6 @@ static void substrFunc(sqlite3_context *context, int argc, sqlite3_value **argv) if( (z[i]&0xc0)==0x80 ) p2++; } while( z[i] && (z[i]&0xc0)==0x80 ){ i++; p2++; } -#endif if( p2<0 ) p2 = 0; sqlite3_result_text(context, &z[p1], p2, 1); } @@ -203,11 +220,15 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ ** All three do the same thing. They return the first non-NULL ** argument. */ -static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void ifnullFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ int i; for(i=0; i<argc; i++){ if( SQLITE3_NULL!=sqlite3_value_type(argv[i]) ){ - sqlite3_result_text(context, sqlite3_value_data(argv[i]), -1, 1); + sqlite3_result(context, argv[i]); break; } } @@ -216,7 +237,11 @@ static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv) /* ** Implementation of random(). Return a random integer. */ -static void randomFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void randomFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ int r; sqlite3Randomness(sizeof(r), &r); sqlite3_result_int32(context, r); @@ -232,14 +257,18 @@ static void last_insert_rowid( sqlite3_value **argv ){ sqlite *db = sqlite3_user_data(context); - sqlite3_result_int32(context, sqlite3_last_insert_rowid(db)); + sqlite3_result_int64(context, sqlite3_last_insert_rowid(db)); } /* ** Implementation of the change_count() SQL function. The return ** value is the same as the sqlite3_changes() API function. */ -static void change_count(sqlite3_context *context, int arg, sqlite3_value **argv){ +static void change_count( + sqlite3_context *context, + int arg, + sqlite3_value **argv +){ sqlite *db = sqlite3_user_data(context); sqlite3_result_int32(context, sqlite3_changes(db)); } @@ -301,11 +330,13 @@ static void globFunc(sqlite3_context *context, int arg, sqlite3_value **argv){ ** argument if the arguments are different. The result is NULL if the ** arguments are equal to each other. */ -static void nullifFunc(sqlite3_context *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_result_text(context, zX, -1, 1); +static void nullifFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + if( sqlite3MemCompare(argv[0], argv[1], 0)!=0 ){ + sqlite3_result(context, argv[0]); } } @@ -313,7 +344,11 @@ static void nullifFunc(sqlite3_context *context, int argc, sqlite3_value **argv) ** Implementation of the VERSION(*) function. The result is the version ** of the SQLite library that is running. */ -static void versionFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ +static void versionFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ sqlite3_result_text(context, sqlite3_version, -1, 0); } @@ -331,27 +366,37 @@ static void versionFunc(sqlite3_context *context, int argc, sqlite3_value **argv static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){ const char *zArg = sqlite3_value_data(argv[0]); if( argc<1 ) return; - if( zArg==0 ){ - sqlite3_result_text(context, "NULL", 4, 0); - }else if( sqlite3IsNumber(zArg, 0, TEXT_Utf8) ){ - sqlite3_result_text(context, zArg, -1, 1); - }else{ - int i,j,n; - char *z; - for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } - z = sqliteMalloc( i+n+3 ); - if( z==0 ) return; - z[0] = '\''; - for(i=0, j=1; zArg[i]; i++){ - z[j++] = zArg[i]; - if( zArg[i]=='\'' ){ - z[j++] = '\''; + switch( sqlite3_value_type(argv[0]) ){ + case SQLITE3_NULL: { + sqlite3_result_text(context, "NULL", 4, 0); + break; + } + case SQLITE3_INTEGER: + case SQLITE3_FLOAT: { + sqlite3_result(context, argv[0]); + break; + } + case SQLITE3_BLOB: /*** FIX ME. Use a BLOB encoding ***/ + case SQLITE3_TEXT: { + int i,j,n; + const char *zArg = sqlite3_value_data(argv[0]); + char *z; + + for(i=n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; } + z = sqliteMalloc( i+n+3 ); + if( z==0 ) return; + z[0] = '\''; + for(i=0, j=1; zArg[i]; i++){ + z[j++] = zArg[i]; + if( zArg[i]=='\'' ){ + z[j++] = '\''; + } } + z[j++] = '\''; + z[j] = 0; + sqlite3_result_text(context, z, j, 1); + sqliteFree(z); } - z[j++] = '\''; - z[j] = 0; - sqlite3_result_text(context, z, j, 1); - sqliteFree(z); } } @@ -409,14 +454,14 @@ static void randStr(sqlite3_context *context, int argc, sqlite3_value **argv){ int iMin, iMax, n, r, i; unsigned char zBuf[1000]; if( argc>=1 ){ - iMin = atoi(sqlite3_value_data(argv[0])); + iMin = sqlite3_value_int(argv[0]); if( iMin<0 ) iMin = 0; if( iMin>=sizeof(zBuf) ) iMin = sizeof(zBuf)-1; }else{ iMin = 1; } if( argc>=2 ){ - iMax = atoi(sqlite3_value_data(argv[1])); + iMax = sqlite3_value_int(argv[1]); if( iMax<iMin ) iMax = iMin; if( iMax>=sizeof(zBuf) ) iMax = sizeof(zBuf)-1; }else{ @@ -578,23 +623,8 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv) static void minMaxFinalize(sqlite3_context *context){ sqlite3_value *pRes; pRes = (sqlite3_value *)sqlite3_get_context(context, sizeof(Mem)); - if( pRes->flags ){ - switch( sqlite3_value_type(pRes) ){ - case SQLITE3_INTEGER: - sqlite3_result_int32(context, sqlite3_value_int(pRes)); - break; - case SQLITE3_FLOAT: - sqlite3_result_double(context, sqlite3_value_float(pRes)); - case SQLITE3_TEXT: - case SQLITE3_BLOB: - sqlite3_result_text(context, - sqlite3_value_data(pRes), sqlite3_value_bytes(pRes), 1); - break; - case SQLITE3_NULL: - default: - assert(0); - } + sqlite3_result(context, pRes); } } @@ -607,90 +637,70 @@ void sqlite3RegisterBuiltinFunctions(sqlite *db){ static struct { char *zName; signed char nArg; - signed char dataType; u8 argType; /* 0: none. 1: db 2: (-1) */ void (*xFunc)(sqlite3_context*,int,sqlite3_value **); } aFuncs[] = { - { "min", -1, SQLITE_ARGS, 0, minmaxFunc }, - { "min", 0, 0, 0, 0 }, - { "max", -1, SQLITE_ARGS, 2, minmaxFunc }, - { "max", 0, 0, 2, 0 }, - { "typeof", 1, SQLITE_TEXT, 0, typeofFunc }, - { "classof", 1, SQLITE_TEXT, 0, typeofFunc }, /* FIX ME: hack */ - { "length", 1, SQLITE_NUMERIC, 0, lengthFunc }, - { "substr", 3, SQLITE_TEXT, 0, substrFunc }, - { "abs", 1, SQLITE_NUMERIC, 0, absFunc }, - { "round", 1, SQLITE_NUMERIC, 0, roundFunc }, - { "round", 2, SQLITE_NUMERIC, 0, roundFunc }, - { "upper", 1, SQLITE_TEXT, 0, upperFunc }, - { "lower", 1, SQLITE_TEXT, 0, lowerFunc }, - { "coalesce", -1, SQLITE_ARGS, 0, ifnullFunc }, - { "coalesce", 0, 0, 0, 0 }, - { "coalesce", 1, 0, 0, 0 }, - { "ifnull", 2, SQLITE_ARGS, 0, ifnullFunc }, - { "random", -1, SQLITE_NUMERIC, 0, randomFunc }, - { "like", 2, SQLITE_NUMERIC, 0, likeFunc }, - { "glob", 2, SQLITE_NUMERIC, 0, globFunc }, - { "nullif", 2, SQLITE_ARGS, 0, nullifFunc }, - { "sqlite_version",0,SQLITE_TEXT, 0, versionFunc}, - { "quote", 1, SQLITE_ARGS, 0, quoteFunc }, - { "last_insert_rowid", 0, SQLITE_NUMERIC, 1, last_insert_rowid }, - { "change_count", 0, SQLITE_NUMERIC, 1, change_count }, - { "last_statement_change_count", - 0, SQLITE_NUMERIC, 1, last_statement_change_count }, + { "min", -1, 0, minmaxFunc }, + { "min", 0, 0, 0 }, + { "max", -1, 2, minmaxFunc }, + { "max", 0, 2, 0 }, + { "typeof", 1, 0, typeofFunc }, + { "classof", 1, 0, typeofFunc }, /* FIX ME: hack */ + { "length", 1, 0, lengthFunc }, + { "substr", 3, 0, substrFunc }, + { "abs", 1, 0, absFunc }, + { "round", 1, 0, roundFunc }, + { "round", 2, 0, roundFunc }, + { "upper", 1, 0, upperFunc }, + { "lower", 1, 0, lowerFunc }, + { "coalesce", -1, 0, ifnullFunc }, + { "coalesce", 0, 0, 0 }, + { "coalesce", 1, 0, 0 }, + { "ifnull", 2, 0, ifnullFunc }, + { "random", -1, 0, randomFunc }, + { "like", 2, 0, likeFunc }, + { "glob", 2, 0, globFunc }, + { "nullif", 2, 0, nullifFunc }, + { "sqlite_version", 0, 0, versionFunc}, + { "quote", 1, 0, quoteFunc }, + { "last_insert_rowid", 0, 1, last_insert_rowid }, + { "change_count", 0, 1, change_count }, + { "last_statement_change_count", 0, 1, last_statement_change_count }, #ifdef SQLITE_SOUNDEX - { "soundex", 1, SQLITE_TEXT, 0, soundexFunc}, + { "soundex", 1, 0, soundexFunc}, #endif #ifdef SQLITE_TEST - { "randstr", 2, SQLITE_TEXT, 0, randStr }, + { "randstr", 2, 0, randStr }, #endif }; static struct { char *zName; signed char nArg; - signed char dataType; u8 argType; void (*xStep)(sqlite3_context*,int,sqlite3_value**); void (*xFinalize)(sqlite3_context*); } aAggs[] = { - { "min", 1, 0, 0, minmaxStep, minMaxFinalize }, - { "max", 1, 0, 2, minmaxStep, minMaxFinalize }, - { "sum", 1, SQLITE_NUMERIC, 0, sumStep, sumFinalize }, - { "avg", 1, SQLITE_NUMERIC, 0, sumStep, avgFinalize }, - { "count", 0, SQLITE_NUMERIC, 0, countStep, countFinalize }, - { "count", 1, SQLITE_NUMERIC, 0, countStep, countFinalize }, + { "min", 1, 0, minmaxStep, minMaxFinalize }, + { "max", 1, 2, minmaxStep, minMaxFinalize }, + { "sum", 1, 0, sumStep, sumFinalize }, + { "avg", 1, 0, sumStep, avgFinalize }, + { "count", 0, 0, countStep, countFinalize }, + { "count", 1, 0, countStep, countFinalize }, #if 0 - { "stddev", 1, SQLITE_NUMERIC, 0, stdDevStep, stdDevFinalize }, + { "stddev", 1, 0, stdDevStep, stdDevFinalize }, #endif }; - static const char *azTypeFuncs[] = { "min", "max", "typeof" }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ void *pArg = aFuncs[i].argType==2 ? (void*)(-1) : db; sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, 0, 0, pArg, aFuncs[i].xFunc, 0, 0); - if( aFuncs[i].xFunc ){ - sqlite3_function_type(db, aFuncs[i].zName, aFuncs[i].dataType); - } } for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ void *pArg = aAggs[i].argType==2 ? (void*)(-1) : db; sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, 0, 0, pArg, 0, aAggs[i].xStep, aAggs[i].xFinalize); - sqlite3_function_type(db, aAggs[i].zName, aAggs[i].dataType); - } - - for(i=0; i<sizeof(azTypeFuncs)/sizeof(azTypeFuncs[0]); i++){ - int n = strlen(azTypeFuncs[i]); - FuncDef *p = sqlite3HashFind(&db->aFunc, azTypeFuncs[i], n); - while( p ){ - p->includeTypes = 1; - p = p->pNext; - } } sqlite3RegisterDateTimeFunctions(db); } - - - diff --git a/src/main.c b/src/main.c index 8a4f5ce99..e9c87aab2 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.193 2004/05/26 10:11:06 danielk1977 Exp $ +** $Id: main.c,v 1.194 2004/05/26 16:54:43 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -412,7 +412,7 @@ static int binaryCollatingFunc( /* ** Return the ROWID of the most recent insert */ -int sqlite3_last_insert_rowid(sqlite *db){ +long long int sqlite3_last_insert_rowid(sqlite *db){ return db->lastRowid; } @@ -696,20 +696,6 @@ int sqlite3_create_function16( } /* -** Change the datatype for all functions with a given name. See the -** header comment for the prototype of this function in sqlite.h for -** additional information. -*/ -int sqlite3_function_type(sqlite *db, const char *zName, int dataType){ - FuncDef *p = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, strlen(zName)); - while( p ){ - p->dataType = dataType; - p = p->pNext; - } - return SQLITE_OK; -} - -/* ** Register a trace function. The pArg from the previously registered trace ** is returned. ** @@ -1028,7 +1014,7 @@ static int openDatabase( db->aDb = db->aDbStatic; db->enc = def_enc; /* db->flags |= SQLITE_ShortColNames; */ - sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 1); + sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); for(i=0; i<db->nDb; i++){ sqlite3HashInit(&db->aDb[i].tblHash, SQLITE_HASH_STRING, 0); diff --git a/src/select.c b/src/select.c index 2340cb5b4..36431d91e 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.177 2004/05/26 10:11:06 danielk1977 Exp $ +** $Id: select.c,v 1.178 2004/05/26 16:54:44 drh Exp $ */ #include "sqliteInt.h" @@ -2338,7 +2338,7 @@ int sqlite3Select( for(i=0; i<pParse->nAgg; i++){ FuncDef *pFunc; if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){ - sqlite3VdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_POINTER); + sqlite3VdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_FUNCDEF); } } if( pGroupBy==0 ){ @@ -2412,7 +2412,7 @@ int sqlite3Select( pE = pAgg->pExpr; assert( pE!=0 ); assert( pE->op==TK_AGG_FUNCTION ); - nExpr = sqlite3ExprCodeExprList(pParse, pE->pList, pDef->includeTypes); + nExpr = sqlite3ExprCodeExprList(pParse, pE->pList); sqlite3VdbeAddOp(v, OP_Integer, i, 0); sqlite3VdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_POINTER); } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index a1d8f7649..027ba7346 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.80 2004/05/26 06:18:38 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.81 2004/05/26 16:54:44 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -163,7 +163,7 @@ int sqlite3_exec( ** ** This function is similar to the mysql_insert_id() function from MySQL. */ -int sqlite3_last_insert_rowid(sqlite*); +long long int sqlite3_last_insert_rowid(sqlite*); /* ** This function returns the number of database rows that were changed @@ -1125,26 +1125,6 @@ int sqlite3_create_function16( ); /* -** Use the following routine to define the datatype returned by a -** user-defined function. The second argument can be one of the -** constants SQLITE_NUMERIC, SQLITE_TEXT, or SQLITE_ARGS or it -** can be an integer greater than or equal to zero. When the datatype -** parameter is non-negative, the type of the result will be the -** same as the datatype-th argument. If datatype==SQLITE_NUMERIC -** then the result is always numeric. If datatype==SQLITE_TEXT then -** the result is always text. If datatype==SQLITE_ARGS then the result -** is numeric if any argument is numeric and is text otherwise. -*/ -int sqlite3_function_type( - sqlite *db, /* The database there the function is registered */ - const char *zName, /* Name of the function */ - int datatype /* The datatype for this function */ -); -#define SQLITE_NUMERIC (-1) -#define SQLITE_TEXT (-2) -#define SQLITE_ARGS (-3) - -/* ** The next routine returns the number of calls to xStep for a particular ** aggregate function instance. The current call to xStep counts so this ** routine always returns at least 1. @@ -1323,6 +1303,11 @@ void sqlite3_result_blob(sqlite3_context*, const void*, int n, int eCopy); void sqlite3_result_error(sqlite3_context*, const char*, int); void sqlite3_result_error16(sqlite3_context*, const void*, int); +/* +** Copy a function parameter into the result of the function. +*/ +void sqlite3_result(sqlite3_context*, sqlite3_value*); + #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3a94128be..e23710e78 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.252 2004/05/26 06:58:44 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.253 2004/05/26 16:54:45 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -160,20 +160,15 @@ extern const int sqlite3one; /* ** The maximum number of bytes of data that can be put into a single -** row of a single table. The upper bound on this limit is 16777215 -** bytes (or 16MB-1). We have arbitrarily set the limit to just 1MB -** here because the overflow page chain is inefficient for really big -** records and we want to discourage people from thinking that +** row of a single table. The upper bound on this limit is +** 9223372036854775808 bytes (or 2**63). We have arbitrarily set the +** limit to just 1MB here because the overflow page chain is inefficient +** for really big records and we want to discourage people from thinking that ** multi-megabyte records are OK. If your needs are different, you can ** change this define and recompile to increase or decrease the record ** size. -** -** The 16777198 is computed as follows: 238 bytes of payload on the -** original pages plus 16448 overflow pages each holding 1020 bytes of -** data. */ #define MAX_BYTES_PER_ROW 1048576 -/* #define MAX_BYTES_PER_ROW 16777198 */ /* ** If memory allocation problems are found, recompile with @@ -334,18 +329,6 @@ struct Db { /* ** Each database is an instance of the following structure. ** -** The sqlite.file_format is initialized by the database file -** and helps determines how the data in the database file is -** represented. This field allows newer versions of the library -** to read and write older databases. The various file formats -** are as follows: -** -** file_format==1 Version 2.1.0. -** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. -** file_format==3 Version 2.6.0. Fix empty-string index bug. -** file_format==4 Version 2.7.0. Add support for separate numeric and -** text datatypes. -** ** The sqlite.temp_store determines where temporary database files ** are stored. If 1, then a file is created to hold those tables. If ** 2, then they are held in memory. 0 means use the default value in @@ -462,15 +445,13 @@ struct sqlite { ** points to a linked list of these structures. */ struct FuncDef { - void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ - void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate function step */ - void (*xFinalize)(sqlite3_context*); /* Aggregate function finializer */ - signed char nArg; /* Number of arguments. -1 means unlimited */ - signed char dataType; /* Arg that determines datatype. -1=NUMERIC, */ - /* -2=TEXT. -3=SQLITE_ARGS */ - u8 includeTypes; /* Add datatypes to args of xFunc and xStep */ - void *pUserData; /* User data parameter */ - FuncDef *pNext; /* Next function with same name */ + char *zName; /* SQL name of the function */ + int nArg; /* Number of arguments. -1 means unlimited */ + void *pUserData; /* User data parameter */ + FuncDef *pNext; /* Next function with same name */ + void (*xFunc)(sqlite3_context*,int,sqlite3_value**); /* Regular function */ + void (*xStep)(sqlite3_context*,int,sqlite3_value**); /* Aggregate step */ + void (*xFinalize)(sqlite3_context*); /* Aggregate finializer */ }; /* @@ -1256,7 +1237,7 @@ void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**); void sqlite3WhereEnd(WhereInfo*); void sqlite3ExprCode(Parse*, Expr*); -int sqlite3ExprCodeExprList(Parse*, ExprList*, int); +int sqlite3ExprCodeExprList(Parse*, ExprList*); void sqlite3ExprIfTrue(Parse*, Expr*, int, int); void sqlite3ExprIfFalse(Parse*, Expr*, int, int); Table *sqlite3FindTable(sqlite*,const char*, const char*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 877ee1056..a1a1a44c9 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.71 2004/05/26 06:18:38 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.72 2004/05/26 16:54:46 drh Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -864,7 +864,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ pFunc->zScript = (char*)&pFunc[1]; strcpy(pFunc->zScript, zScript); sqlite3_create_function(pDb->db, zName, -1, 0, 0, pFunc, tclSqlFunc, 0, 0); - sqlite3_function_type(pDb->db, zName, SQLITE_NUMERIC); break; } @@ -1245,6 +1244,3 @@ int TCLSH_MAIN(int argc, char **argv){ #endif /* TCLSH */ #endif /* !defined(NO_TCL) */ - - - diff --git a/src/vdbe.c b/src/vdbe.c index 7cc4288b0..2b8e2822e 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.334 2004/05/26 13:27:00 danielk1977 Exp $ +** $Id: vdbe.c,v 1.335 2004/05/26 16:54:47 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -5864,7 +5864,8 @@ default: { assert( (pTos->flags & (MEM_Static|MEM_Dyn|MEM_Ephem|MEM_Short))==0 ); } /* MEM_Null excludes all other types */ - assert( pTos->flags==MEM_Null || (pTos->flags&MEM_Null)==0 ); + assert( (pTos->flags&(MEM_Str|MEM_Int|MEM_Real|MEM_Blob))==0 + || (pTos->flags&MEM_Null)==0 ); } if( pc<-1 || pc>=p->nOp ){ sqlite3SetString(&p->zErrMsg, "jump destination out of range", (char*)0); diff --git a/src/vdbe.h b/src/vdbe.h index 80ecb0a78..b093f3082 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.83 2004/05/26 10:11:07 danielk1977 Exp $ +** $Id: vdbe.h,v 1.84 2004/05/26 16:54:48 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -69,7 +69,8 @@ typedef struct VdbeOpList VdbeOpList; #define P3_STATIC (-2) /* Pointer to a static string */ #define P3_POINTER (-3) /* P3 is a pointer to some structure or object */ #define P3_COLLSEQ (-4) /* P3 is a pointer to a CollSeq structure */ -#define P3_KEYINFO (-5) /* P3 is a pointer to a KeyInfo structure */ +#define P3_FUNCDEF (-5) /* P3 is a pointer to a FuncDef structure */ +#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */ /* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure ** is made. That copy is freed when the Vdbe is finalized. But if the @@ -78,7 +79,7 @@ typedef struct VdbeOpList VdbeOpList; ** from a single sqliteMalloc(). But no copy is made and the calling ** function should *not* try to free the KeyInfo. */ -#define P3_KEYINFO_HANDOFF (-6) +#define P3_KEYINFO_HANDOFF (-7) /* ** The following macro converts a relative address in the p2 field diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 60158fd32..b03e49372 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -517,6 +517,17 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ zP3 = zTemp; break; } + case P3_FUNCDEF: { + FuncDef *pDef = (FuncDef*)pOp->p3; + char zNum[30]; + sprintf(zTemp, "%.*s", nTemp, pDef->zName); + sprintf(zNum,"(%d)", pDef->nArg); + if( strlen(zTemp)+strlen(zNum)+1<=nTemp ){ + strcat(zTemp, zNum); + } + zP3 = zTemp; + break; + } default: { zP3 = pOp->p3; if( zP3==0 ){ @@ -1869,10 +1880,13 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){ } /* -** The following nine routines, named sqlite3_result_*(), are used to +** The following ten 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(sqlite3_context *pCtx, sqlite3_value *pValue){ + sqlite3VdbeMemCopy(&pCtx->s, pValue); +} void sqlite3_result_int32(sqlite3_context *pCtx, int iVal){ MemSetInt(&pCtx->s, iVal); } @@ -1918,4 +1932,3 @@ void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){ pCtx->isError = 1; MemSetStr(&pCtx->s, z, n, TEXT_Utf16, 1); } - |