Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Code for user-defined aggregates added. Legacy tests all pass but there has been no testing of the new user-defined aggregate code. (CVS 392) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1e037eb303d8508cb2ea3418e71b0331 |
User & Date: | drh 2002-02-24 03:25:15.000 |
Context
2002-02-24
| ||
17:12 | Added a "stddev()" aggregate function for testing the new user aggregate function interface. (CVS 393) (check-in: 2198109712 user: drh tags: trunk) | |
03:25 | Code for user-defined aggregates added. Legacy tests all pass but there has been no testing of the new user-defined aggregate code. (CVS 392) (check-in: 1e037eb303 user: drh tags: trunk) | |
01:55 | Move the build-in function definitions into a new source file "func.c". (CVS 391) (check-in: 530b0f4f2d 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.44 2002/02/24 03:25:15 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 |
︙ | ︙ | |||
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 | } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; } pExpr->iAgg = i; break; } default: { if( pExpr->pLeft ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft); | > > > > > > | 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 | } } if( i>=pParse->nAgg ){ i = appendAggInfo(pParse); if( i<0 ) return 1; pParse->aAgg[i].isAgg = 1; pParse->aAgg[i].pExpr = pExpr; if( pExpr->iColumn==FN_Unknown ){ pParse->aAgg[i].pUser = sqliteFindUserFunction(pParse->db, pExpr->token.z, pExpr->token.n, pExpr->pList->nExpr, 0); }else{ pParse->aAgg[i].pUser = 0; } } pExpr->iAgg = i; break; } default: { if( pExpr->pLeft ){ nErr = sqliteExprAnalyzeAggregates(pParse, pExpr->pLeft); |
︙ | ︙ |
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.66 2002/02/24 03:25:16 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 | generateColumnNames(pParse, pTabList, pEList); } /* Reset the aggregator */ if( isAgg ){ sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); if( pGroupBy==0 ){ sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_AggFocus, 0, 0); for(i=0; i<pParse->nAgg; i++){ Expr *pE; if( !pParse->aAgg[i].isAgg ) continue; pE = pParse->aAgg[i].pExpr; | > > > > > > > | 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 | generateColumnNames(pParse, pTabList, pEList); } /* Reset the aggregator */ if( isAgg ){ sqliteVdbeAddOp(v, OP_AggReset, 0, pParse->nAgg); for(i=0; i<pParse->nAgg; i++){ UserFunc *pUser; if( (pUser = pParse->aAgg[i].pUser)!=0 && pUser->xFinalize!=0 ){ sqliteVdbeAddOp(v, OP_AggFinalizer, 0, i); sqliteVdbeChangeP3(v, -1, (char*)pUser->xFinalize, P3_POINTER); } } if( pGroupBy==0 ){ sqliteVdbeAddOp(v, OP_String, 0, 0); sqliteVdbeAddOp(v, OP_AggFocus, 0, 0); for(i=0; i<pParse->nAgg; i++){ Expr *pE; if( !pParse->aAgg[i].isAgg ) continue; pE = pParse->aAgg[i].pExpr; |
︙ | ︙ | |||
1161 1162 1163 1164 1165 1166 1167 | sqliteExprCode(pParse, pParse->aAgg[i].pExpr); sqliteVdbeAddOp(v, OP_AggSet, 0, i); } sqliteVdbeResolveLabel(v, lbl1); } for(i=0; i<pParse->nAgg; i++){ Expr *pE; | | | > | > | | | | > > | > > > > > > < | 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 | 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 op, j; if( !pParse->aAgg[i].isAgg ) continue; pE = pParse->aAgg[i].pExpr; if( pE==0 ){ sqliteVdbeAddOp(v, OP_AggIncr, 1, i); continue; } assert( pE->op==TK_AGG_FUNCTION ); assert( pE->pList!=0 ); for(j=0; j<pE->pList->nExpr; j++){ sqliteExprCode(pParse, pE->pList->a[j].pExpr); } sqliteVdbeAddOp(v, OP_AggGet, 0, i); switch( pE->iColumn ){ case FN_Min: op = OP_Min; break; case FN_Max: op = OP_Max; break; case FN_Avg: op = OP_Add; break; case FN_Sum: op = OP_Add; break; case FN_Unknown: op = OP_AggFunc; break; } if( op!=OP_AggFunc ){ sqliteVdbeAddOp(v, op, 0, 0); }else{ sqliteVdbeAddOp(v, OP_AggFunc, 0, pE->pList->nExpr); assert( pParse->aAgg[i].pUser!=0 ); assert( pParse->aAgg[i].pUser->xStep!=0 ); sqliteVdbeChangeP3(v,-1,(char*)pParse->aAgg[i].pUser->xStep,P3_POINTER); } sqliteVdbeAddOp(v, OP_AggSet, 0, i); } } /* End the database scan loop. */ sqliteWhereEnd(pWInfo); /* If we are processing aggregates, we need to set up a second loop ** over all of the aggregate values and process them. |
︙ | ︙ |
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.93 2002/02/24 03:25:16 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
505 506 507 508 509 510 511 512 513 514 515 516 517 518 | ** 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 */ }; /* ** 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. */ | > | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | ** 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 */ UserFunc *pUser; /* User-defined 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. */ |
︙ | ︙ |
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.123 2002/02/24 03:25:16 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 |
︙ | ︙ | |||
134 135 136 137 138 139 140 141 142 143 144 145 146 147 | #define STK_Null 0x0001 /* Value is NULL */ #define STK_Str 0x0002 /* Value is a string */ #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 "context" argument for a user-defined function. */ struct UserFuncContext { Stack s; /* Small string, integer, and floating point values go here */ char *z; /* Space for holding dynamic string results */ int isError; /* Set to true for an error */ | > > > > > > | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | #define STK_Null 0x0001 /* Value is NULL */ #define STK_Str 0x0002 /* Value is a string */ #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 ** user-defined aggregate context that needs to be finalized. */ #define STK_AggCtx 0x0040 /* zStack[] points to an user function context */ /* ** The "context" argument for a user-defined function. */ struct UserFuncContext { Stack s; /* Small string, integer, and floating point values go here */ char *z; /* Space for holding dynamic string results */ int isError; /* Set to true for an error */ |
︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | 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 */ }; 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 */ }; | > | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | 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 */ void (**axFinalize)(void*,void*); /* Array of nMem finalizers */ }; 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 */ }; |
︙ | ︙ | |||
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | ** Reset an Agg structure. Delete all its contents. */ static void AggReset(Agg *pAgg){ int i; HashElem *p; for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){ AggElem *pElem = sqliteHashData(p); for(i=0; i<pAgg->nMem; i++){ if( pElem->aMem[i].s.flags & STK_Dyn ){ sqliteFree(pElem->aMem[i].z); } } sqliteFree(pElem); } sqliteHashClear(&pAgg->hash); pAgg->pCurrent = 0; pAgg->pSearch = 0; pAgg->nMem = 0; } /* ** Insert a new element and make it the current element. | > > > > > | 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 | ** Reset an Agg structure. Delete all its contents. */ static void AggReset(Agg *pAgg){ int i; HashElem *p; for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){ AggElem *pElem = sqliteHashData(p); assert( pAgg->axFinalize!=0 ); for(i=0; i<pAgg->nMem; i++){ if( pElem->aMem[i].s.flags & STK_Dyn ){ sqliteFree(pElem->aMem[i].z); }else if( pAgg->axFinalize[i] && (pElem->aMem[i].s.flags & STK_AggCtx) ){ (pAgg->axFinalize[i])((void*)pElem->aMem[i].z, 0); } } sqliteFree(pElem); } sqliteHashClear(&pAgg->hash); sqliteFree(pAgg->axFinalize); pAgg->axFinalize = 0; pAgg->pCurrent = 0; pAgg->pSearch = 0; pAgg->nMem = 0; } /* ** Insert a new element and make it the current element. |
︙ | ︙ | |||
950 951 952 953 954 955 956 | "Clear", "CreateIndex", "CreateTable", "IntegrityCk", "IdxPut", "IdxDelete", "IdxRecno", "IdxGT", "IdxGE", "MemLoad", "MemStore", "ListWrite", "ListRewind", "ListRead", "ListReset", "SortPut", "SortMakeRec", "SortMakeKey", "Sort", "SortNext", "SortCallback", "SortReset", "FileOpen", "FileRead", "FileColumn", "AggReset", "AggFocus", "AggIncr", | | | | | | | | | | | | | | | | > | 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 | "Clear", "CreateIndex", "CreateTable", "IntegrityCk", "IdxPut", "IdxDelete", "IdxRecno", "IdxGT", "IdxGE", "MemLoad", "MemStore", "ListWrite", "ListRewind", "ListRead", "ListReset", "SortPut", "SortMakeRec", "SortMakeKey", "Sort", "SortNext", "SortCallback", "SortReset", "FileOpen", "FileRead", "FileColumn", "AggReset", "AggFocus", "AggIncr", "AggNext", "AggSet", "AggGet", "AggFinalizer", "AggFunc", "SetInsert", "SetFound", "SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "Push", "MustBeInt", "Add", "AddImm", "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", "UserFunc", "Limit", }; /* ** Given the name of an opcode, return its number. Return 0 if ** there is no match. ** ** This routine is used for testing and debugging. |
︙ | ︙ | |||
4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 | ** ** Reset the aggregator so that it no longer contains any data. ** Future aggregator elements will contain P2 values each. */ case OP_AggReset: { AggReset(&p->agg); p->agg.nMem = pOp->p2; break; } /* Opcode: AggFocus * P2 * ** ** Pop the top of the stack and use that as an aggregator key. If ** an aggregator with that same key already exists, then make the | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 | ** ** Reset the aggregator so that it no longer contains any data. ** Future aggregator elements will contain P2 values each. */ case OP_AggReset: { AggReset(&p->agg); p->agg.nMem = pOp->p2; p->agg.axFinalize = sqliteMalloc( p->agg.nMem*sizeof(p->agg.axFinalize[0]) ); break; } /* Opcode: AggFinalizer * P2 P3 ** ** Register a finializer function for the P2-th column of the aggregate. ** The P3 parameter is a pointer to the finalizer. ** There should be one instance of this opcode immediately following ** each AggReset for each user defined aggregate function that is used ** in a SELECT. ** ** All finalizers must be registered so that user-defined aggregate ** function contexts can be deallocated if the VDBE aborts. */ case OP_AggFinalizer: { int i = pOp->p2; VERIFY( if( p->agg.nMem<=i ) goto bad_instruction; ); p->agg.axFinalize[i] = (void(*)(void*,void*))pOp->p3; break; } /* Opcode: AggFunc * P2 P3 ** ** Execute the step function for a user-defined aggregate. The ** function has P2 arguments. P3 is a pointer to the step function. ** ** The top of the stack should be the function context. The P2 ** parameters occur below the function context on the stack. The ** revised function context remains on the stack after this op-code ** finishes. */ case OP_AggFunc: { int n = pOp->p2; int i; void *pCtx; void *(*xStep)(void*,int,const char**); if( aStack[p->tos].flags & STK_AggCtx ){ pCtx = zStack[p->tos]; }else{ pCtx = 0; } VERIFY( if( n<=0 ) goto bad_instruction; ) VERIFY( if( p->tos+1<n ) goto not_enough_stack; ) for(i=p->tos-n; i<p->tos; i++){ if( (aStack[i].flags & STK_Null)==0 ){ if( Stringify(p, i) ) goto no_mem; } } xStep = (void*(*)(void*,int,const char**))pOp->p3; pCtx = xStep(pCtx, n, (const char**)&zStack[p->tos-n]); PopStack(p, n+1); VERIFY( NeedStack(p, p->tos+1); ) p->tos++; aStack[p->tos].flags = STK_AggCtx; zStack[p->tos] = (char*)pCtx; break; } /* Opcode: AggFocus * P2 * ** ** Pop the top of the stack and use that as an aggregator key. If ** an aggregator with that same key already exists, then make the |
︙ | ︙ | |||
4389 4390 4391 4392 4393 4394 4395 | zOld = 0; } pMem->s = aStack[tos]; if( pMem->s.flags & STK_Dyn ){ pMem->z = zStack[tos]; zStack[tos] = 0; aStack[tos].flags = 0; | | | 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 | zOld = 0; } pMem->s = aStack[tos]; if( pMem->s.flags & STK_Dyn ){ pMem->z = zStack[tos]; zStack[tos] = 0; aStack[tos].flags = 0; }else if( pMem->s.flags & (STK_Static|STK_AggCtx) ){ pMem->z = zStack[tos]; }else if( pMem->s.flags & STK_Str ){ pMem->z = pMem->s.z; } if( zOld ) sqliteFree(zOld); } POPSTACK; |
︙ | ︙ | |||
4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 | p->agg.pSearch = sqliteHashFirst(&p->agg.hash); }else{ p->agg.pSearch = sqliteHashNext(p->agg.pSearch); } if( p->agg.pSearch==0 ){ pc = pOp->p2 - 1; } else { p->agg.pCurrent = sqliteHashData(p->agg.pSearch); } break; } /* Opcode: SetInsert P1 * P3 ** ** If Set P1 does not exist then create it. Then insert value | > > > > > > > > > > > > > > > > > > > > > | 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 | p->agg.pSearch = sqliteHashFirst(&p->agg.hash); }else{ p->agg.pSearch = sqliteHashNext(p->agg.pSearch); } if( p->agg.pSearch==0 ){ pc = pOp->p2 - 1; } else { int i; UserFuncContext ctx; void *pCtx; 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.axFinalize[i]==0 ) continue; if( (aMem[i].s.flags & STK_AggCtx)==0 ) continue; ctx.s.flags = STK_Null; ctx.z = 0; pCtx = (void*)aMem[i].z; (*p->agg.axFinalize[i])(pCtx, &ctx); 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; } } break; } /* Opcode: SetInsert P1 * P3 ** ** If Set P1 does not exist then create it. Then insert value |
︙ | ︙ |
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.46 2002/02/24 03:25:16 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
136 137 138 139 140 141 142 143 | #define OP_AggReset 58 #define OP_AggFocus 59 #define OP_AggIncr 60 #define OP_AggNext 61 #define OP_AggSet 62 #define OP_AggGet 63 | > > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | | 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 173 174 175 176 177 178 179 180 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 207 208 209 210 211 212 213 214 215 216 | #define OP_AggReset 58 #define OP_AggFocus 59 #define OP_AggIncr 60 #define OP_AggNext 61 #define OP_AggSet 62 #define OP_AggGet 63 #define OP_AggFinalizer 64 #define OP_AggFunc 65 #define OP_SetInsert 66 #define OP_SetFound 67 #define OP_SetNotFound 68 #define OP_MakeRecord 69 #define OP_MakeKey 70 #define OP_MakeIdxKey 71 #define OP_IncrKey 72 #define OP_Goto 73 #define OP_If 74 #define OP_Halt 75 #define OP_ColumnCount 76 #define OP_ColumnName 77 #define OP_Callback 78 #define OP_NullCallback 79 #define OP_Integer 80 #define OP_String 81 #define OP_Pop 82 #define OP_Dup 83 #define OP_Pull 84 #define OP_Push 85 #define OP_MustBeInt 86 #define OP_Add 87 #define OP_AddImm 88 #define OP_Subtract 89 #define OP_Multiply 90 #define OP_Divide 91 #define OP_Remainder 92 #define OP_BitAnd 93 #define OP_BitOr 94 #define OP_BitNot 95 #define OP_ShiftLeft 96 #define OP_ShiftRight 97 #define OP_AbsValue 98 #define OP_Precision 99 #define OP_Min 100 #define OP_Max 101 #define OP_Like 102 #define OP_Glob 103 #define OP_Eq 104 #define OP_Ne 105 #define OP_Lt 106 #define OP_Le 107 #define OP_Gt 108 #define OP_Ge 109 #define OP_IsNull 110 #define OP_NotNull 111 #define OP_Negative 112 #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_UserFunc 120 #define OP_Limit 121 #define OP_MAX 121 /* ** Prototypes for the VDBE interface. See comments on the implementation ** for a description of what each of these routines does. */ Vdbe *sqliteVdbeCreate(sqlite*); void sqliteVdbeCreateCallback(Vdbe*, int*); |
︙ | ︙ |