Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Optimizations to the code generator. (CVS 1899) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
bd6649c5aae1bf182610eb267b546c29 |
User & Date: | drh 2004-08-21 17:54:45.000 |
Context
2004-08-21
| ||
19:20 | Fix a pager bug that might have made multi-database commits non-atomic if a power failure occurred at just the wrong moment. (CVS 1900) (check-in: b6eb4bf8c7 user: drh tags: trunk) | |
17:54 | Optimizations to the code generator. (CVS 1899) (check-in: bd6649c5aa user: drh tags: trunk) | |
2004-08-20
| ||
18:34 | Tcl interface transfers values directly between SQLite and Tcl_Objs, without at translation to strings. (CVS 1898) (check-in: e97c331362 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.249 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs |
︙ | ︙ | |||
92 93 94 95 96 97 98 | /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); | | > | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /* Get the VDBE program ready for execution */ if( v && pParse->nErr==0 ){ FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0; sqlite3VdbeTrace(v, trace); sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3, pParse->nTab+3, pParse->explain); pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE; pParse->colNamesSet = 0; }else if( pParse->rc==SQLITE_OK ){ pParse->rc = SQLITE_ERROR; } pParse->nTab = 0; pParse->nMem = 0; |
︙ | ︙ |
Changes to src/delete.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 DELETE FROM statements. ** | | | 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 DELETE FROM statements. ** ** $Id: delete.c,v 1.78 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" /* ** Look up every table that is named in pSrc. If any table is not found, ** add an error message to pParse->zErrMsg and return NULL. If all tables ** are found, return a pointer to the last table. |
︙ | ︙ | |||
117 118 119 120 121 122 123 | oldIdx = pParse->nTab++; } /* Resolve the column names in all the expressions. */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; | < | | < < < < | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | oldIdx = pParse->nTab++; } /* Resolve the column names in all the expressions. */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ goto delete_from_cleanup; } /* Start the view context */ if( isView ){ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); } |
︙ | ︙ | |||
258 259 260 261 262 263 264 | if( !isView ){ /* Open cursors for the table we are deleting from and all its ** indices. If there are row triggers, this happens inside the ** OP_ListRead loop because the cursor have to all be closed ** before the trigger fires. If there are no row triggers, the ** cursors are opened only once on the outside the loop. */ | < | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | if( !isView ){ /* Open cursors for the table we are deleting from and all its ** indices. If there are row triggers, this happens inside the ** OP_ListRead loop because the cursor have to all be closed ** before the trigger fires. If there are no row triggers, the ** cursors are opened only once on the outside the loop. */ sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite); /* This is the beginning of the delete loop when there are no ** row triggers */ if( !row_triggers_exist ){ addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end); } |
︙ | ︙ | |||
297 298 299 300 301 302 303 | /* Close the cursors after the loop if there are no row triggers */ if( !row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | < | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | /* Close the cursors after the loop if there are no row triggers */ if( !row_triggers_exist ){ for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } } sqlite3EndWriteOperation(pParse); /* ** Return the number of rows that were deleted. */ |
︙ | ︙ |
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.157 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> char const *sqlite3AffinityString(char affinity){ switch( affinity ){ case SQLITE_AFF_INTEGER: return "i"; |
︙ | ︙ | |||
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 | } } break; } } return nErr; } /* ** Generate an instruction that will put the integer describe by ** text z[0..n-1] on the stack. */ static void codeInteger(Vdbe *v, const char *z, int n){ int i; | > > > > > > > > > > > > > > > > > > > > > | 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 | } } break; } } return nErr; } /* ** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck(). ** ** This routine is provided as a convenience since it is very common ** to call ResolveIds() and Check() back to back. */ int sqlite3ExprResolveAndCheck( Parse *pParse, /* The parser context */ SrcList *pSrcList, /* List of tables used to resolve column names */ ExprList *pEList, /* List of expressions used to resolve "AS" */ Expr *pExpr, /* The expression to be analyzed. */ int allowAgg, /* True to allow aggregate expressions */ int *pIsAgg /* Set to TRUE if aggregates are found */ ){ if( pExpr==0 ) return 0; if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){ return 1; } return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg); } /* ** Generate an instruction that will put the integer describe by ** text z[0..n-1] on the stack. */ static void codeInteger(Vdbe *v, const char *z, int n){ int i; |
︙ | ︙ |
Changes to src/insert.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 INSERT 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 INSERT statements in SQLite. ** ** $Id: insert.c,v 1.115 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" /* ** Set P3 of the most recently inserted opcode to a column affinity ** string for index pIdx. A column affinity string has one character ** for each column in the table, according to the affinity of the column: |
︙ | ︙ | |||
329 330 331 332 333 334 335 | assert( pList!=0 ); srcTab = -1; useTempTable = 0; assert( pList ); nColumn = pList->nExpr; dummy.nSrc = 0; for(i=0; i<nColumn; i++){ | | < < < | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | assert( pList!=0 ); srcTab = -1; useTempTable = 0; assert( pList ); nColumn = pList->nExpr; dummy.nSrc = 0; for(i=0; i<nColumn; i++){ if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){ goto insert_cleanup; } } } /* Make sure the number of columns in the source data matches the number ** of columns to be inserted into the table. |
︙ | ︙ | |||
416 417 418 419 420 421 422 | sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1); } /* Open tables and indices if there are no row triggers */ if( !row_triggers_exist ){ base = pParse->nTab; | | < | 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 | sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, iCntMem, 1); } /* Open tables and indices if there are no row triggers */ if( !row_triggers_exist ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } /* If the data source is a temporary table, then we have to create ** a loop because there might be multiple rows of data. If the data ** source is a subroutine call from the SELECT statement, then we need ** to launch the SELECT statement processing. */ |
︙ | ︙ | |||
503 504 505 506 507 508 509 | } /* If any triggers exists, the opening of tables and indices is deferred ** until now. */ if( row_triggers_exist && !isView ){ base = pParse->nTab; | | < | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 | } /* If any triggers exists, the opening of tables and indices is deferred ** until now. */ if( row_triggers_exist && !isView ){ base = pParse->nTab; sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite); } /* Push the record number for the new entry onto the stack. The ** record number is a randomly generate integer created by NewRecno ** except when the table has an INTEGER PRIMARY KEY column, in which ** case the record number is the same as that column. */ |
︙ | ︙ | |||
989 990 991 992 993 994 995 | if( isUpdate && recnoChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); } } /* | | < < < | > > > > > | | | > | > | 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 | if( isUpdate && recnoChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); } } /* ** Generate code that will open cursors for a table and for all ** indices of that table. The "base" parameter is the cursor number used ** for the table. Indices are opened on subsequent cursors. */ void sqlite3OpenTableAndIndices( Parse *pParse, /* Parsing context */ Table *pTab, /* Table to be opened */ int base, /* Cursor number assigned to the table */ int op /* OP_OpenRead or OP_OpenWrite */ ){ int i; Index *pIdx; Vdbe *v = sqlite3GetVdbe(pParse); assert( v!=0 ); sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeAddOp(v, op, base, pTab->tnum); sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol); for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0); sqlite3VdbeOp3(v, op, i+base, pIdx->tnum, (char*)&pIdx->keyInfo, P3_KEYINFO); } if( pParse->nTab<=base+i ){ pParse->nTab = base+i; } } |
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.253 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** The following constant value is used by the SQLITE_BIGENDIAN and |
︙ | ︙ | |||
1249 1250 1251 1252 1253 1254 1255 | ** the prior execution is returned. ** ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc = sqlite3VdbeReset((Vdbe*)pStmt); | | | 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | ** the prior execution is returned. ** ** This routine sets the error code and string returned by ** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16(). */ int sqlite3_reset(sqlite3_stmt *pStmt){ int rc = sqlite3VdbeReset((Vdbe*)pStmt); sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0); return rc; } /* ** Register a new collation sequence with the database handle db. */ int sqlite3_create_collation( |
︙ | ︙ |
Changes to src/pragma.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 April 6 ** ** 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 April 6 ** ** 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.60 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) # include "pager.h" # include "btree.h" |
︙ | ︙ | |||
534 535 536 537 538 539 540 | ** messages have been generated, output OK. Otherwise output the ** error message */ static VdbeOpList endCode[] = { { OP_MemLoad, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 0, 0}, /* 2 */ | | | 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 | ** messages have been generated, output OK. Otherwise output the ** error message */ static VdbeOpList endCode[] = { { OP_MemLoad, 0, 0, 0}, { OP_Integer, 0, 0, 0}, { OP_Ne, 0, 0, 0}, /* 2 */ { OP_String8, 0, 0, "ok"}, { OP_Callback, 1, 0, 0}, }; /* Initialize the VDBE program */ if( sqlite3ReadSchema(pParse) ) goto pragma_out; sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, "integrity_check", P3_STATIC); |
︙ | ︙ | |||
585 586 587 588 589 590 591 | sqlite3CodeVerifySchema(pParse, i); for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; if( pTab->pIndex==0 ) continue; | < | < < < < < < < | | | | | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | sqlite3CodeVerifySchema(pParse, i); for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; int loopTop; if( pTab->pIndex==0 ) continue; sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead); sqlite3VdbeAddOp(v, OP_Integer, 0, 0); sqlite3VdbeAddOp(v, OP_MemStore, 1, 1); loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0); sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0); for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){ int jmp2; static VdbeOpList idxErr[] = { { OP_MemIncr, 0, 0, 0}, { OP_String8, 0, 0, "rowid "}, { OP_Recno, 1, 0, 0}, { OP_String8, 0, 0, " missing from index "}, { OP_String8, 0, 0, 0}, /* 4 */ { OP_Concat8, 4, 0, 0}, { OP_Callback, 1, 0, 0}, }; sqlite3GenerateIndexKey(v, pIdx, 1); jmp2 = sqlite3VdbeAddOp(v, OP_Found, j+2, 0); addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); sqlite3VdbeChangeP3(v, addr+4, pIdx->zName, P3_STATIC); sqlite3VdbeChangeP2(v, jmp2, sqlite3VdbeCurrentAddr(v)); |
︙ | ︙ | |||
628 629 630 631 632 633 634 | { OP_Rewind, 0, 0, 0}, /* 2 */ { OP_MemIncr, 2, 0, 0}, { OP_Next, 0, 0, 0}, /* 4 */ { OP_MemLoad, 1, 0, 0}, { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 7 */ { OP_MemIncr, 0, 0, 0}, | | | | | 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | { OP_Rewind, 0, 0, 0}, /* 2 */ { OP_MemIncr, 2, 0, 0}, { OP_Next, 0, 0, 0}, /* 4 */ { OP_MemLoad, 1, 0, 0}, { OP_MemLoad, 2, 0, 0}, { OP_Eq, 0, 0, 0}, /* 7 */ { OP_MemIncr, 0, 0, 0}, { OP_String8, 0, 0, "wrong # of entries in index "}, { OP_String8, 0, 0, 0}, /* 10 */ { OP_Concat8, 2, 0, 0}, { OP_Callback, 1, 0, 0}, }; if( pIdx->tnum==0 ) continue; addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx); sqlite3VdbeChangeP1(v, addr+2, j+2); sqlite3VdbeChangeP2(v, addr+2, addr+5); sqlite3VdbeChangeP1(v, addr+4, j+2); |
︙ | ︙ |
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.203 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
79 80 81 82 83 84 85 | */ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; Token *apAll[3]; Token *p; static struct { const char *zKeyword; | | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | */ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int jointype = 0; Token *apAll[3]; Token *p; static struct { const char *zKeyword; u8 nChar; u8 code; } keywords[] = { { "natural", 7, JT_NATURAL }, { "left", 4, JT_LEFT|JT_OUTER }, { "right", 5, JT_RIGHT|JT_OUTER }, { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, { "outer", 5, JT_OUTER }, { "inner", 5, JT_INNER }, |
︙ | ︙ | |||
800 801 802 803 804 805 806 | ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ Table *pTab; int i, j; ExprList *pEList; | | | > | | | | | | | | | | | | | | 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 | ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ Table *pTab; int i, j; ExprList *pEList; Column *aCol, *pCol; if( fillInColumnList(pParse, pSelect) ){ return 0; } pTab = sqliteMalloc( sizeof(Table) ); if( pTab==0 ){ return 0; } pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0; pEList = pSelect->pEList; pTab->nCol = pEList->nExpr; assert( pTab->nCol>0 ); pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol ); for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){ Expr *pR; char *zType; Expr *p = pEList->a[i].pExpr; assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 ); if( pEList->a[i].zName ){ pCol->zName = sqliteStrDup(pEList->a[i].zName); }else if( p->op==TK_DOT && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){ int cnt; sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, 0); for(j=cnt=0; j<i; j++){ if( sqlite3StrICmp(aCol[j].zName, pCol->zName)==0 ){ int n; char zBuf[30]; sprintf(zBuf,"_%d",++cnt); n = strlen(zBuf); sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, zBuf,n,0); j = -1; } } }else if( p->span.z && p->span.z[0] ){ sqlite3SetNString(&pCol->zName, p->span.z, p->span.n, 0); }else{ char zBuf[30]; sprintf(zBuf, "column%d", i+1); pCol->zName = sqliteStrDup(zBuf); } sqlite3Dequote(pCol->zName); zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p)); pCol->zType = zType; pCol->affinity = SQLITE_AFF_NUMERIC; if( zType ){ pCol->affinity = sqlite3AffinityType(zType, strlen(zType)); } pCol->pColl = sqlite3ExprCollSeq(pParse, p); if( !pCol->pColl ){ pCol->pColl = pParse->db->pDfltColl; } } pTab->iPKey = -1; return pTab; } /* |
︙ | ︙ | |||
885 886 887 888 889 890 891 892 893 894 895 896 897 898 | ** in pParse and return non-zero. */ static int fillInColumnList(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; Table *pTab; if( p==0 || p->pSrc==0 ) return 1; pTabList = p->pSrc; pEList = p->pEList; /* Look up every table in the table list. */ | > | | | | | | < | | | < | | | | | | 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 | ** in pParse and return non-zero. */ static int fillInColumnList(Parse *pParse, Select *p){ int i, j, k, rc; SrcList *pTabList; ExprList *pEList; Table *pTab; struct SrcList_item *pFrom; if( p==0 || p->pSrc==0 ) return 1; pTabList = p->pSrc; pEList = p->pEList; /* Look up every table in the table list. */ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ if( pFrom->pTab ){ /* This routine has run before! No need to continue */ return 0; } if( pFrom->zName==0 ){ /* A sub-query in the FROM clause of a SELECT */ assert( pFrom->pSelect!=0 ); if( pFrom->zAlias==0 ){ char zFakeName[60]; sprintf(zFakeName, "sqlite_subquery_%p_", (void*)pFrom->pSelect); sqlite3SetString(&pFrom->zAlias, zFakeName, 0); } pFrom->pTab = pTab = sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect); if( pTab==0 ){ return 1; } /* The isTransient flag indicates that the Table structure has been ** dynamically allocated and may be freed at any time. In other words, ** pTab is not pointing to a persistent table structure that defines ** part of the schema. */ pTab->isTransient = 1; }else{ /* An ordinary table or view name in the FROM clause */ pFrom->pTab = pTab = sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase); if( pTab==0 ){ return 1; } if( pTab->pSelect ){ /* We reach here if the named table is a really a view */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ return 1; } /* If pFrom->pSelect!=0 it means we are dealing with a ** view within a view. The SELECT structure has already been ** copied by the outer view so we can skip the copy step here ** in the inner view. */ if( pFrom->pSelect==0 ){ pFrom->pSelect = sqlite3SelectDup(pTab->pSelect); } } } } /* Process NATURAL keywords, and ON and USING clauses of joins. */ |
︙ | ︙ | |||
990 991 992 993 994 995 996 | int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName; /* text of name of TABLE */ if( pE->op==TK_DOT && pE->pLeft ){ zTName = sqlite3NameFromToken(&pE->pLeft->token); }else{ zTName = 0; } | | | | | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 | int tableSeen = 0; /* Set to 1 when TABLE matches */ char *zTName; /* text of name of TABLE */ if( pE->op==TK_DOT && pE->pLeft ){ zTName = sqlite3NameFromToken(&pE->pLeft->token); }else{ zTName = 0; } for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ Table *pTab = pFrom->pTab; char *zTabName = pFrom->zAlias; if( zTabName==0 || zTabName[0]==0 ){ zTabName = pTab->zName; } if( zTName && (zTabName==0 || zTabName[0]==0 || sqlite3StrICmp(zTName, zTabName)!=0) ){ continue; } |
︙ | ︙ | |||
1184 1185 1186 1187 1188 1189 1190 | Vdbe *v = pParse->pVdbe; if( v==0 ){ v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); } return v; } | < < < < < < < < < < < < < < < | 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 | Vdbe *v = pParse->pVdbe; if( v==0 ){ v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db); } return v; } /* ** Compute the iLimit and iOffset fields of the SELECT based on the ** nLimit and nOffset fields. nLimit and nOffset hold the integers ** that appear in the original SQL statement after the LIMIT and OFFSET ** keywords. Or that hold -1 and 0 if those keywords are omitted. ** iLimit and iOffset are the integer memory register numbers for ** counters used to compute the limit and offset. If there is no |
︙ | ︙ | |||
2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 | eList.a[0].pExpr = pExpr; selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0); sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp(v, OP_Close, base, 0); return 1; } /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the ** value of eDest and iParm. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 | eList.a[0].pExpr = pExpr; selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont, 0); sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp(v, OP_Close, base, 0); return 1; } /* ** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return ** the number of errors seen. ** ** An ORDER BY or GROUP BY is a list of expressions. If any expression ** is an integer constant, then that expression is replaced by the ** corresponding entry in the result set. */ static int processOrderGroupBy( Parse *pParse, /* Parsing context */ ExprList *pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ SrcList *pTabList, /* The FROM clause */ ExprList *pEList, /* The result set */ int isAgg, /* True if aggregate functions are involved */ const char *zType /* Either "ORDER" or "GROUP", as appropriate */ ){ int i; if( pOrderBy==0 ) return 0; for(i=0; i<pOrderBy->nExpr; i++){ int iCol; Expr *pE = pOrderBy->a[i].pExpr; if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){ sqlite3ExprDelete(pE); pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); } if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){ return 1; } if( sqlite3ExprIsConstant(pE) ){ if( sqlite3ExprIsInteger(pE, &iCol)==0 ){ sqlite3ErrorMsg(pParse, "%s BY terms must not be non-integer constants", zType); return 1; }else if( iCol<=0 || iCol>pEList->nExpr ){ sqlite3ErrorMsg(pParse, "%s BY column number %d out of range - should be " "between 1 and %d", zType, iCol, pEList->nExpr); return 1; } } } return 0; } /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the ** value of eDest and iParm. ** |
︙ | ︙ | |||
2250 2251 2252 2253 2254 2255 2256 | /* At this point, we should have allocated all the cursors that we ** need to handle subquerys and temporary tables. ** ** Resolve the column names and do a semantics check on all the expressions. */ for(i=0; i<pEList->nExpr; i++){ | | < < | < | | | < < < < | < < | < < < < | < < < < | < < < < < < < < < < < < < < < < < < < | < < < < < < < < | < < < < < < < < < < < < < < < < < | 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 | /* At this point, we should have allocated all the cursors that we ** need to handle subquerys and temporary tables. ** ** Resolve the column names and do a semantics check on all the expressions. */ for(i=0; i<pEList->nExpr; i++){ if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr, 1, &isAgg) ){ goto select_end; } } if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){ goto select_end; } if( pHaving ){ if( pGroupBy==0 ){ sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); goto select_end; } if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){ goto select_end; } } if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER") || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP") ){ goto select_end; } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; |
︙ | ︙ |
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.316 2004/08/21 17:54:45 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ #include "config.h" #include "sqlite3.h" #include "hash.h" |
︙ | ︙ | |||
884 885 886 887 888 889 890 | */ struct WhereInfo { Parse *pParse; SrcList *pTabList; /* List of tables in the join */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ | < < | 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | */ struct WhereInfo { Parse *pParse; SrcList *pTabList; /* List of tables in the join */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ WhereLevel a[1]; /* Information about each nest loop in the WHERE */ }; /* ** An instance of the following structure contains all information ** needed to generate code for a single SELECT statement. ** |
︙ | ︙ | |||
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 | int sqlite3RunVacuum(char**, sqlite*); int sqlite3GlobCompare(const unsigned char*,const unsigned char*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*); int sqlite3ExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqlite3GetVdbe(Parse*); void sqlite3Randomness(int, void*); void sqlite3RollbackAll(sqlite*); void sqlite3CodeVerifySchema(Parse*, int); void sqlite3BeginTransaction(Parse*); void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(sqlite*, Vdbe*, Table*, int, int); void sqlite3GenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); | > | | 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 | int sqlite3RunVacuum(char**, sqlite*); int sqlite3GlobCompare(const unsigned char*,const unsigned char*); char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*); int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*); int sqlite3ExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqlite3GetVdbe(Parse*); void sqlite3Randomness(int, void*); void sqlite3RollbackAll(sqlite*); void sqlite3CodeVerifySchema(Parse*, int); void sqlite3BeginTransaction(Parse*); void sqlite3CommitTransaction(Parse*); void sqlite3RollbackTransaction(Parse*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(sqlite*, Vdbe*, Table*, int, int); void sqlite3GenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); void sqlite3OpenTableAndIndices(Parse*, Table*, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); void sqlite3EndWriteOperation(Parse*); Expr *sqlite3ExprDup(Expr*); void sqlite3TokenCopy(Token*, Token*); ExprList *sqlite3ExprListDup(ExprList*); SrcList *sqlite3SrcListDup(SrcList*); IdList *sqlite3IdListDup(IdList*); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
643 644 645 646 647 648 649 | TriggerStep *pStepList, /* List of statements inside the trigger body */ int orconfin /* Conflict algorithm. (OE_Abort, etc) */ ){ TriggerStep * pTriggerStep = pStepList; int orconf; while( pTriggerStep ){ | < < | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | TriggerStep *pStepList, /* List of statements inside the trigger body */ int orconfin /* Conflict algorithm. (OE_Abort, etc) */ ){ TriggerStep * pTriggerStep = pStepList; int orconf; while( pTriggerStep ){ orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select * ss = sqlite3SelectDup(pTriggerStep->pSelect); assert(ss); assert(ss->pSrc); |
︙ | ︙ | |||
692 693 694 695 696 697 698 | sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0); sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0); break; } default: assert(0); } | < | 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0); sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0); break; } default: assert(0); } pTriggerStep = pTriggerStep->pNext; } return 0; } /* |
︙ | ︙ |
Changes to src/update.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 UPDATE statements. ** | | | 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 UPDATE statements. ** ** $Id: update.c,v 1.86 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" /* ** Process an UPDATE statement. ** ** UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL; |
︙ | ︙ | |||
107 108 109 110 111 112 113 | ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRecno = 0; for(i=0; i<pChanges->nExpr; i++){ | | < < | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | ** of the UPDATE statement. Also find the column index ** for each column to be updated in the pChanges array. For each ** column to be updated, make sure we have authorization to change ** that column. */ chngRecno = 0; for(i=0; i<pChanges->nExpr; i++){ if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pChanges->a[i].pExpr, 0, 0) ){ goto update_cleanup; } for(j=0; j<pTab->nCol; j++){ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){ if( j==pTab->iPKey ){ chngRecno = 1; pRecnoExpr = pChanges->a[i].pExpr; |
︙ | ︙ | |||
186 187 188 189 190 191 192 | aIdxUsed[j] = 0; } } /* Resolve the column names in all the expressions in the ** WHERE clause. */ | < | | < < < < | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | aIdxUsed[j] = 0; } } /* Resolve the column names in all the expressions in the ** WHERE clause. */ if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){ goto update_cleanup; } /* Start the view context */ if( isView ){ sqlite3AuthContextPush(pParse, &sContext, pTab->zName); } |
︙ | ︙ | |||
408 409 410 411 412 413 414 | if( row_triggers_exist ){ if( !isView ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ) sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | < | 401 402 403 404 405 406 407 408 409 410 411 412 413 414 | if( row_triggers_exist ){ if( !isView ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ) sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, newIdx, oldIdx, onError, addr) ){ goto update_cleanup; } } |
︙ | ︙ | |||
431 432 433 434 435 436 437 | if( !row_triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); } } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); | < | 423 424 425 426 427 428 429 430 431 432 433 434 435 436 | if( !row_triggers_exist ){ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){ if( openAll || aIdxUsed[i] ){ sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0); } } sqlite3VdbeAddOp(v, OP_Close, iCur, 0); }else{ sqlite3VdbeAddOp(v, OP_Close, newIdx, 0); sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0); } sqlite3EndWriteOperation(pParse); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.409 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
257 258 259 260 261 262 263 | /* ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ static Cursor *allocateCursor(Vdbe *p, int iCur){ Cursor *pCx; | < < < < | < < < < < < | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | /* ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ static Cursor *allocateCursor(Vdbe *p, int iCur){ Cursor *pCx; assert( iCur<p->nCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p->apCsr[iCur]); } p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) ); return pCx; } /* |
︙ | ︙ | |||
798 799 800 801 802 803 804 | ** sqlite3_bind() API. */ case OP_Variable: { int j = pOp->p1 - 1; assert( j>=0 && j<p->nVar ); pTos++; | < | | 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 | ** sqlite3_bind() API. */ case OP_Variable: { int j = pOp->p1 - 1; assert( j>=0 && j<p->nVar ); pTos++; memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS); pTos->xDel = 0; if( pTos->flags&(MEM_Str|MEM_Blob) ){ pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short); pTos->flags |= MEM_Static; } break; } |
︙ | ︙ | |||
4052 4053 4054 4055 4056 4057 4058 | apSorter[i] = 0; } while( p->pSort ){ pElem = p->pSort; p->pSort = pElem->pNext; pElem->pNext = 0; for(i=0; i<NSORT-1; i++){ | | | 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 | apSorter[i] = 0; } while( p->pSort ){ pElem = p->pSort; p->pSort = pElem->pNext; pElem->pNext = 0; for(i=0; i<NSORT-1; i++){ if( apSorter[i]==0 ){ apSorter[i] = pElem; break; }else{ pElem = Merge(apSorter[i], pElem, pKeyInfo); apSorter[i] = 0; } } |
︙ | ︙ | |||
4119 4120 4121 4122 4123 4124 4125 | ** stack is popped once if P2 is 1. If P2 is zero, then ** the original data remains on the stack. */ case OP_MemStore: { int i = pOp->p1; Mem *pMem; assert( pTos>=p->aStack ); | < < < < < < < < < < < < < < < | < < < < < | < < < < < < < | < < | | > > > > | | | | 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 | ** stack is popped once if P2 is 1. If P2 is zero, then ** the original data remains on the stack. */ case OP_MemStore: { int i = pOp->p1; Mem *pMem; assert( pTos>=p->aStack ); assert( i<p->nMem ); Deephemeralize(pTos); pMem = &p->aMem[i]; Release(pMem); *pMem = *pTos; pTos->flags = MEM_Null; if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } pTos--; /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will ** restore the top of the stack to its original value. */ if( pOp->p2 ){ break; } } /* Opcode: MemLoad P1 * * ** ** Push a copy of the value in memory location P1 onto the stack. ** ** If the value is a string, then the value pushed is a pointer to ** the string that is stored in the memory location. If the memory ** location is subsequently changed (using OP_MemStore) then the |
︙ | ︙ | |||
4334 4335 4336 4337 4338 4339 4340 | rc = sqlite3BtreeMoveto(p->agg.pCsr, zKey, nKey, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res==0 ){ rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*), (char *)&p->agg.pCurrent); | < < < > | | < | 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 | rc = sqlite3BtreeMoveto(p->agg.pCsr, zKey, nKey, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } if( res==0 ){ rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*), (char *)&p->agg.pCurrent); pc = pOp->p2 - 1; }else{ rc = AggInsert(&p->agg, zKey, nKey); } if( rc!=SQLITE_OK ){ goto abort_due_to_error; } Release(pTos); pTos--; break; } /* Opcode: AggSet * P2 * |
︙ | ︙ | |||
4367 4368 4369 4370 4371 4372 4373 | assert( pTos>=p->aStack ); if( pFocus==0 ) goto no_mem; assert( i>=0 && i<p->agg.nMem ); Deephemeralize(pTos); pMem = &pFocus->aMem[i]; Release(pMem); *pMem = *pTos; | < | | | 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 | assert( pTos>=p->aStack ); if( pFocus==0 ) goto no_mem; assert( i>=0 && i<p->agg.nMem ); Deephemeralize(pTos); pMem = &pFocus->aMem[i]; Release(pMem); *pMem = *pTos; pTos->flags = MEM_Null; if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } pTos--; break; } /* Opcode: AggGet * P2 * |
︙ | ︙ | |||
4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 | ** AggReset AggFocus AggNext. In other words, you must execute ** AggReset first, then zero or more AggFocus operations, then ** zero or more AggNext operations. You must not execute an AggFocus ** in between an AggNext and an AggReset. */ case OP_AggNext: { int res; CHECK_FOR_INTERRUPT; if( p->agg.searching==0 ){ p->agg.searching = 1; if( p->agg.pCsr ){ rc = sqlite3BtreeFirst(p->agg.pCsr, &res); | > < < > < | > | | | | | | | < | | | | | | 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 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 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 | ** AggReset AggFocus AggNext. In other words, you must execute ** AggReset first, then zero or more AggFocus operations, then ** zero or more AggNext operations. You must not execute an AggFocus ** in between an AggNext and an AggReset. */ case OP_AggNext: { int res; assert( rc==SQLITE_OK ); CHECK_FOR_INTERRUPT; if( p->agg.searching==0 ){ p->agg.searching = 1; if( p->agg.pCsr ){ rc = sqlite3BtreeFirst(p->agg.pCsr, &res); }else{ res = 0; } }else{ if( p->agg.pCsr ){ rc = sqlite3BtreeNext(p->agg.pCsr, &res); }else{ res = 1; } } if( rc!=SQLITE_OK ) goto abort_due_to_error; if( res!=0 ){ pc = pOp->p2 - 1; }else{ int i; sqlite3_context ctx; Mem *aMem; if( p->agg.pCsr ){ rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*), (char *)&p->agg.pCurrent); if( rc!=SQLITE_OK ) goto abort_due_to_error; } aMem = p->agg.pCurrent->aMem; for(i=0; i<p->agg.nMem; i++){ FuncDef *pFunc = p->agg.apFunc[i]; Mem *pMem = &aMem[i]; if( pFunc==0 || pFunc->xFinalize==0 ) continue; ctx.s.flags = MEM_Null; ctx.s.z = pMem->zShort; ctx.pAgg = (void*)pMem->z; ctx.cnt = pMem->i; ctx.isStep = 0; ctx.pFunc = pFunc; pFunc->xFinalize(&ctx); pMem->z = ctx.pAgg; if( pMem->z && pMem->z!=pMem->zShort ){ sqliteFree( pMem->z ); } *pMem = ctx.s; if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } } } break; } /* Opcode: Vacuum * * * |
︙ | ︙ |
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.90 2004/08/21 17:54:45 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
106 107 108 109 110 111 112 | void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeDequoteP3(Vdbe*, int addr); int sqlite3VdbeFindOp(Vdbe*, int, int, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); | | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N); void sqlite3VdbeDequoteP3(Vdbe*, int addr); int sqlite3VdbeFindOp(Vdbe*, int, int, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); void sqlite3VdbeTrace(Vdbe*,FILE*); int sqlite3VdbeReset(Vdbe*); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
307 308 309 310 311 312 313 | Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ | < < < | | < < | 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ Mem **apArg; /* Arguments to currently executing user function */ Mem *aColName; /* Column names to return */ int nCursor; /* Number of slots in apCsr[] */ Cursor **apCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ int nVar; /* Number of entries in aVar[] */ Mem *aVar; /* Values for the OP_Variable opcode. */ char **azVar; /* Name of variables */ int okVar; /* True if azVar[] has been initialized */ int magic; /* Magic number for sanity checking */ int nMem; /* Number of memory locations currently allocated */ Mem *aMem; /* The memory locations */ Agg agg; /* Aggregate information */ int nCallback; /* Number of callbacks invoked so far */ Keylist *pList; /* A list of ROWIDs */ int keylistStackDepth; /* The size of the "keylist" stack */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
410 411 412 413 414 415 416 | return SQLITE_MISUSE; } if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE, 0); return SQLITE_RANGE; } i--; | | | 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 | return SQLITE_MISUSE; } if( i<1 || i>p->nVar ){ sqlite3Error(p->db, SQLITE_RANGE, 0); return SQLITE_RANGE; } i--; pVar = &p->aVar[i]; sqlite3VdbeMemRelease(pVar); pVar->flags = MEM_Null; sqlite3Error(p->db, SQLITE_OK, 0); return SQLITE_OK; } /* |
︙ | ︙ | |||
435 436 437 438 439 440 441 | Mem *pVar; int rc; rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } | | | | | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 | Mem *pVar; int rc; rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, 0, xDel); return rc; } int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue); } return rc; } int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); } int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){ int rc; Vdbe *p = (Vdbe *)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue); } return rc; } int sqlite3_bind_null(sqlite3_stmt* p, int i){ return vdbeUnbind((Vdbe *)p, i); } int sqlite3_bind_text( |
︙ | ︙ | |||
478 479 480 481 482 483 484 | Mem *pVar; int rc; rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } | | | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 | Mem *pVar; int rc; rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, SQLITE_UTF8, xDel); if( rc ){ return rc; } rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc); return rc; } |
︙ | ︙ | |||
501 502 503 504 505 506 507 | Mem *pVar; int rc; rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } | | | 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | Mem *pVar; int rc; rc = vdbeUnbind(p, i); if( rc || zData==0 ){ return rc; } pVar = &p->aVar[i-1]; rc = sqlite3VdbeMemSetStr(pVar, zData, nData, SQLITE_UTF16NATIVE, xDel); if( rc ){ return rc; } rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc); return rc; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
543 544 545 546 547 548 549 550 551 552 553 554 555 556 | ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqlite3VdbeExec(). */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); | > > | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqlite3VdbeExec(). */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ int nVar, /* Number of '?' see in the SQL statement */ int nMem, /* Number of memory cells to allocate */ int nCursor, /* Number of cursors to allocate */ int isExplain /* True if the EXPLAIN keywords is present */ ){ int n; assert( p!=0 ); assert( p->magic==VDBE_MAGIC_INIT ); |
︙ | ︙ | |||
564 565 566 567 568 569 570 | ** stack. And the stack never grows on successive executions of the ** same loop. So the total number of instructions is an upper bound ** on the maximum stack depth required. ** ** Allocation all the stack space we will ever need. */ if( p->aStack==0 ){ | < | | > > > | | | | > > > > > | | > > > > | 566 567 568 569 570 571 572 573 574 575 576 577 578 579 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 | ** stack. And the stack never grows on successive executions of the ** same loop. So the total number of instructions is an upper bound ** on the maximum stack depth required. ** ** Allocation all the stack space we will ever need. */ if( p->aStack==0 ){ assert( nVar>=0 ); n = isExplain ? 10 : p->nOp; p->aStack = sqliteMalloc( n*(sizeof(p->aStack[0])+sizeof(Mem*)) /* aStack, apArg */ + nVar*sizeof(Mem) /* aVar */ + nVar*sizeof(char*) /* azVar */ + nMem*sizeof(Mem) /* aMem */ + nCursor*sizeof(Cursor*) /* apCsr */ ); if( !sqlite3_malloc_failed ){ p->apArg = (Mem **)&p->aStack[n]; p->aVar = (Mem *)&p->apArg[n]; p->azVar = (char**)&p->aVar[nVar]; p->okVar = 0; p->nVar = nVar; p->aMem = (Mem*)&p->azVar[nVar]; p->nMem = nMem; p->apCsr = (Cursor**)&p->aMem[nMem]; p->nCursor = nCursor; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; } for(n=0; n<nMem; n++){ p->aMem[n].flags = MEM_Null; } } } #ifdef SQLITE_DEBUG if( (p->db->flags & SQLITE_VdbeListing)!=0 || sqlite3OsFileExists("vdbe_explain") ){ |
︙ | ︙ | |||
796 797 798 799 800 801 802 803 804 805 | } /* ** Close all cursors */ static void closeAllCursors(Vdbe *p){ int i; for(i=0; i<p->nCursor; i++){ sqlite3VdbeFreeCursor(p->apCsr[i]); } | > > < < < < | | | < < < < < < < < < < < < < < < < < < | 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 | } /* ** Close all cursors */ static void closeAllCursors(Vdbe *p){ int i; if( p->apCsr==0 ) return; for(i=0; i<p->nCursor; i++){ sqlite3VdbeFreeCursor(p->apCsr[i]); p->apCsr[i] = 0; } } /* ** Clean up the VM after execution. ** ** This routine will automatically close any cursors, lists, and/or ** sorters that were left open. It also deletes the values of ** variables in the aVar[] array. */ static void Cleanup(Vdbe *p){ int i; if( p->aStack ){ Mem *pTos = p->pTos; while( pTos>=p->aStack ){ sqlite3VdbeMemRelease(pTos); pTos--; } p->pTos = pTos; } closeAllCursors(p); for(i=0; i<p->nMem; i++){ sqlite3VdbeMemRelease(&p->aMem[i]); } if( p->pList ){ sqlite3VdbeKeylistFree(p->pList); p->pList = 0; } sqlite3VdbeSorterReset(p); sqlite3VdbeAggReset(0, &p->agg, 0); if( p->keylistStack ){ int ii; for(ii = 0; ii < p->keylistStackDepth; ii++){ sqlite3VdbeKeylistFree(p->keylistStack[ii]); } sqliteFree(p->keylistStack); |
︙ | ︙ | |||
1356 1357 1358 1359 1360 1361 1362 | if( pOp->p3type==P3_VDBEFUNC ){ VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); sqliteFree(pVdbeFunc); } } for(i=0; i<p->nVar; i++){ | | | 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 | if( pOp->p3type==P3_VDBEFUNC ){ VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; sqlite3VdbeDeleteAuxData(pVdbeFunc, 0); sqliteFree(pVdbeFunc); } } for(i=0; i<p->nVar; i++){ sqlite3VdbeMemRelease(&p->aVar[i]); } sqliteFree(p->aOp); sqliteFree(p->aLabel); sqliteFree(p->aStack); if( p->aColName ){ for(i=0; i<(p->nResColumn)*2; i++){ sqlite3VdbeMemRelease(&(p->aColName[i])); |
︙ | ︙ |
Changes to src/where.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 module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** | | | 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 module contains C code that generates VDBE code used to process ** the WHERE clause of SQL statements. ** ** $Id: where.c,v 1.112 2004/08/21 17:54:45 drh Exp $ */ #include "sqliteInt.h" /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by an AND operator. |
︙ | ︙ | |||
480 481 482 483 484 485 486 | pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); if( sqlite3_malloc_failed ){ /* sqliteFree(pWInfo); // Leak memory when malloc fails */ return 0; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; | < | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); if( sqlite3_malloc_failed ){ /* sqliteFree(pWInfo); // Leak memory when malloc fails */ return 0; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->iBreak = sqlite3VdbeMakeLabel(v); /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (pTabList->nSrc==0 || sqlite3ExprIsConstant(pWhere)) ){ sqlite3ExprIfFalse(pParse, pWhere, pWInfo->iBreak, 1); |
︙ | ︙ | |||
682 683 684 685 686 687 688 | } pWInfo->a[i].pIdx = pBestIdx; pWInfo->a[i].score = bestScore; pWInfo->a[i].bRev = 0; loopMask |= mask; if( pBestIdx ){ pWInfo->a[i].iCur = pParse->nTab++; | < | 681 682 683 684 685 686 687 688 689 690 691 692 693 694 | } pWInfo->a[i].pIdx = pBestIdx; pWInfo->a[i].score = bestScore; pWInfo->a[i].bRev = 0; loopMask |= mask; if( pBestIdx ){ pWInfo->a[i].iCur = pParse->nTab++; } } /* Check to see if the ORDER BY clause is or can be satisfied by the ** use of an index on the first table. */ if( ppOrderBy && *ppOrderBy && pTabList->nSrc>0 ){ |
︙ | ︙ | |||
717 718 719 720 721 722 723 | pSortIdx = findSortingIndex(pParse, pTab, pTabList->a[0].iCursor, *ppOrderBy, pIdx, nEqCol, &bRev); } if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){ if( pIdx==0 ){ pWInfo->a[0].pIdx = pSortIdx; pWInfo->a[0].iCur = pParse->nTab++; | < | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 | pSortIdx = findSortingIndex(pParse, pTab, pTabList->a[0].iCursor, *ppOrderBy, pIdx, nEqCol, &bRev); } if( pSortIdx && (pIdx==0 || pIdx==pSortIdx) ){ if( pIdx==0 ){ pWInfo->a[0].pIdx = pSortIdx; pWInfo->a[0].iCur = pParse->nTab++; } pWInfo->a[0].bRev = bRev; *ppOrderBy = 0; } } /* Open all tables in the pTabList and all indices used by those tables. |
︙ | ︙ | |||
1206 1207 1208 1209 1210 1211 1212 | if( pTab->isTransient || pTab->pSelect ) continue; pLevel = &pWInfo->a[i]; sqlite3VdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0); if( pLevel->pIdx!=0 ){ sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0); } } | < < < < < | 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 | if( pTab->isTransient || pTab->pSelect ) continue; pLevel = &pWInfo->a[i]; sqlite3VdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0); if( pLevel->pIdx!=0 ){ sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0); } } sqliteFree(pWInfo); return; } |
Changes to test/crash.test.
︙ | ︙ | |||
16 17 18 19 20 21 22 | # module "crashtest" compiled with the special "os_test.c" backend is used. # The os_test.c simulates the kind of file corruption that can occur # when writes are happening at the moment of power loss. # # The special crash-test module with its os_test.c backend only works # on Unix. # | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | # module "crashtest" compiled with the special "os_test.c" backend is used. # The os_test.c simulates the kind of file corruption that can occur # when writes are happening at the moment of power loss. # # The special crash-test module with its os_test.c backend only works # on Unix. # # $Id: crash.test,v 1.8 2004/08/21 17:54:46 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # set repeats 100 set repeats 10 |
︙ | ︙ | |||
163 164 165 166 167 168 169 | execsql { BEGIN } for {set n 0} {$n < 1000} {incr n} { execsql "INSERT INTO abc VALUES($n, [expr 2*$n], [expr 3*$n])" } execsql { COMMIT } set ::sig [signature] execsql { SELECT sum(a), sum(b), sum(c) from abc } | | | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | execsql { BEGIN } for {set n 0} {$n < 1000} {incr n} { execsql "INSERT INTO abc VALUES($n, [expr 2*$n], [expr 3*$n])" } execsql { COMMIT } set ::sig [signature] execsql { SELECT sum(a), sum(b), sum(c) from abc } } {499500.0 999000.0 1498500.0} do_test crash-2.2 { expr [file size test.db] / 1024 } {19} do_test crash-2.3 { crashsql 2 test.db-journal { DELETE FROM abc WHERE a < 800; } |
︙ | ︙ | |||
269 270 271 272 273 274 275 276 277 278 279 280 281 282 | signature } $sig do_test crash-4.1.$i.3 { signature2 } $sig2 } set i 0 while {[incr i]} { set sig [signature] set sig2 [signature2] set ::fin 0 do_test crash-4.2.$i.1 { set c [crashsql $i test2.db-journal " ATTACH 'test2.db' AS aux; | > | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | signature } $sig do_test crash-4.1.$i.3 { signature2 } $sig2 } set i 0 set i 55 while {[incr i]} { set sig [signature] set sig2 [signature2] set ::fin 0 do_test crash-4.2.$i.1 { set c [crashsql $i test2.db-journal " ATTACH 'test2.db' AS aux; |
︙ | ︙ |