Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Completely remove the old SQL function system and replace it with the new user functions. The code currently compiles but it coredumps on the test suite. Do not use in its present state. (CVS 400) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
50797fee5066ec9ea23b720e5ab7e8fc |
User & Date: | drh 2002-02-28 00:41:10.000 |
Context
2002-02-28
| ||
00:46 | Added IFNULL and NVL functions. (CVS 401) (check-in: c6a85c8ee3 user: drh tags: trunk) | |
00:41 | Completely remove the old SQL function system and replace it with the new user functions. The code currently compiles but it coredumps on the test suite. Do not use in its present state. (CVS 400) (check-in: 50797fee50 user: drh tags: trunk) | |
2002-02-27
| ||
19:50 | Try to reduce the number of malloc() for user-defined functions. Begin transfering built-in functions over to the user-define function mechanism. (CVS 399) (check-in: c4f9e017b4 user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.49 2002/02/28 00:41:10 drh Exp $ */ #include "sqliteInt.h" /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function |
︙ | ︙ | |||
627 628 629 630 631 632 633 | } } } } return 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | < < < | | | | | | | | | | < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 | } } } } return 0; } /* ** Error check the functions in an expression. Make sure all ** function names are recognized and all functions have the correct ** number of arguments. Leave an error message in pParse->zErrMsg ** if anything is amiss. Return the number of errors. ** ** if pIsAgg is not null and this expression is an aggregate function ** (like count(*) or max(value)) then write a 1 into *pIsAgg. */ int sqliteExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){ int nErr = 0; if( pExpr==0 ) return 0; switch( pExpr->op ){ case TK_FUNCTION: { int n = pExpr->pList ? pExpr->pList->nExpr : 0; int no_such_func = 0; int wrong_num_args = 0; int is_agg = 0; int i; FuncDef *pDef; pDef = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n,n,0); if( pDef==0 ){ pDef = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, -1, 0); if( pDef==0 ){ no_such_func = 1; }else{ wrong_num_args = 1; } }else{ is_agg = pDef->xFunc==0; } if( is_agg && !allowAgg ){ sqliteSetNString(&pParse->zErrMsg, "misuse of aggregate function ", -1, pExpr->token.z, pExpr->token.n, "()", 2, 0); pParse->nErr++; nErr++; is_agg = 0; }else if( no_such_func ){ sqliteSetNString(&pParse->zErrMsg, "no such function: ", -1, pExpr->token.z, pExpr->token.n, 0); pParse->nErr++; nErr++; }else if( wrong_num_args ){ sqliteSetNString(&pParse->zErrMsg, "wrong number of arguments to function ",-1, pExpr->token.z, pExpr->token.n, "()", 2, 0); pParse->nErr++; nErr++; } |
︙ | ︙ | |||
939 940 941 942 943 944 945 | dest = sqliteVdbeCurrentAddr(v) + 2; sqliteVdbeAddOp(v, op, 0, dest); sqliteVdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_AGG_FUNCTION: { sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | | | < < < < < < < | 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 | dest = sqliteVdbeCurrentAddr(v) + 2; sqliteVdbeAddOp(v, op, 0, dest); sqliteVdbeAddOp(v, OP_AddImm, -1, 0); break; } case TK_AGG_FUNCTION: { sqliteVdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); break; } case TK_FUNCTION: { int i; ExprList *pList = pExpr->pList; FuncDef *pDef; pDef = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pList->nExpr, 0); assert( pDef!=0 ); for(i=0; i<pList->nExpr; i++){ sqliteExprCode(pParse, pList->a[i].pExpr); } sqliteVdbeAddOp(v, OP_Function, pList->nExpr, 0); sqliteVdbeChangeP3(v, -1, (char*)pDef, P3_POINTER); break; } case TK_SELECT: { sqliteVdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0); break; } case TK_IN: { |
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 | pParse->aAgg[i].isAgg = 0; pParse->aAgg[i].pExpr = pExpr; } pExpr->iAgg = i; break; } case TK_AGG_FUNCTION: { | < < < < < < < < < < < < < < < < | < < < | 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 | pParse->aAgg[i].isAgg = 0; pParse->aAgg[i].pExpr = pExpr; } pExpr->iAgg = i; break; } case TK_AGG_FUNCTION: { aAgg = pParse->aAgg; for(i=0; i<pParse->nAgg; i++){ if( !aAgg[i].isAgg ) continue; if( sqliteExprCompare(aAgg[i].pExpr, pExpr) ){ break; } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; pParse->aAgg[i].pFunc = sqliteFindFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList->nExpr, 0); } pExpr->iAgg = i; break; } default: { if( pExpr->pLeft ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft); |
︙ | ︙ | |||
1370 1371 1372 1373 1374 1375 1376 | } } return nErr; } /* ** Locate a user function given a name and a number of arguments. | | | | | | | | 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 | } } return nErr; } /* ** Locate a user function given a name and a number of arguments. ** Return a pointer to the FuncDef structure that defines that ** function, or return NULL if the function does not exist. ** ** If the createFlag argument is true, then a new (blank) FuncDef ** structure is created and liked into the "db" structure if a ** no matching function previously existed. When createFlag is true ** and the nArg parameter is -1, then only a function that accepts ** any number of arguments will be returned. ** ** If createFlag is false and nArg is -1, then the first valid ** function found is returned. A function is valid if either xFunc ** or xStep is non-zero. */ FuncDef *sqliteFindFunction( sqlite *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ int createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *pFirst, *p, *pMaybe; pFirst = p = (FuncDef*)sqliteHashFind(&db->aFunc, zName, nName); if( p && !createFlag && nArg<0 ){ while( p && p->xFunc==0 && p->xStep==0 ){ p = p->pNext; } return p; } pMaybe = 0; while( p && p->nArg!=nArg ){ if( p->nArg<0 && !createFlag && (p->xFunc || p->xStep) ) pMaybe = p; p = p->pNext; } if( p && !createFlag && p->xFunc==0 && p->xStep==0 ){ return 0; } if( p==0 && pMaybe ){ assert( createFlag==0 ); return pMaybe; } if( p==0 && createFlag ){ p = sqliteMalloc( sizeof(*p) ); p->nArg = nArg; p->pNext = pFirst; sqliteHashInsert(&db->aFunc, zName, nName, (void*)p); } return p; } |
Changes to src/func.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | ** This file contains the C functions that implement various SQL ** functions of SQLite. ** ** There is only one exported symbol in this file - the function ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** ** $Id: func.c,v 1.6 2002/02/28 00:41:10 drh Exp $ */ #include <ctype.h> #include <math.h> #include <stdlib.h> #include <assert.h> #include "sqliteInt.h" /* ** Implementation of the non-aggregate min() and max() functions */ static void minFunc(sqlite_func *context, int argc, const char **argv){ const char *zBest; int i; zBest = argv[0]; for(i=1; i<argc; i++){ if( sqliteCompare(argv[i], zBest)<0 ){ zBest = argv[i]; } } sqlite_set_result_string(context, zBest, -1); } static void maxFunc(sqlite_func *context, int argc, const char **argv){ const char *zBest; int i; zBest = argv[0]; for(i=1; i<argc; i++){ if( sqliteCompare(argv[i], zBest)>0 ){ zBest = argv[i]; } } sqlite_set_result_string(context, zBest, -1); } /* ** Implementation of the length() function */ static void lengthFunc(sqlite_func *context, int argc, const char **argv){ const char *z; int len; assert( argc==1 ); z = argv[0]; if( z==0 ){ len = 0; }else{ #ifdef SQLITE_UTF8 for(len=0; *z; z++){ if( (0xc0&*z)!=0x80 ) len++; } #else len = strlen(z); #endif } sqlite_set_result_int(context, len); } /* ** Implementation of the abs() function */ static void absFunc(sqlite_func *context, int argc, const char **argv){ const char *z; assert( argc==1 ); z = argv[0]; if( z && z[0]=='-' && isdigit(z[1]) ) z++; sqlite_set_result_string(context, z, -1); } /* ** Implementation of the substr() function */ static void substrFunc(sqlite_func *context, int argc, const char **argv){ const char *z; #ifdef SQLITE_UTF8 const char *z2; int i; #endif int p1, p2, len; assert( argc==3 ); z = argv[0]; if( z==0 ) return; p1 = atoi(argv[1]?argv[1]:0); p2 = atoi(argv[2]?argv[2]:0); #ifdef SQLITE_UTF8 for(len=0, z2=z; *z2; z2++){ if( (0xc0&*z)!=0x80 ) len++; } #else len = strlen(z); #endif if( p1<0 ){ p1 = len-p1; }else if( p1>0 ){ p1--; } if( p1+p2>len ){ p2 = len-p1; } #ifdef SQLITE_UTF8 for(i=0; i<p1; i++){ assert( z[i] ); if( (z[i]&0xc0)!=0x80 ) p1++; } for(; i<p1+p2; i++){ assert( z[i] ); if( (z[i]&0xc0)!=0x80 ) p2++; } #endif sqlite_set_result_string(context, &z[p1], p2); } /* ** Implementation of the round() function */ static void roundFunc(sqlite_func *context, int argc, const char **argv){ int n; double r; char zBuf[100]; assert( argc==1 || argc==2 ); n = argc==2 && argv[1] ? atoi(argv[1]) : 0; if( n>30 ) n = 30; if( n<0 ) n = 0; r = argv[0] ? atof(argv[0]) : 0.0; sprintf(zBuf,"%.*f",n,r); sqlite_set_result_string(context, zBuf, -1); } /* ** Implementation of the upper() and lower() SQL functions. */ static void upperFunc(sqlite_func *context, int argc, const char **argv){ char *z; int i; |
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p)); if( p && rN>1.0 ){ sqlite_set_result_double(context, sqrt((p->sum2 - p->sum*p->sum/rN)/(rN-1.0))); } } /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. */ void sqliteRegisterBuildinFunctions(sqlite *db){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | < > > > | | | > | 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 | StdDevCtx *p = sqlite_aggregate_context(context, sizeof(*p)); if( p && rN>1.0 ){ sqlite_set_result_double(context, sqrt((p->sum2 - p->sum*p->sum/rN)/(rN-1.0))); } } /* ** The following structure keeps track of state information for the ** count() aggregate function. */ typedef struct CountCtx CountCtx; struct CountCtx { int n; }; /* ** Routines to implement the count() aggregate function. */ static void countStep(sqlite_func *context, int argc, const char **argv){ CountCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( (argc==0 || argv[0]) && p ){ p->n++; } } static void countFinalize(sqlite_func *context){ CountCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( p ){ sqlite_set_result_int(context, p->n); } } /* ** This function tracks state information for the min() and max() ** aggregate functions. */ typedef struct MinMaxCtx MinMaxCtx; struct MinMaxCtx { char *z; /* The best so far */ char zBuf[28]; /* Space that can be used for storage */ }; /* ** Routines to implement min() and max() aggregate functions. */ static void minStep(sqlite_func *context, int argc, const char **argv){ MinMaxCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( p==0 || argc<1 ) return; if( sqlite_aggregate_count(context)==1 || sqliteCompare(argv[0],p->z)<0 ){ if( p->z && p->z!=p->zBuf ){ sqliteFree(p->z); } if( argv[0] ){ int len = strlen(argv[0]); if( len < sizeof(p->zBuf) ){ p->z = p->zBuf; }else{ p->z = sqliteMalloc( len+1 ); if( p->z==0 ) return; } strcpy(p->z, argv[0]); }else{ p->z = 0; } } } static void maxStep(sqlite_func *context, int argc, const char **argv){ MinMaxCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( p==0 || argc<1 ) return; if( sqlite_aggregate_count(context)==1 || sqliteCompare(argv[0],p->z)>0 ){ if( p->z && p->z!=p->zBuf ){ sqliteFree(p->z); } if( argv[0] ){ int len = strlen(argv[0]); if( len < sizeof(p->zBuf) ){ p->z = p->zBuf; }else{ p->z = sqliteMalloc( len+1 ); if( p->z==0 ) return; } strcpy(p->z, argv[0]); }else{ p->z = 0; } } } static void minMaxFinalize(sqlite_func *context){ MinMaxCtx *p; p = sqlite_aggregate_context(context, sizeof(*p)); if( p && p->z ){ sqlite_set_result_string(context, p->z, strlen(p->z)); } if( p && p->z && p->z!=p->zBuf ){ sqliteFree(p->z); } } /* ** This function registered all of the above C functions as SQL ** functions. This should be the only routine in this file with ** external linkage. */ void sqliteRegisterBuildinFunctions(sqlite *db){ static struct { char *zName; int nArg; void (*xFunc)(sqlite_func*,int,const char**); } aFuncs[] = { { "min", -1, minFunc }, { "max", -1, maxFunc }, { "length", 1, lengthFunc }, { "substr", 3, substrFunc }, { "abs", 1, absFunc }, { "round", 1, roundFunc }, { "round", 2, roundFunc }, { "upper", 1, upperFunc }, { "lower", 1, lowerFunc }, }; static struct { char *zName; int nArg; void (*xStep)(sqlite_func*,int,const char**); void (*xFinalize)(sqlite_func*); } aAggs[] = { { "min", 1, minStep, minMaxFinalize }, { "max", 1, maxStep, minMaxFinalize }, { "sum", 1, sumStep, sumFinalize }, { "avg", 1, sumStep, avgFinalize }, { "count", 0, countStep, countFinalize }, { "count", 1, countStep, countFinalize }, { "stddev", 1, stdDevStep, stdDevFinalize }, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite_create_function(db, aFuncs[i].zName, aFuncs[i].nArg, aFuncs[i].xFunc, 0); } for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){ sqlite_create_aggregate(db, aAggs[i].zName, aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0); } } |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.66 2002/02/28 00:41:11 drh Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. |
︙ | ︙ | |||
309 310 311 312 313 314 315 | db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0); sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0); | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | db = sqliteMalloc( sizeof(sqlite) ); if( pzErrMsg ) *pzErrMsg = 0; if( db==0 ) goto no_mem_on_open; sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0); sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0); sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1); sqliteRegisterBuildinFunctions(db); db->onError = OE_Default; db->priorNewRowid = 0; /* Open the backend database driver */ rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe); if( rc!=SQLITE_OK ){ |
︙ | ︙ | |||
412 413 414 415 416 417 418 | void sqlite_close(sqlite *db){ HashElem *i; sqliteBtreeClose(db->pBe); clearHashTable(db, 0); if( db->pBeTemp ){ sqliteBtreeClose(db->pBeTemp); } | | | | | | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 | void sqlite_close(sqlite *db){ HashElem *i; sqliteBtreeClose(db->pBe); clearHashTable(db, 0); if( db->pBeTemp ){ sqliteBtreeClose(db->pBeTemp); } for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; sqliteFree(pFunc); } } sqliteHashClear(&db->aFunc); sqliteFree(db); } /* ** Return TRUE if the given SQL string ends in a semicolon. */ int sqlite_complete(const char *zSql){ |
︙ | ︙ | |||
642 643 644 645 646 647 648 | int sqlite_create_function( sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */ void *pUserData /* User data */ ){ | | | | | | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | int sqlite_create_function( sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xFunc)(sqlite_func*,int,const char**), /* The implementation */ void *pUserData /* User data */ ){ FuncDef *p; if( db==0 || zName==0 ) return 1; p = sqliteFindFunction(db, zName, strlen(zName), nArg, 1); if( p==0 ) return 1; p->xFunc = xFunc; p->xStep = 0; p->xFinalize = 0; p->pUserData = pUserData; return 0; } int sqlite_create_aggregate( sqlite *db, /* Add the function to this database connection */ const char *zName, /* Name of the function to add */ int nArg, /* Number of arguments */ void (*xStep)(sqlite_func*,int,const char**), /* The step function */ void (*xFinalize)(sqlite_func*), /* The finalizer */ void *pUserData /* User data */ ){ FuncDef *p; if( db==0 || zName==0 ) return 1; p = sqliteFindFunction(db, zName, strlen(zName), nArg, 1); if( p==0 ) return 1; p->xFunc = 0; p->xStep = xStep; p->xFinalize = xFinalize; p->pUserData = pUserData; return 0; } |
Changes to src/select.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** ** $Id: select.c,v 1.69 2002/02/28 00:41:11 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
74 75 76 77 78 79 80 | /* ** Delete the aggregate information from the parse structure. */ static void sqliteAggregateInfoReset(Parse *pParse){ sqliteFree(pParse->aAgg); pParse->aAgg = 0; pParse->nAgg = 0; | < | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | /* ** Delete the aggregate information from the parse structure. */ static void sqliteAggregateInfoReset(Parse *pParse){ sqliteFree(pParse->aAgg); pParse->aAgg = 0; pParse->nAgg = 0; pParse->useAgg = 0; } /* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** |
︙ | ︙ | |||
843 844 845 846 847 848 849 | */ if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; if( p->pSrc->nId!=1 ) return 0; if( p->pEList->nExpr!=1 ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( pExpr->pList==0 || pExpr->pList->nExpr!=1 ) return 0; | | > > > | > > > | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 | */ if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; if( p->pSrc->nId!=1 ) return 0; if( p->pEList->nExpr!=1 ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; if( pExpr->pList==0 || pExpr->pList->nExpr!=1 ) return 0; if( pExpr->token.n!=3 ) return 0; if( sqliteStrNICmp(pExpr->token.z,"min",3)==0 ){ seekOp = OP_Rewind; }else if( sqliteStrNICmp(pExpr->token.z,"max",3)==0 ){ seekOp = OP_Last; }else{ return 0; } pExpr = pExpr->pList->a[0].pExpr; if( pExpr->op!=TK_COLUMN ) return 0; iCol = pExpr->iColumn; pTab = p->pSrc->a[0].pTab; /* If we get to here, it means the query is of the correct form. ** Check to make sure we have an index and make pIdx point to the |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | pParse->nTab = oldNTab; } /* Do an analysis of aggregate expressions. */ sqliteAggregateInfoReset(pParse); if( isAgg ){ | | | 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | pParse->nTab = oldNTab; } /* Do an analysis of aggregate expressions. */ sqliteAggregateInfoReset(pParse); if( isAgg ){ assert( pParse->nAgg==0 ); for(i=0; i<pEList->nExpr; i++){ if( sqliteExprAnalyzeAggregates(pParse, pEList->a[i].pExpr) ){ goto select_end; } } if( pGroupBy ){ for(i=0; i<pGroupBy->nExpr; i++){ |
︙ | ︙ | |||
1194 1195 1196 1197 1198 1199 1200 | } /* Reset the aggregator */ if( isAgg ){ sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); for(i=0; i<pParse->nAgg; i++){ | | | | < < < < < < < < < < < < | 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | } /* Reset the aggregator */ if( isAgg ){ sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); for(i=0; i<pParse->nAgg; i++){ FuncDef *pFunc; if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){ sqliteVdbeAddOp(v, OP_AggInit, 0, i); sqliteVdbeChangeP3(v, -1, (char*)pFunc, P3_POINTER); } } if( pGroupBy==0 ){ sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_AggFocus, 0, 0); } } /* Initialize the memory cell to NULL */ if( eDest==SRT_Mem ){ sqliteVdbeAddOp(v, OP_String, 0, 0); |
︙ | ︙ | |||
1264 1265 1266 1267 1268 1269 1270 | sqliteExprCode(pParse, pParse->aAgg[i].pExpr); sqliteVdbeAddOp(v, OP_AggSet, 0, i); } sqliteVdbeResolveLabel(v, lbl1); } for(i=0; i<pParse->nAgg; i++){ Expr *pE; | | < < < < | | | | < < < < < < < < < < < | | | | | < | 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 | sqliteExprCode(pParse, pParse->aAgg[i].pExpr); sqliteVdbeAddOp(v, OP_AggSet, 0, i); } sqliteVdbeResolveLabel(v, lbl1); } for(i=0; i<pParse->nAgg; i++){ Expr *pE; int j; if( !pParse->aAgg[i].isAgg ) continue; pE = pParse->aAgg[i].pExpr; assert( pE->op==TK_AGG_FUNCTION ); if( pE->pList ){ for(j=0; j<pE->pList->nExpr; j++){ sqliteExprCode(pParse, pE->pList->a[j].pExpr); } } sqliteVdbeAddOp(v, OP_Integer, i, 0); sqliteVdbeAddOp(v, OP_AggFunc, 0, pE->pList->nExpr); assert( pParse->aAgg[i].pFunc!=0 ); assert( pParse->aAgg[i].pFunc->xStep!=0 ); sqliteVdbeChangeP3(v, -1, (char*)pParse->aAgg[i].pFunc, P3_POINTER); } } /* End the database scan loop. */ sqliteWhereEnd(pWInfo); |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.96 2002/02/28 00:41:11 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
123 124 125 126 127 128 129 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) | < < < < < < < < < < < < < < < | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) (sizeof(X)/sizeof(X[0])) /* ** Forward references to structures */ typedef struct Column Column; typedef struct Table Table; typedef struct Index Index; typedef struct Instruction Instruction; typedef struct Expr Expr; typedef struct ExprList ExprList; typedef struct Parse Parse; typedef struct Token Token; typedef struct IdList IdList; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; typedef struct Select Select; typedef struct AggExpr AggExpr; typedef struct FuncDef FuncDef; /* ** Each database is an instance of the following structure */ struct sqlite { Btree *pBe; /* The B*Tree backend */ Btree *pBeTemp; /* Backend for session temporary tables */ int flags; /* Miscellanous flags. See below */ int file_format; /* What file format version is this database? */ int schema_cookie; /* Magic number that changes with the schema */ int next_cookie; /* Value of schema_cookie after commit */ int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash tblDrop; /* Uncommitted DROP TABLEs */ Hash idxDrop; /* Uncommitted DROP INDEXs */ Hash aFunc; /* All functions that can be in SQL exprs */ int lastRowid; /* ROWID of most recent insert */ int priorNewRowid; /* Last randomly generated ROWID */ int onError; /* Default conflict algorithm */ }; /* ** Possible values for the sqlite.flags. |
︙ | ︙ | |||
196 197 198 199 200 201 202 | /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000080 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_ResultDetails 0x00000100 /* Details added to result set */ /* | | | | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_NullCallback 0x00000080 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_ResultDetails 0x00000100 /* Details added to result set */ /* ** Each SQL function is defined by an instance of the following ** structure. A pointer to this structure is stored in the sqlite.aFunc ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { void (*xFunc)(sqlite_func*,int,const char**); /* Regular function */ void *(*xStep)(sqlite_func*,int,const char**); /* Aggregate function step */ void (*xFinalize)(sqlite_func*); /* Aggregate function finializer */ int nArg; /* Number of arguments */ void *pUserData; /* User data parameter */ FuncDef *pNext; /* Next function with same name */ }; /* ** information about each column of an SQL table is held in an instance ** of this structure. */ struct Column { |
︙ | ︙ | |||
506 507 508 509 510 511 512 | ** up. Do not try to delete the expression attached to AggExpr.pExpr. ** ** If AggExpr.pExpr==0, that means the expression is "count(*)". */ struct AggExpr { int isAgg; /* if TRUE contains an aggregate function */ Expr *pExpr; /* The expression */ | | | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 | ** up. Do not try to delete the expression attached to AggExpr.pExpr. ** ** If AggExpr.pExpr==0, that means the expression is "count(*)". */ struct AggExpr { int isAgg; /* if TRUE contains an aggregate function */ Expr *pExpr; /* The expression */ FuncDef *pFunc; /* Information about the aggregate function */ }; /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. */ |
︙ | ︙ | |||
537 538 539 540 541 542 543 | int newTnum; /* Table number to use when reparsing CREATE TABLEs */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ | < | 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | int newTnum; /* Table number to use when reparsing CREATE TABLEs */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated cursors */ int nMem; /* Number of memory cells used so far */ int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ int useAgg; /* If true, extract field values from the aggregator ** while generating expressions. Normally false */ int schemaVerified; /* True if an OP_VerifySchema has been coded someplace ** other than after an OP_Transaction */ }; /* |
︙ | ︙ | |||
648 649 650 651 652 653 654 | void sqliteExprMoveStrings(Expr*, int); void sqliteExprListMoveStrings(ExprList*, int); void sqliteSelectMoveStrings(Select*, int); Expr *sqliteExprDup(Expr*); ExprList *sqliteExprListDup(ExprList*); IdList *sqliteIdListDup(IdList*); Select *sqliteSelectDup(Select*); | | | 632 633 634 635 636 637 638 639 640 | void sqliteExprMoveStrings(Expr*, int); void sqliteExprListMoveStrings(ExprList*, int); void sqliteSelectMoveStrings(Select*, int); Expr *sqliteExprDup(Expr*); ExprList *sqliteExprListDup(ExprList*); IdList *sqliteIdListDup(IdList*); Select *sqliteSelectDup(Select*); FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int); void sqliteRegisterBuildinFunctions(sqlite*); |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.39 2002/02/28 00:41:11 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> #include <ctype.h> /* ** If malloc() ever fails, this global variable gets set to 1. |
︙ | ︙ | |||
655 656 657 658 659 660 661 | ** ** This is NOT the comparison function used for sorting. The sort ** order is a little bit different. See sqliteSortCompare below ** for additional information. */ int sqliteCompare(const char *atext, const char *btext){ int result; | > > > > > > | | | 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | ** ** This is NOT the comparison function used for sorting. The sort ** order is a little bit different. See sqliteSortCompare below ** for additional information. */ int sqliteCompare(const char *atext, const char *btext){ int result; int isNumA, isNumB; if( atext==0 ){ return -(btext!=0); }else if( btext==0 ){ return 1; } isNumA = isNum(atext); isNumB = isNum(btext); if( isNumA ){ if( !isNumB ){ result = -1; }else{ double rA, rB; rA = atof(atext); rB = atof(btext); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.126 2002/02/28 00:41:11 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
136 137 138 139 140 141 142 | #define STK_Int 0x0004 /* Value is an integer */ #define STK_Real 0x0008 /* Value is a real number */ #define STK_Dyn 0x0010 /* Need to call sqliteFree() on zStack[*] */ #define STK_Static 0x0020 /* zStack[] points to a static string */ /* The following STK_ value appears only in AggElem.aMem.s.flag fields. ** It indicates that the corresponding AggElem.aMem.z points to a | | | | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | #define STK_Int 0x0004 /* Value is an integer */ #define STK_Real 0x0008 /* Value is a real number */ #define STK_Dyn 0x0010 /* Need to call sqliteFree() on zStack[*] */ #define STK_Static 0x0020 /* zStack[] points to a static string */ /* The following STK_ value appears only in AggElem.aMem.s.flag fields. ** It indicates that the corresponding AggElem.aMem.z points to a ** aggregate function context that needs to be finalized. */ #define STK_AggCtx 0x0040 /* zStack[] points to an agg function context */ /* ** The "context" argument for a installable function. A pointer to an ** instance of this structure is the first argument to the routines used ** implement the SQL functions. ** ** There is a typedef for this structure in sqlite.h. So all routines, ** even the public interface to SQLite, can use a pointer to this structure. ** But this file is the only place where the internal details of this ** structure are known. ** ** This structure is defined inside of vdbe.c because it uses substructures ** (Stack) which are only defined there. */ struct sqlite_func { FuncDef *pFunc; /* Pointer to function information. MUST BE FIRST */ Stack s; /* Small strings, ints, and double values go here */ char *z; /* Space for holding dynamic string results */ void *pAgg; /* Aggregate context */ u8 isError; /* Set to true for an error */ u8 isStep; /* Current in the step function */ int cnt; /* Number of times that the step function has been called */ }; |
︙ | ︙ | |||
177 178 179 180 181 182 183 | typedef struct Agg Agg; typedef struct AggElem AggElem; struct Agg { int nMem; /* Number of values stored in each AggElem */ AggElem *pCurrent; /* The AggElem currently in focus */ HashElem *pSearch; /* The hash element for pCurrent */ Hash hash; /* Hash table of all aggregate elements */ | | | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | typedef struct Agg Agg; typedef struct AggElem AggElem; struct Agg { int nMem; /* Number of values stored in each AggElem */ AggElem *pCurrent; /* The AggElem currently in focus */ HashElem *pSearch; /* The hash element for pCurrent */ Hash hash; /* Hash table of all aggregate elements */ FuncDef **apFunc; /* Information about aggregate functions */ }; struct AggElem { char *zKey; /* The key to this AggElem */ int nKey; /* Number of bytes in the key, including '\0' at end */ Mem aMem[1]; /* The values for this AggElem */ }; |
︙ | ︙ | |||
519 520 521 522 523 524 525 | } } while( j>0 && isspace(z[j-1]) ){ j--; } z[j] = 0; } /* | | | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | } } while( j>0 && isspace(z[j-1]) ){ j--; } z[j] = 0; } /* ** The following group or routines are employed by installable functions ** to return their results. ** ** The sqlite_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 a ephemeral string. ** |
︙ | ︙ | |||
624 625 626 627 628 629 630 | p->pAgg = sqliteMalloc( nByte ); } } return p->pAgg; } /* | | | | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 | p->pAgg = sqliteMalloc( nByte ); } } return p->pAgg; } /* ** Return the number of times the Step function of a aggregate has been ** called. ** ** This routine is defined here in vdbe.c because it depends on knowing ** the internals of the sqlite_func structure which is only defined in that ** one source file. */ int sqlite_aggregate_count(sqlite_func *p){ assert( p && p->pFunc && p->pFunc->xStep ); return p->cnt; } /* ** Reset an Agg structure. Delete all its contents. ** ** For installable aggregate functions, if the step function has been ** called, make sure the finalizer function has also been called. The ** finalizer might need to free memory that was allocated as part of its ** private context. If the finalizer has not been called yet, call it ** now. */ static void AggReset(Agg *pAgg){ int i; |
︙ | ︙ | |||
1057 1058 1059 1060 1061 1062 1063 | "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "Precision", "Min", "Max", "Like", "Glob", "Eq", "Ne", "Lt", "Le", "Gt", "Ge", "IsNull", "NotNull", "Negative", "And", "Or", "Not", "Concat", | | | 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 | "Subtract", "Multiply", "Divide", "Remainder", "BitAnd", "BitOr", "BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "Precision", "Min", "Max", "Like", "Glob", "Eq", "Ne", "Lt", "Le", "Gt", "Ge", "IsNull", "NotNull", "Negative", "And", "Or", "Not", "Concat", "Noop", "Strlen", "Substr", "Function", "Limit", }; /* ** Given the name of an opcode, return its number. Return 0 if ** there is no match. ** |
︙ | ︙ | |||
1861 1862 1863 1864 1865 1866 1867 | }else{ Release(p, tos); } p->tos = nos; break; } | | | | | | 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 | }else{ Release(p, tos); } p->tos = nos; break; } /* Opcode: Function P1 * P3 ** ** Invoke a user function (P3 is a pointer to a Function structure that ** defines the function) with P1 string arguments taken from the stack. ** Pop all arguments from the stack and push back the result. ** ** See also: AggFunc */ case OP_Function: { int n, i; sqlite_func ctx; n = pOp->p1; VERIFY( if( n<=0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) for(i=p->tos-n+1; i<=p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; } } ctx.pFunc = (FuncDef*)pOp->p3; ctx.s.flags = STK_Null; ctx.z = 0; ctx.isError = 0; ctx.isStep = 0; (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&zStack[p->tos-n+1]); PopStack(p, n); VERIFY( NeedStack(p, p->tos+1); ) |
︙ | ︙ | |||
4400 4401 4402 4403 4404 4405 4406 | p->agg.nMem = pOp->p2; p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) ); break; } /* Opcode: AggInit * P2 P3 ** | | | | | | | | | 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 | p->agg.nMem = pOp->p2; p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) ); break; } /* Opcode: AggInit * P2 P3 ** ** Initialize the function parameters for an aggregate function. ** The aggregate will operate out of aggregate column P2. ** P3 is a pointer to the FuncDef structure for the function. */ case OP_AggInit: { int i = pOp->p2; VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) p->agg.apFunc[i] = (FuncDef*)pOp->p3; break; } /* Opcode: AggFunc * P2 P3 ** ** Execute the step function for an aggregate. The ** function has P2 arguments. P3 is a pointer to the FuncDef ** structure that specifies the function. ** ** The top of the stack must be an integer which is the index of ** the aggregate column that corresponds to this aggregate function. ** Ideally, this index would be another parameter, but there are ** no free parameters left. The integer is popped from the stack. */ case OP_AggFunc: { |
︙ | ︙ | |||
4438 4439 4440 4441 4442 4443 4444 | for(i=p->tos-n; i<p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; } } i = aStack[p->tos].i; VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) | | | 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 | for(i=p->tos-n; i<p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; } } i = aStack[p->tos].i; VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) ctx.pFunc = (FuncDef*)pOp->p3; pMem = &p->agg.pCurrent->aMem[i]; ctx.z = pMem->s.z; ctx.pAgg = pMem->z; ctx.cnt = ++pMem->s.i; ctx.isError = 0; ctx.isStep = 1; (ctx.pFunc->xStep)(&ctx, n, (const char**)&zStack[p->tos-n]); |
︙ | ︙ | |||
4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 | int i; sqlite_func ctx; Mem *aMem; int nErr = 0; p->agg.pCurrent = sqliteHashData(p->agg.pSearch); aMem = p->agg.pCurrent->aMem; for(i=0; i<p->agg.nMem; i++){ if( p->agg.apFunc[i]==0 ) continue; if( p->agg.apFunc[i]->xFinalize==0 ) continue; if( (aMem[i].s.flags & STK_AggCtx)==0 ) continue; ctx.s.flags = STK_Null; ctx.z = 0; ctx.pAgg = (void*)aMem[i].z; ctx.cnt = aMem[i].s.i; ctx.isStep = 0; ctx.pFunc = p->agg.apFunc[i]; (*p->agg.apFunc[i]->xFinalize)(&ctx); | > > > | > | 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 | int i; sqlite_func ctx; Mem *aMem; int nErr = 0; p->agg.pCurrent = sqliteHashData(p->agg.pSearch); aMem = p->agg.pCurrent->aMem; for(i=0; i<p->agg.nMem; i++){ int freeCtx; if( p->agg.apFunc[i]==0 ) continue; if( p->agg.apFunc[i]->xFinalize==0 ) continue; if( (aMem[i].s.flags & STK_AggCtx)==0 ) continue; ctx.s.flags = STK_Null; ctx.z = 0; ctx.pAgg = (void*)aMem[i].z; freeCtx = aMem[i].z && aMem[i].z!=aMem[i].s.z; ctx.cnt = aMem[i].s.i; ctx.isStep = 0; ctx.pFunc = p->agg.apFunc[i]; (*p->agg.apFunc[i]->xFinalize)(&ctx); if( freeCtx ){ sqliteFree( aMem[i].z ); } aMem[i].s = ctx.s; aMem[i].z = ctx.z; if( (aMem[i].s.flags & STK_Str) && (aMem[i].s.flags & (STK_Dyn|STK_Static))==0 ){ aMem[i].z = aMem[i].s.z; } nErr += ctx.isError; |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** Header file for the Virtual DataBase Engine (VDBE) ** ** This header defines the interface to the virtual database engine ** 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.48 2002/02/28 00:41:11 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
198 199 200 201 202 203 204 | #define OP_And 113 #define OP_Or 114 #define OP_Not 115 #define OP_Concat 116 #define OP_Noop 117 #define OP_Strlen 118 #define OP_Substr 119 | | | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 | #define OP_And 113 #define OP_Or 114 #define OP_Not 115 #define OP_Concat 116 #define OP_Noop 117 #define OP_Strlen 118 #define OP_Substr 119 #define OP_Function 120 #define OP_Limit 121 #define OP_MAX 121 /* ** Prototypes for the VDBE interface. See comments on the implementation |
︙ | ︙ |