Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | New Next opcode and indexing style implemented. (CVS 304) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
decbeb9151885fee473b3fa58c8cf78a |
User & Date: | drh 2001-11-07 16:48:27.000 |
Context
2001-11-08
| ||
00:45 | The new code for taking advantage of inequalities in WHERE clauses is in place. It appears to work. (CVS 305) (check-in: 262bcd17df user: drh tags: trunk) | |
2001-11-07
| ||
16:48 | New Next opcode and indexing style implemented. (CVS 304) (check-in: decbeb9151 user: drh tags: trunk) | |
14:22 | Incremental update. We are in the middle of modifying the index system to support range queries without doing a complete table scan. (CVS 303) (check-in: e6ca23fa45 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.55 2001/11/07 16:48:27 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called after a single SQL statement has been ** parsed and we want to execute the VDBE code to implement |
︙ | ︙ | |||
688 689 690 691 692 693 694 | /* Generate code to remove the table from the master table ** on disk. */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOp dropTable[] = { { OP_OpenWrite, 0, 2, MASTER_NAME}, | | | | | | | 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 | /* Generate code to remove the table from the master table ** on disk. */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOp dropTable[] = { { OP_OpenWrite, 0, 2, MASTER_NAME}, { OP_Rewind, 0, ADDR(9), 0}, { OP_String, 0, 0, 0}, /* 2 */ { OP_MemStore, 1, 1, 0}, { OP_MemLoad, 1, 0, 0}, /* 4 */ { OP_Column, 0, 2, 0}, { OP_Ne, 0, ADDR(8), 0}, { OP_Delete, 0, 0, 0}, { OP_Next, 0, ADDR(4), 0}, /* 8 */ { OP_SetCookie, 0, 0, 0}, /* 9 */ { OP_Close, 0, 0, 0}, }; Index *pIdx; if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Transaction, 0, 0); sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0); |
︙ | ︙ | |||
977 978 979 980 981 982 983 | } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_Put, 0, 0); } if( pTable ){ sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); | < | < < | | < | 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 | } sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0); sqliteVdbeAddOp(v, OP_Put, 0, 0); } if( pTable ){ sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); lbl2 = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2); lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0); for(i=0; i<pIndex->nColumn; i++){ sqliteVdbeAddOp(v, OP_Column, 2, pIndex->aiColumn[i]); } sqliteVdbeAddOp(v, OP_MakeIdxKey, pIndex->nColumn, 0); sqliteVdbeAddOp(v, OP_IdxPut, 1, pIndex->isUnique); sqliteVdbeAddOp(v, OP_Next, 2, lbl1); sqliteVdbeResolveLabel(v, lbl2); sqliteVdbeAddOp(v, OP_Close, 2, 0); sqliteVdbeAddOp(v, OP_Close, 1, 0); } if( pTable!=0 ){ if( !isTemp ){ changeCookie(db); sqliteVdbeAddOp(v, OP_SetCookie, db->next_cookie, 0); |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 | } /* Generate code to remove the index and from the master table */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOp dropIndex[] = { { OP_OpenWrite, 0, 2, MASTER_NAME}, | | | | | > > | < | | | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 | } /* Generate code to remove the index and from the master table */ v = sqliteGetVdbe(pParse); if( v ){ static VdbeOp dropIndex[] = { { OP_OpenWrite, 0, 2, MASTER_NAME}, { OP_Rewind, 0, ADDR(10),0}, { OP_String, 0, 0, 0}, /* 2 */ { OP_MemStore, 1, 1, 0}, { OP_MemLoad, 1, 0, 0}, /* 4 */ { OP_Column, 0, 1, 0}, { OP_Eq, 0, ADDR(9), 0}, { OP_Next, 0, ADDR(4), 0}, { OP_Goto, 0, ADDR(10),0}, { OP_Delete, 0, 0, 0}, /* 9 */ { OP_SetCookie, 0, 0, 0}, /* 10 */ { OP_Close, 0, 0, 0}, }; int base; Table *pTab = pIndex->pTable; if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Transaction, 0, 0); sqliteVdbeAddOp(v, OP_VerifyCookie, db->schema_cookie, 0); pParse->schemaVerified = 1; } if( !pTab->isTemp ){ base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex); sqliteVdbeChangeP3(v, base+2, pIndex->zName, P3_STATIC); changeCookie(db); sqliteVdbeChangeP1(v, base+10, db->next_cookie); } sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp); if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 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.21 2001/11/07 16:48:27 drh Exp $ */ #include "sqliteInt.h" /* ** Process a DELETE FROM statement. */ void sqliteDeleteFrom( |
︙ | ︙ | |||
102 103 104 105 106 107 108 | if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqliteVdbeMakeLabel(v); int addr; openOp = pTab->isTemp ? OP_OpenAux : OP_Open; sqliteVdbeAddOp(v, openOp, 0, pTab->tnum); | | | | < | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | if( db->flags & SQLITE_CountRows ){ /* If counting rows deleted, just count the total number of ** entries in the table. */ int endOfLoop = sqliteVdbeMakeLabel(v); int addr; openOp = pTab->isTemp ? OP_OpenAux : OP_Open; sqliteVdbeAddOp(v, openOp, 0, pTab->tnum); sqliteVdbeAddOp(v, OP_Rewind, 0, sqliteVdbeCurrentAddr(v)+2); addr = sqliteVdbeAddOp(v, OP_AddImm, 1, 0); sqliteVdbeAddOp(v, OP_Next, 0, addr); sqliteVdbeResolveLabel(v, endOfLoop); sqliteVdbeAddOp(v, OP_Close, 0, 0); } sqliteVdbeAddOp(v, OP_Clear, pTab->tnum, pTab->isTemp); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqliteVdbeAddOp(v, OP_Clear, pIdx->tnum, pTab->isTemp); } |
︙ | ︙ |
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.26 2001/11/07 16:48:27 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is call to handle SQL of the following forms: ** ** insert into TABLE (IDLIST) values(EXPRLIST) |
︙ | ︙ | |||
169 170 171 172 173 174 175 | ** source is an expression list, then exactly one row will be inserted ** and the loop is not used. */ if( srcTab>=0 ){ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */ } | < > | | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | ** source is an expression list, then exactly one row will be inserted ** and the loop is not used. */ if( srcTab>=0 ){ if( db->flags & SQLITE_CountRows ){ sqliteVdbeAddOp(v, OP_Integer, 0, 0); /* Initialize the row count */ } iBreak = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, srcTab, iBreak); iCont = sqliteVdbeCurrentAddr(v); } /* Create a new entry in the table and fill it with data. */ sqliteVdbeAddOp(v, OP_NewRecno, base, 0); if( pTab->pIndex ){ sqliteVdbeAddOp(v, OP_Dup, 0, 0); |
︙ | ︙ | |||
241 242 243 244 245 246 247 | if( srcTab>=0 && (db->flags & SQLITE_CountRows)!=0 ){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } /* The bottom of the loop, if the data source is a SELECT statement */ if( srcTab>=0 ){ | | > > | > > | 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | if( srcTab>=0 && (db->flags & SQLITE_CountRows)!=0 ){ sqliteVdbeAddOp(v, OP_AddImm, 1, 0); } /* The bottom of the loop, if the data source is a SELECT statement */ if( srcTab>=0 ){ sqliteVdbeAddOp(v, OP_Next, srcTab, iCont); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, srcTab, 0); } sqliteVdbeAddOp(v, OP_Close, base, 0); for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){ sqliteVdbeAddOp(v, OP_Close, idx+base, 0); } if( (db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_Commit, 0, 0); } /* ** Return the number of rows inserted. |
︙ | ︙ |
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.49 2001/11/07 16:48:27 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. |
︙ | ︙ | |||
153 154 155 156 157 158 159 | ** table then goes back and invokes the callback on the ** SQL for each index. The callback will invoke the ** parser to build the internal representation of the ** database scheme. */ static VdbeOp initProg[] = { { OP_Open, 0, 2, 0}, | | | > > > > > > > > > | | < | | | | | < < | < < < < < < < < < | | 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 | ** table then goes back and invokes the callback on the ** SQL for each index. The callback will invoke the ** parser to build the internal representation of the ** database scheme. */ static VdbeOp initProg[] = { { OP_Open, 0, 2, 0}, { OP_Rewind, 0, 31, 0}, { OP_Column, 0, 0, 0}, /* 2 */ { OP_String, 0, 0, "meta"}, { OP_Ne, 0, 10, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Callback, 4, 0, 0}, { OP_Next, 0, 2, 0}, /* 10 */ { OP_Rewind, 0, 31, 0}, /* 11 */ { OP_Column, 0, 0, 0}, /* 12 */ { OP_String, 0, 0, "table"}, { OP_Ne, 0, 20, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Callback, 4, 0, 0}, { OP_Next, 0, 12, 0}, /* 20 */ { OP_Rewind, 0, 31, 0}, /* 21 */ { OP_Column, 0, 0, 0}, /* 22 */ { OP_String, 0, 0, "index"}, { OP_Ne, 0, 30, 0}, { OP_Column, 0, 0, 0}, { OP_Column, 0, 1, 0}, { OP_Column, 0, 3, 0}, { OP_Column, 0, 4, 0}, { OP_Callback, 4, 0, 0}, { OP_Next, 0, 22, 0}, /* 30 */ { OP_String, 0, 0, "meta"}, /* 31 */ { OP_String, 0, 0, "schema-cookie"}, { OP_String, 0, 0, 0}, { OP_ReadCookie,0,0, 0}, { OP_Callback, 4, 0, 0}, { OP_Close, 0, 0, 0}, { OP_Halt, 0, 0, 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.49 2001/11/07 16:48:27 drh Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. */ |
︙ | ︙ | |||
553 554 555 556 557 558 559 | p->pPrior = pPrior; if( rc ) return rc; /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ if( eDest!=priorOp ){ | | < | > > > | | | 553 554 555 556 557 558 559 560 561 562 563 564 565 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 | p->pPrior = pPrior; if( rc ) return rc; /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ if( eDest!=priorOp ){ int iCont, iBreak, iStart; assert( p->pEList ); generateColumnNames(pParse, 0, p->pEList); iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, unionTab, iBreak); iStart = sqliteVdbeCurrentAddr(v); rc = selectInnerLoop(pParse, 0, unionTab, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak); if( rc ) return 1; sqliteVdbeResolveLabel(v, iCont); sqliteVdbeAddOp(v, OP_Next, unionTab, iStart); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, unionTab, 0); if( p->pOrderBy ){ generateSortTail(v, p->pEList->nExpr); } } break; } case TK_INTERSECT: { int tab1, tab2; int iCont, iBreak, iStart; /* INTERSECT is different from the others since it requires ** two temporary tables. Hence it has its own case. Begin ** by allocating the tables we will need. */ tab1 = pParse->nTab++; tab2 = pParse->nTab++; |
︙ | ︙ | |||
607 608 609 610 611 612 613 | if( rc ) return rc; /* Generate code to take the intersection of the two temporary ** tables. */ assert( p->pEList ); generateColumnNames(pParse, 0, p->pEList); | < | > | > | | 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 | if( rc ) return rc; /* Generate code to take the intersection of the two temporary ** tables. */ assert( p->pEList ); generateColumnNames(pParse, 0, p->pEList); iBreak = sqliteVdbeMakeLabel(v); iCont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, tab1, iBreak); iStart = sqliteVdbeAddOp(v, OP_FullKey, tab1, 0); sqliteVdbeAddOp(v, OP_NotFound, tab2, iCont); rc = selectInnerLoop(pParse, 0, tab1, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak); if( rc ) return 1; sqliteVdbeResolveLabel(v, iCont); sqliteVdbeAddOp(v, OP_Next, tab1, iStart); sqliteVdbeResolveLabel(v, iBreak); sqliteVdbeAddOp(v, OP_Close, tab2, 0); sqliteVdbeAddOp(v, OP_Close, tab1, 0); if( p->pOrderBy ){ generateSortTail(v, p->pEList->nExpr); } break; |
︙ | ︙ |
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.68 2001/11/07 16:48:27 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 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 Select Select; typedef struct AggExpr AggExpr; /* ** Each database is an instance of the following structure */ struct sqlite { | > | 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 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; /* ** Each database is an instance of the following structure */ struct sqlite { |
︙ | ︙ | |||
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ int idx; /* Index in some Table.aCol[] of a column named zName */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ } *a; /* One entry for each identifier on the list */ }; /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ struct WhereInfo { Parse *pParse; IdList *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 base; /* Index of first Open opcode */ | > > > > > > > > > > > > > > > > | | 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 | char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ int idx; /* Index in some Table.aCol[] of a column named zName */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ } *a; /* One entry for each identifier on the list */ }; /* ** For each nested loop in a WHERE clause implementation, the WhereInfo ** structure contains a single instance of this structure. This structure ** is intended to be private the the where.c module and should not be ** access or modified by other modules. */ struct WhereLevel { int iMem; /* Memory cell used by this level */ Index *pIdx; /* Index used */ int iCur; /* Cursor number used for this index */ int brk; /* Jump here to break out of the loop */ int cont; /* Jump here to continue with the next loop cycle */ int op, p1, p2; /* Opcode used to terminate the loop */ }; /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ struct WhereInfo { Parse *pParse; IdList *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 base; /* Index of first Open opcode */ 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. */ struct Select { |
︙ | ︙ |
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.95 2001/11/07 16:48:27 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance |
︙ | ︙ | |||
60 61 62 63 64 65 66 | struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ int lastRecno; /* Last recno from a Next or NextIdx operation */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Btree *pBt; /* Separate file holding temporary table */ | < < | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | struct Cursor { BtCursor *pCursor; /* The cursor structure of the backend */ int lastRecno; /* Last recno from a Next or NextIdx operation */ Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ Btree *pBt; /* Separate file holding temporary table */ }; typedef struct Cursor Cursor; /* ** A sorter builds a list of elements to be sorted. Each element of ** the list is an instance of the following structure. */ |
︙ | ︙ | |||
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | p2 = p->aLabel[-1-p2]; } p->aOp[i].p2 = p2; p->aOp[i].p3 = 0; p->aOp[i].p3type = P3_NOTUSED; return i; } /* ** Resolve label "x" to be the address of the next instruction to ** be inserted. */ void sqliteVdbeResolveLabel(Vdbe *p, int x){ int j; if( x<0 && (-x)<=p->nLabel && p->aOp ){ p->aLabel[-1-x] = p->nOp; for(j=0; j<p->nOp; j++){ if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp; } } } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | p2 = p->aLabel[-1-p2]; } p->aOp[i].p2 = p2; p->aOp[i].p3 = 0; p->aOp[i].p3type = P3_NOTUSED; return i; } /* ** Create a new symbolic label for an instruction that has yet to be ** coded. The symbolic label is really just a negative number. The ** label can be used as the P2 value of an operation. Later, when ** the label is resolved to a specific address, the VDBE will scan ** through its operation list and change all values of P2 which match ** the label into the resolved address. ** ** The VDBE knows that a P2 value is a label because labels are ** always negative and P2 values are suppose to be non-negative. ** Hence, a negative P2 value is a label that has yet to be resolved. */ int sqliteVdbeMakeLabel(Vdbe *p){ int i; i = p->nLabel++; if( i>=p->nLabelAlloc ){ int *aNew; p->nLabelAlloc = p->nLabelAlloc*2 + 10; aNew = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0])); if( aNew==0 ){ sqliteFree(p->aLabel); } p->aLabel = aNew; } if( p->aLabel==0 ){ p->nLabel = 0; p->nLabelAlloc = 0; return 0; } p->aLabel[i] = -1; return -1-i; } /* ** Resolve label "x" to be the address of the next instruction to ** be inserted. */ void sqliteVdbeResolveLabel(Vdbe *p, int x){ int j; if( x<0 && (-x)<=p->nLabel && p->aOp ){ if( p->aLabel[-1-x]==p->nOp ) return; assert( p->aLabel[-1-x]<0 ); p->aLabel[-1-x] = p->nOp; for(j=0; j<p->nOp; j++){ if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp; } } } |
︙ | ︙ | |||
436 437 438 439 440 441 442 | } while( i>0 && isspace(z[i-1]) ){ z[i-1] = 0; i--; } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 469 470 471 472 473 474 475 476 477 478 479 480 481 482 | } while( i>0 && isspace(z[i-1]) ){ z[i-1] = 0; i--; } } /* ** 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)){ |
︙ | ︙ | |||
717 718 719 720 721 722 723 | ** Close a cursor and release all the resources that cursor happens ** to hold. */ static void cleanupCursor(Cursor *pCx){ if( pCx->pCursor ){ sqliteBtreeCloseCursor(pCx->pCursor); } | < < < | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | ** Close a cursor and release all the resources that cursor happens ** to hold. */ static void cleanupCursor(Cursor *pCx){ if( pCx->pCursor ){ sqliteBtreeCloseCursor(pCx->pCursor); } if( pCx->pBt ){ sqliteBtreeClose(pCx->pBt); } memset(pCx, 0, sizeof(Cursor)); } /* |
︙ | ︙ | |||
839 840 841 842 843 844 845 | static char *zOpName[] = { 0, "Transaction", "Commit", "Rollback", "ReadCookie", "SetCookie", "VerifyCookie", "Open", "OpenTemp", "OpenWrite", "OpenAux", "OpenWrAux", "Close", "MoveTo", "Fcnt", "NewRecno", "Put", "Distinct", "Found", "NotFound", "Delete", "Column", "KeyAsData", "Recno", "FullKey", | | | < | | | | | | | | | | | | | | | | | | | | | 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 867 868 869 870 871 | static char *zOpName[] = { 0, "Transaction", "Commit", "Rollback", "ReadCookie", "SetCookie", "VerifyCookie", "Open", "OpenTemp", "OpenWrite", "OpenAux", "OpenWrAux", "Close", "MoveTo", "Fcnt", "NewRecno", "Put", "Distinct", "Found", "NotFound", "Delete", "Column", "KeyAsData", "Recno", "FullKey", "Rewind", "Next", "Destroy", "Clear", "CreateIndex", "CreateTable", "Reorganize", "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", "SetInsert", "SetFound", "SetNotFound", "MakeRecord", "MakeKey", "MakeIdxKey", "IncrKey", "Goto", "If", "Halt", "ColumnCount", "ColumnName", "Callback", "NullCallback", "Integer", "String", "Pop", "Dup", "Pull", "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", "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. |
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 | ** ** Allocation all the stack space we will ever need. */ NeedStack(p, p->nOp); zStack = p->zStack; aStack = p->aStack; p->tos = -1; /* Initialize the aggregrate hash table. */ sqliteHashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0); p->agg.pSearch = 0; rc = SQLITE_OK; | > > | 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 | ** ** Allocation all the stack space we will ever need. */ NeedStack(p, p->nOp); zStack = p->zStack; aStack = p->aStack; p->tos = -1; p->iLimit = 0; p->iOffset = 0; /* Initialize the aggregrate hash table. */ sqliteHashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0); p->agg.pSearch = 0; rc = SQLITE_OK; |
︙ | ︙ | |||
2924 2925 2926 2927 2928 2929 2930 | } } break; } /* Opcode: Next P1 P2 * ** | < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 | } } break; } /* Opcode: Next P1 P2 * ** ** Advance cursor P1 so that it points to the next key/data pair in its ** table or index. If there are no more key/value pairs then fall through ** to the following instruction. But if the cursor advance was successful, ** jump immediately to P2. */ case OP_Next: { int i = pOp->p1; BtCursor *pCrsr; if( VERIFY( i>=0 && i<p->nCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res; rc = sqliteBtreeNext(pCrsr, &res); if( res==0 ){ pc = pOp->p2 - 1; p->nFetch++; } p->aCsr[i].recnoIsValid = 0; } break; } /* Opcode: IdxPut P1 P2 P3 ** ** The top of the stack hold an SQL index key made using the ** MakeIdxKey instruction. This opcode writes that key into the |
︙ | ︙ | |||
3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 | if( pOp->opcode==OP_IdxGE ){ res++; } if( res>0 ){ pc = pOp->p2 - 1 ; } } break; } /* Opcode: Destroy P1 P2 * ** ** Delete an entire database table or index whose root page in the database ** file is given by P1. | > | 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 | if( pOp->opcode==OP_IdxGE ){ res++; } if( res>0 ){ pc = pOp->p2 - 1 ; } } POPSTACK; break; } /* Opcode: Destroy P1 P2 * ** ** Delete an entire database table or index whose root page in the database ** file is given by P1. |
︙ | ︙ | |||
3776 3777 3778 3779 3780 3781 3782 | }else{ zOld = 0; } pMem->s = aStack[tos]; if( pMem->s.flags & (STK_Static|STK_Dyn) ){ if( pOp->p2==0 && (pMem->s.flags & STK_Dyn)!=0 ){ pMem->z = sqliteMalloc( pMem->s.n ); | | | 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 | }else{ zOld = 0; } pMem->s = aStack[tos]; if( pMem->s.flags & (STK_Static|STK_Dyn) ){ if( pOp->p2==0 && (pMem->s.flags & STK_Dyn)!=0 ){ pMem->z = sqliteMalloc( pMem->s.n ); if( pMem->z==0 ) goto no_mem; memcpy(pMem->z, zStack[tos], pMem->s.n); }else{ pMem->z = zStack[tos]; } }else{ pMem->z = pMem->s.z; } |
︙ | ︙ |
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.35 2001/11/07 16:48:28 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ #include <stdio.h> /* ** A single VDBE is an opaque structure named "Vdbe". Only routines |
︙ | ︙ | |||
92 93 94 95 96 97 98 | #define OP_Delete 20 #define OP_Column 21 #define OP_KeyAsData 22 #define OP_Recno 23 #define OP_FullKey 24 #define OP_Rewind 25 #define OP_Next 26 | < | | | | | < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 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 | #define OP_Delete 20 #define OP_Column 21 #define OP_KeyAsData 22 #define OP_Recno 23 #define OP_FullKey 24 #define OP_Rewind 25 #define OP_Next 26 #define OP_Destroy 27 #define OP_Clear 28 #define OP_CreateIndex 29 #define OP_CreateTable 30 #define OP_Reorganize 31 #define OP_IdxPut 32 #define OP_IdxDelete 33 #define OP_IdxRecno 34 #define OP_IdxGT 35 #define OP_IdxGE 36 #define OP_MemLoad 37 #define OP_MemStore 38 #define OP_ListWrite 39 #define OP_ListRewind 40 #define OP_ListRead 41 #define OP_ListReset 42 #define OP_SortPut 43 #define OP_SortMakeRec 44 #define OP_SortMakeKey 45 #define OP_Sort 46 #define OP_SortNext 47 #define OP_SortCallback 48 #define OP_SortReset 49 #define OP_FileOpen 50 #define OP_FileRead 51 #define OP_FileColumn 52 #define OP_AggReset 53 #define OP_AggFocus 54 #define OP_AggIncr 55 #define OP_AggNext 56 #define OP_AggSet 57 #define OP_AggGet 58 #define OP_SetInsert 59 #define OP_SetFound 60 #define OP_SetNotFound 61 #define OP_MakeRecord 62 #define OP_MakeKey 63 #define OP_MakeIdxKey 64 #define OP_IncrKey 65 #define OP_Goto 66 #define OP_If 67 #define OP_Halt 68 #define OP_ColumnCount 69 #define OP_ColumnName 70 #define OP_Callback 71 #define OP_NullCallback 72 #define OP_Integer 73 #define OP_String 74 #define OP_Pop 75 #define OP_Dup 76 #define OP_Pull 77 #define OP_Add 78 #define OP_AddImm 79 #define OP_Subtract 80 #define OP_Multiply 81 #define OP_Divide 82 #define OP_Remainder 83 #define OP_BitAnd 84 #define OP_BitOr 85 #define OP_BitNot 86 #define OP_ShiftLeft 87 #define OP_ShiftRight 88 #define OP_AbsValue 89 #define OP_Precision 90 #define OP_Min 91 #define OP_Max 92 #define OP_Like 93 #define OP_Glob 94 #define OP_Eq 95 #define OP_Ne 96 #define OP_Lt 97 #define OP_Le 98 #define OP_Gt 99 #define OP_Ge 100 #define OP_IsNull 101 #define OP_NotNull 102 #define OP_Negative 103 #define OP_And 104 #define OP_Or 105 #define OP_Not 106 #define OP_Concat 107 #define OP_Noop 108 #define OP_Strlen 109 #define OP_Substr 110 #define OP_Limit 111 #define OP_MAX 111 /* ** 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*); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** 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. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** 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. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** ** $Id: where.c,v 1.25 2001/11/07 16:48:28 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. |
︙ | ︙ | |||
143 144 145 146 147 148 149 | Vdbe *v = pParse->pVdbe; /* The virtual database engine */ int brk, cont; /* Addresses used during code generation */ int *aOrder; /* Order in which pTabList entries are searched */ int nExpr; /* Number of subexpressions in the WHERE clause */ int loopMask; /* One bit set for each outer loop */ int haveKey; /* True if KEY is on the stack */ int base; /* First available index for OP_Open opcodes */ | | | | > | 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 | Vdbe *v = pParse->pVdbe; /* The virtual database engine */ int brk, cont; /* Addresses used during code generation */ int *aOrder; /* Order in which pTabList entries are searched */ int nExpr; /* Number of subexpressions in the WHERE clause */ int loopMask; /* One bit set for each outer loop */ int haveKey; /* True if KEY is on the stack */ int base; /* First available index for OP_Open opcodes */ int nCur; /* Next unused cursor number */ int aDirect[32]; /* If TRUE, then index this table using ROWID */ ExprInfo aExpr[50]; /* The WHERE clause is divided into these expressions */ /* Allocate space for aOrder[] and aiMem[]. */ aOrder = sqliteMalloc( sizeof(int) * pTabList->nId ); /* Allocate and initialize the WhereInfo structure that will become the ** return value. */ pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nId*sizeof(WhereLevel) ); if( sqlite_malloc_failed ){ sqliteFree(aOrder); sqliteFree(pWInfo); return 0; } pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; base = pWInfo->base = pParse->nTab; nCur = base + pTabList->nId; /* Split the WHERE clause into as many as 32 separate subexpressions ** where each subexpression is separated by an AND operator. Any additional ** subexpressions are attached in the aExpr[32] and will not enter ** into the query optimizer computations. 32 is chosen as the cutoff ** since that is the number of bits in an integer that we use for an ** expression-used mask. |
︙ | ︙ | |||
193 194 195 196 197 198 199 | ** tables appear in in the pTabList. */ for(i=0; i<pTabList->nId; i++){ aOrder[i] = i; } /* Figure out what index to use (if any) for each nested loop. | | | | | 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 | ** tables appear in in the pTabList. */ for(i=0; i<pTabList->nId; i++){ aOrder[i] = i; } /* Figure out what index to use (if any) for each nested loop. ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested ** loop where i==0 is the outer loop and i==pTabList->nId-1 is the inner ** loop. If the expression uses only the ROWID field, then set ** aDirect[i] to 1. ** ** Actually, if there are more than 32 tables in the join, only the ** first 32 tables are candidates for indices. */ loopMask = 0; for(i=0; i<pTabList->nId && i<ARRAYSIZE(aDirect); i++){ int j; int idx = aOrder[i]; Table *pTab = pTabList->a[idx].pTab; Index *pIdx; Index *pBestIdx = 0; /* Check to see if there is an expression that uses only the |
︙ | ︙ | |||
228 229 230 231 232 233 234 | && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){ aDirect[i] = 1; break; } } if( aDirect[i] ){ loopMask |= 1<<idx; | | | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | && (aExpr[j].prereqLeft & loopMask)==aExpr[j].prereqLeft ){ aDirect[i] = 1; break; } } if( aDirect[i] ){ loopMask |= 1<<idx; pWInfo->a[i].pIdx = 0; continue; } /* Do a search for usable indices. Leave pBestIdx pointing to ** the most specific usable index. ** ** "Most specific" means that pBestIdx is the usable index that |
︙ | ︙ | |||
274 275 276 277 278 279 280 | } if( columnMask + 1 == (1<<pIdx->nColumn) ){ if( pBestIdx==0 || pBestIdx->nColumn<pIdx->nColumn ){ pBestIdx = pIdx; } } } | | > > | | > | | | | < < > > | | | 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 | } if( columnMask + 1 == (1<<pIdx->nColumn) ){ if( pBestIdx==0 || pBestIdx->nColumn<pIdx->nColumn ){ pBestIdx = pIdx; } } } pWInfo->a[i].pIdx = pBestIdx; loopMask |= 1<<idx; if( pBestIdx ){ pWInfo->a[i].iCur = nCur++; } } /* Open all tables in the pTabList and all indices used by those tables. */ for(i=0; i<pTabList->nId; i++){ int openOp; Table *pTab; pTab = pTabList->a[i].pTab; openOp = pTab->isTemp ? OP_OpenAux : OP_Open; sqliteVdbeAddOp(v, openOp, base+i, pTab->tnum); sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); if( i==0 && !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){ sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0); pParse->schemaVerified = 1; } if( pWInfo->a[i].pIdx!=0 ){ sqliteVdbeAddOp(v, openOp, pWInfo->a[i].iCur, pWInfo->a[i].pIdx->tnum); sqliteVdbeChangeP3(v, -1, pWInfo->a[i].pIdx->zName, P3_STATIC); } } /* Generate the code to do the search */ loopMask = 0; pWInfo->iBreak = sqliteVdbeMakeLabel(v); for(i=0; i<pTabList->nId; i++){ int j, k; int idx = aOrder[i]; int goDirect; Index *pIdx; WhereLevel *pLevel = &pWInfo->a[i]; if( i<ARRAYSIZE(aDirect) ){ pIdx = pLevel->pIdx; goDirect = aDirect[i]; }else{ pIdx = 0; goDirect = 0; } if( goDirect ){ |
︙ | ︙ | |||
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | ){ sqliteExprCode(pParse, aExpr[k].p->pLeft); aExpr[k].p = 0; break; } } sqliteVdbeAddOp(v, OP_AddImm, 0, 0); if( i==pTabList->nId-1 && pushKey ){ haveKey = 1; }else{ sqliteVdbeAddOp(v, OP_NotFound, base+idx, brk); haveKey = 0; } }else if( pIdx==0 ){ /* Case 2: There was no usable index. We must do a complete ** scan of the table. */ | > > > > | | | | > > > > | | 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 379 380 381 382 383 384 385 386 | ){ sqliteExprCode(pParse, aExpr[k].p->pLeft); aExpr[k].p = 0; break; } } sqliteVdbeAddOp(v, OP_AddImm, 0, 0); brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = brk; if( i==pTabList->nId-1 && pushKey ){ haveKey = 1; }else{ sqliteVdbeAddOp(v, OP_NotFound, base+idx, brk); haveKey = 0; } pLevel->op = OP_Noop; }else if( pIdx==0 ){ /* Case 2: There was no usable index. We must do a complete ** scan of the table. */ int start; brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_Rewind, base+idx, brk); start = sqliteVdbeCurrentAddr(v); pLevel->op = OP_Next; pLevel->p1 = base+idx; pLevel->p2 = start; haveKey = 0; }else{ /* Case 3: We do have a usable index in pIdx. */ int start; for(j=0; j<pIdx->nColumn; j++){ for(k=0; k<nExpr; k++){ if( aExpr[k].p==0 ) continue; if( aExpr[k].idxLeft==idx && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j] ){ |
︙ | ︙ | |||
382 383 384 385 386 387 388 389 | ){ sqliteExprCode(pParse, aExpr[k].p->pLeft); aExpr[k].p = 0; break; } } } sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nColumn, 0); | > > > | | > | > > > > | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | ){ sqliteExprCode(pParse, aExpr[k].p->pLeft); aExpr[k].p = 0; break; } } } pLevel->iMem = pParse->nMem++; brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = sqliteVdbeMakeLabel(v); sqliteVdbeAddOp(v, OP_MakeKey, pIdx->nColumn, 0); sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0); sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk); start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqliteVdbeAddOp(v, OP_IdxGT, pLevel->iCur, brk); sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0); if( i==pTabList->nId-1 && pushKey ){ haveKey = 1; }else{ sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); haveKey = 0; } pLevel->op = OP_Next; pLevel->p1 = pLevel->iCur; pLevel->p2 = start; } loopMask |= 1<<idx; /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(j=0; j<nExpr; j++){ |
︙ | ︙ | |||
425 426 427 428 429 430 431 | /* ** Generate the end of the WHERE loop. */ void sqliteWhereEnd(WhereInfo *pWInfo){ Vdbe *v = pWInfo->pParse->pVdbe; int i; | < > < | > | < < | | > < | > > | > > | > | 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 471 472 473 | /* ** Generate the end of the WHERE loop. */ void sqliteWhereEnd(WhereInfo *pWInfo){ Vdbe *v = pWInfo->pParse->pVdbe; int i; int base = pWInfo->base; WhereLevel *pLevel; for(i=pWInfo->pTabList->nId-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqliteVdbeResolveLabel(v, pLevel->cont); if( pLevel->op!=OP_Noop ){ sqliteVdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2); } sqliteVdbeResolveLabel(v, pLevel->brk); } sqliteVdbeResolveLabel(v, pWInfo->iBreak); for(i=0; i<pWInfo->pTabList->nId; i++){ pLevel = &pWInfo->a[i]; sqliteVdbeAddOp(v, OP_Close, base+i, 0); if( pLevel->pIdx!=0 ){ sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0); } } sqliteFree(pWInfo); return; } |