Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix many problems with manifest types and column affinity. Most things are working now. (CVS 1392) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
a62872aacd544a1465b06e0071531686 |
User & Date: | danielk1977 2004-05-18 09:58:07.000 |
Context
2004-05-18
| ||
10:06 | Fix many problems with manifest types and column affinity. Most things are working now. (CVS 1393) (check-in: ad4a964158 user: danielk1977 tags: trunk) | |
09:58 | Fix many problems with manifest types and column affinity. Most things are working now. (CVS 1392) (check-in: a62872aacd user: danielk1977 tags: trunk) | |
01:31 | Bugfix for row format. (CVS 1391) (check-in: c1745f47ae user: danielk1977 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.187 2004/05/18 09:58:07 danielk1977 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 |
︙ | ︙ | |||
786 787 788 789 790 791 792 | {"CHAR", 4, SQLITE_AFF_TEXT}, {"CLOB", 4, SQLITE_AFF_TEXT}, {"TEXT", 4, SQLITE_AFF_TEXT} }; for(n=0; n<(nType-2); n++){ for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){ | | | 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 | {"CHAR", 4, SQLITE_AFF_TEXT}, {"CLOB", 4, SQLITE_AFF_TEXT}, {"TEXT", 4, SQLITE_AFF_TEXT} }; for(n=0; n<(nType-2); n++){ for(i=0; i<sizeof(substrings)/sizeof(substrings[0]); i++){ if( 0==sqlite3StrNICmp(&zType[n], substrings[i].zSub, substrings[i].nSub) ){ return substrings[i].affinity; } } } return SQLITE_AFF_NONE; } |
︙ | ︙ | |||
988 989 990 991 992 993 994 | sqlite3VdbeChangeP3(v, -1, z, n); sqliteFree(z); }else{ assert( pEnd!=0 ); n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1; sqlite3VdbeChangeP3(v, -1, pParse->sFirstToken.z, n); } | | | | 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 | sqlite3VdbeChangeP3(v, -1, z, n); sqliteFree(z); }else{ assert( pEnd!=0 ); n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1; sqlite3VdbeChangeP3(v, -1, pParse->sFirstToken.z, n); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( !p->iDb ){ sqlite3ChangeCookie(db, v); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( pSelect ){ sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0); } sqlite3EndWriteOperation(pParse); } /* Add the table to the in-memory representation of the database. */ if( pParse->explain==0 && pParse->nErr==0 ){ |
︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 | 0); } addr = sqlite3VdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ n = Addr(pEnd->z) - Addr(pStart->z) + 1; sqlite3VdbeChangeP3(v, addr, pStart->z, n); } | | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 | 0); } addr = sqlite3VdbeAddOp(v, OP_String, 0, 0); if( pStart && pEnd ){ n = Addr(pEnd->z) - Addr(pStart->z) + 1; sqlite3VdbeChangeP3(v, addr, pStart->z, n); } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); if( pTable ){ sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0); sqlite3VdbeOp3(v, OP_OpenRead, 2, pTab->tnum, pTab->zName, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol); lbl2 = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2); |
︙ | ︙ |
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.67 2004/05/18 09:58:07 danielk1977 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. |
︙ | ︙ | |||
145 146 147 148 149 150 151 | sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView = sqlite3SelectDup(pTab->pSelect); | | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView = sqlite3SelectDup(pTab->pSelect); sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Initialize the counter of the number of rows deleted, if ** we are counting rows. */ if( db->flags & SQLITE_CountRows ){ |
︙ | ︙ | |||
209 210 211 212 213 214 215 216 217 218 219 220 221 222 | */ sqlite3WhereEnd(pWInfo); /* Open the pseudo-table used to store OLD if there are triggers. */ if( row_triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); } /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); | > | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | */ sqlite3WhereEnd(pWInfo); /* Open the pseudo-table used to store OLD if there are triggers. */ if( row_triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); } /* Delete every item whose key was written to the list during the ** database scan. We have to delete items after the scan is complete ** because deleting an item can change the scan order. */ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); |
︙ | ︙ |
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.102 2004/05/18 09:58:07 danielk1977 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: |
︙ | ︙ | |||
256 257 258 259 260 261 262 | if( pSelect ){ /* Data is coming from a SELECT. Generate code to implement that SELECT */ int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); | | | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | if( pSelect ){ /* Data is coming from a SELECT. Generate code to implement that SELECT */ int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock, 0,0,0,0); if( rc || pParse->nErr || sqlite3_malloc_failed ) goto insert_cleanup; iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; /* Set useTempTable to TRUE if the result of the SELECT statement ** should be written into a temporary table. Set to FALSE if each ** row of the SELECT can be written directly into the result table. ** ** A temp table must be used if the table being updated is also one ** of the tables being read by the SELECT statement. Also use a ** temp table in the case of row triggers. */ if( row_triggers_exist ){ useTempTable = 1; }else{ int addr = sqlite3VdbeFindOp(v, 0, OP_OpenRead, pTab->tnum); useTempTable = 0; if( addr>0 ){ VdbeOp *pOp = sqlite3VdbeGetOp(v, addr-2); if( pOp->opcode==OP_Integer && pOp->p1==pTab->iDb ){ useTempTable = 1; } } |
︙ | ︙ | |||
394 395 396 397 398 399 400 401 402 403 404 405 406 407 | keyColumn = pTab->iPKey; } /* Open the temp table for FOR EACH ROW triggers */ if( row_triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ iCntMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Integer, 0, 0); | > | 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | keyColumn = pTab->iPKey; } /* Open the temp table for FOR EACH ROW triggers */ if( row_triggers_exist ){ sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted */ if( db->flags & SQLITE_CountRows ){ iCntMem = pParse->nMem++; sqlite3VdbeAddOp(v, OP_Integer, 0, 0); |
︙ | ︙ |
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.25 2004/05/18 09:58:08 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Interpret the given string as a boolean value. */ |
︙ | ︙ | |||
618 619 620 621 622 623 624 | for(i=0; i<db->nDb; i++){ HashElem *x; /* Do an integrity check of the B-Tree */ addr = sqlite3VdbeAddOpList(v, ArraySize(checkDb), checkDb); sqlite3VdbeChangeP1(v, addr+1, i); | | | | | | | 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 | for(i=0; i<db->nDb; i++){ HashElem *x; /* Do an integrity check of the B-Tree */ addr = sqlite3VdbeAddOpList(v, ArraySize(checkDb), checkDb); sqlite3VdbeChangeP1(v, addr+1, i); sqlite3VdbeChangeP2(v, addr+4, addr+8); sqlite3VdbeChangeP2(v, addr+7, addr+5); sqlite3VdbeChangeP2(v, addr+8, i); sqlite3VdbeChangeP2(v, addr+11, addr+ArraySize(checkDb)); sqlite3VdbeChangeP3(v, addr+14, db->aDb[i].zName, P3_STATIC); /* Make sure all the indices are constructed correctly. */ sqlite3CodeVerifySchema(pParse, i); for(x=sqliteHashFirst(&db->aDb[i].tblHash); x; x=sqliteHashNext(x)){ Table *pTab = sqliteHashData(x); Index *pIdx; |
︙ | ︙ |
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.167 2004/05/18 09:58:08 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Allocate a new Select structure and return a pointer to that ** structure. |
︙ | ︙ | |||
378 379 380 381 382 383 384 | int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ ExprList *pOrderBy, /* If not NULL, sort results using this key */ int distinct, /* If >=0, make sure results are distinct */ int eDest, /* How to dispose of the results */ int iParm, /* An argument to the disposal method */ int iContinue, /* Jump here to continue with next row */ | | > | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 | int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ ExprList *pOrderBy, /* If not NULL, sort results using this key */ int distinct, /* If >=0, make sure results are distinct */ int eDest, /* How to dispose of the results */ int iParm, /* An argument to the disposal method */ int iContinue, /* Jump here to continue with next row */ int iBreak, /* Jump here to break out of the inner loop */ char *aff /* affinity string if eDest is SRT_Union */ ){ Vdbe *v = pParse->pVdbe; int i; if( v==0 ) return 0; assert( pEList!=0 ); |
︙ | ︙ | |||
436 437 438 439 440 441 442 443 444 445 446 447 448 449 | switch( eDest ){ /* In this mode, write each query result to the key of the temporary ** table iParm. */ case SRT_Union: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0); break; } /* Store the result as data using a unique key. */ | > | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | switch( eDest ){ /* In this mode, write each query result to the key of the temporary ** table iParm. */ case SRT_Union: { sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, iParm, 0); break; } /* Store the result as data using a unique key. */ |
︙ | ︙ | |||
463 464 465 466 467 468 469 470 471 472 473 474 475 476 | /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ case SRT_Except: { int addr; addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); break; } /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this | > | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ case SRT_Except: { int addr; addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3); sqlite3VdbeAddOp(v, OP_Delete, iParm, 0); break; } /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this |
︙ | ︙ | |||
487 488 489 490 491 492 493 | if( pOrderBy ){ pushOntoSorter(pParse, v, pOrderBy); }else{ char const *affStr; char aff = (iParm>>16)&0xFF; aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); affStr = sqlite3AffinityString(aff); | | | 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | if( pOrderBy ){ pushOntoSorter(pParse, v, pOrderBy); }else{ char const *affStr; char aff = (iParm>>16)&0xFF; aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff); affStr = sqlite3AffinityString(aff); sqlite3VdbeOp3(v, OP_MakeKey, 1, 0, affStr, P3_STATIC); sqlite3VdbeAddOp(v, OP_String, 0, 0); sqlite3VdbeAddOp(v, OP_PutStrKey, (iParm&0x0000FFFF), 0); } sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v)); break; } |
︙ | ︙ | |||
608 609 610 611 612 613 614 615 616 617 618 | assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); sqlite3VdbeAddOp(v, OP_Goto, 0, end1); break; } case SRT_Subroutine: { int i; for(i=0; i<nColumn; i++){ sqlite3VdbeAddOp(v, OP_Column, -1-i, i); } sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); | > > | | 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 | assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); sqlite3VdbeAddOp(v, OP_Goto, 0, end1); break; } case SRT_Subroutine: { int i; sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); for(i=0; i<nColumn; i++){ sqlite3VdbeAddOp(v, OP_Column, -1-i, i); } sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm); sqlite3VdbeAddOp(v, OP_Pop, 2, 0); break; } default: { /* Do nothing */ break; } } |
︙ | ︙ | |||
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 | if( pE->dataType==SQLITE_SO_NUM ) continue; assert( pE->iColumn>=0 ); if( pEList->nExpr>pE->iColumn ){ pE->dataType = sqlite3ExprType(pEList->a[pE->iColumn].pExpr); } } } /* ** 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 | > > > > > > > > > > > > > | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 | if( pE->dataType==SQLITE_SO_NUM ) continue; assert( pE->iColumn>=0 ); if( pEList->nExpr>pE->iColumn ){ pE->dataType = sqlite3ExprType(pEList->a[pE->iColumn].pExpr); } } } static void multiSelectAffinity(Select *p, char *zAff){ int i; if( !p ) return; multiSelectAffinity(p->pPrior, zAff); for(i=0; i<p->pEList->nExpr; i++){ if( zAff[i]=='\0' ){ zAff[i] = sqlite3ExprAffinity(p->pEList->a[i].pExpr); } } } /* ** 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 |
︙ | ︙ | |||
1280 1281 1282 1283 1284 1285 1286 | ** The arrows in the diagram above represent the Select.pPrior pointer. ** So if this routine is called with p equal to the t3 query, then ** pPrior will be the t2 query. p->op will be TK_UNION in this case. ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ | | > > > > > > | > > > > > > > > > > > > > > > > > | > > > | > | > | > > > | | > > | | > > | 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 | ** The arrows in the diagram above represent the Select.pPrior pointer. ** So if this routine is called with p equal to the t3 query, then ** pPrior will be the t2 query. p->op will be TK_UNION in this case. ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ static int multiSelect( Parse *pParse, Select *p, int eDest, int iParm, char *aff /* If eDest is SRT_Union, the affinity string */ ){ int rc = SQLITE_OK; /* Success code from a subroutine */ Select *pPrior; /* Another SELECT immediately to our left */ Vdbe *v; /* Generate code to this VDBE */ char *affStr = 0; if( !aff ){ int len; rc = fillInColumnList(pParse, p); if( rc!=SQLITE_OK ){ goto multi_select_end; } len = p->pEList->nExpr+1; affStr = (char *)sqliteMalloc(p->pEList->nExpr+1); if( !affStr ){ rc = SQLITE_NOMEM; goto multi_select_end; } memset(affStr, (int)SQLITE_AFF_NUMERIC, len-1); aff = affStr; } /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last SELECT in the series may have an ORDER BY or LIMIT. */ if( p==0 || p->pPrior==0 ){ rc = 1; goto multi_select_end; } pPrior = p->pPrior; if( pPrior->pOrderBy ){ sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before", selectOpName(p->op)); rc = 1; goto multi_select_end; } if( pPrior->nLimit>=0 || pPrior->nOffset>0 ){ sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before", selectOpName(p->op)); rc = 1; goto multi_select_end; } /* Make sure we have a valid query engine. If not, create a new one. */ v = sqlite3GetVdbe(pParse); if( v==0 ){ rc = 1; goto multi_select_end; } /* Create the destination temporary table if necessary */ if( eDest==SRT_TempTable ){ assert( p->pEList ); sqlite3VdbeAddOp(v, OP_OpenTemp, iParm, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, p->pEList->nExpr); eDest = SRT_Table; } /* Generate code for the left and right SELECT statements. */ switch( p->op ){ case TK_ALL: { if( p->pOrderBy==0 ){ pPrior->nLimit = p->nLimit; pPrior->nOffset = p->nOffset; rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; p->nLimit = -1; p->nOffset = 0; rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff); p->pPrior = pPrior; if( rc ){ goto multi_select_end; } break; } /* For UNION ALL ... ORDER BY fall through to the next case */ } case TK_EXCEPT: case TK_UNION: { int unionTab; /* Cursor number of the temporary table holding result */ |
︙ | ︙ | |||
1357 1358 1359 1360 1361 1362 1363 | }else{ /* We will need to create our own temporary table to hold the ** intermediate results. */ unionTab = pParse->nTab++; if( p->pOrderBy && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){ | | > > | | > > > > > | | > > > | | > > > | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 | }else{ /* We will need to create our own temporary table to hold the ** intermediate results. */ unionTab = pParse->nTab++; if( p->pOrderBy && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){ rc = 1; goto multi_select_end; } if( p->op!=TK_ALL ){ sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 1); sqlite3VdbeAddOp(v, OP_KeyAsData, unionTab, 1); }else{ sqlite3VdbeAddOp(v, OP_OpenTemp, unionTab, 0); } assert( p->pEList ); } /* Code the SELECT statements to our left */ rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } if( p->op==TK_ALL ){ sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, pPrior->pEList->nExpr); } /* Code the current SELECT statement */ switch( p->op ){ case TK_EXCEPT: op = SRT_Except; break; case TK_UNION: op = SRT_Union; break; case TK_ALL: op = SRT_Table; break; } p->pPrior = 0; pOrderBy = p->pOrderBy; p->pOrderBy = 0; nLimit = p->nLimit; p->nLimit = -1; nOffset = p->nOffset; p->nOffset = 0; rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff); p->pPrior = pPrior; p->pOrderBy = pOrderBy; p->nLimit = nLimit; p->nOffset = nOffset; if( rc ){ goto multi_select_end; } /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ if( eDest!=priorOp || unionTab!=iParm ){ int iCont, iBreak, iStart; assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); generateColumnTypes(pParse, p->pSrc, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); computeLimitRegisters(pParse, p); iStart = sqlite3VdbeCurrentAddr(v); multiSelectSortOrder(p, p->pOrderBy); rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak, 0); if( rc ){ rc = 1; goto multi_select_end; } sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp(v, OP_Close, unionTab, 0); if( p->pOrderBy ){ generateSortTail(p, v, p->pEList->nExpr, eDest, iParm); } |
︙ | ︙ | |||
1435 1436 1437 1438 1439 1440 1441 | /* 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++; if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){ | | > > | | > > | | > > | | > > > | > > > > > > > > > > > | | 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 | /* 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++; if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){ rc = 1; goto multi_select_end; } sqlite3VdbeAddOp(v, OP_OpenTemp, tab1, 1); sqlite3VdbeAddOp(v, OP_KeyAsData, tab1, 1); assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT into temporary table "tab2" */ sqlite3VdbeAddOp(v, OP_OpenTemp, tab2, 1); sqlite3VdbeAddOp(v, OP_KeyAsData, tab2, 1); p->pPrior = 0; nLimit = p->nLimit; p->nLimit = -1; nOffset = p->nOffset; p->nOffset = 0; rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff); p->pPrior = pPrior; p->nLimit = nLimit; p->nOffset = nOffset; if( rc ){ goto multi_select_end; } /* Generate code to take the intersection of the two temporary ** tables. */ assert( p->pEList ); if( eDest==SRT_Callback ){ generateColumnNames(pParse, 0, p->pEList); generateColumnTypes(pParse, p->pSrc, p->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); computeLimitRegisters(pParse, p); iStart = sqlite3VdbeAddOp(v, OP_FullKey, tab1, 0); sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); multiSelectSortOrder(p, p->pOrderBy); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, p->pOrderBy, -1, eDest, iParm, iCont, iBreak, 0); if( rc ){ rc = 1; goto multi_select_end; } sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp(v, OP_Next, tab1, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp(v, OP_Close, tab2, 0); sqlite3VdbeAddOp(v, OP_Close, tab1, 0); if( p->pOrderBy ){ generateSortTail(p, v, p->pEList->nExpr, eDest, iParm); } break; } } assert( p->pEList && pPrior->pEList ); if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" " do not have the same number of result columns", selectOpName(p->op)); rc = 1; goto multi_select_end; } multi_select_end: if( affStr ){ if( rc!=SQLITE_OK ){ sqliteFree(affStr); }else{ multiSelectAffinity(p, affStr); sqlite3VdbeOp3(v, OP_Noop, 0, 0, affStr, P3_DYNAMIC); } } return rc; } /* ** Scan through the expression pExpr. Replace every reference to ** a column in table number iTable with a copy of the iColumn-th ** entry in pEList. (But leave references to the ROWID column ** unchanged.) |
︙ | ︙ | |||
1933 1934 1935 1936 1937 1938 1939 | sqlite3VdbeAddOp(v, OP_Close, base+1, 0); sqlite3VdbeAddOp(v, OP_MoveTo, base, 0); } eList.nExpr = 1; memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; | | | 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 | sqlite3VdbeAddOp(v, OP_Close, base+1, 0); sqlite3VdbeAddOp(v, OP_MoveTo, base, 0); } eList.nExpr = 1; memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; 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; } /* |
︙ | ︙ | |||
1999 2000 2001 2002 2003 2004 2005 | int sqlite3Select( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ | | > | 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 | int sqlite3Select( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ int eDest, /* How to dispose of the results */ int iParm, /* A parameter used by the eDest disposal method */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ int *pParentAgg, /* True if pParent uses aggregate functions */ char *aff /* If eDest is SRT_Union, the affinity string */ ){ int i; WhereInfo *pWInfo; Vdbe *v; int isAgg = 0; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ SrcList *pTabList; /* List of tables to select from */ |
︙ | ︙ | |||
2021 2022 2023 2024 2025 2026 2027 | if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ | | | 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 | if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ return multiSelect(pParse, p, eDest, iParm, aff); } /* Make local copies of the parameters for this query. */ pTabList = p->pSrc; pWhere = p->pWhere; pOrderBy = p->pOrderBy; |
︙ | ︙ | |||
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 | /* Identify column names if we will be using them in a callback. This ** step is skipped if the output is going to some other destination. */ if( eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } /* Generate code for all sub-queries in the FROM clause */ for(i=0; i<pTabList->nSrc; i++){ const char *zSavedAuthContext; int needRestoreContext; if( pTabList->a[i].pSelect==0 ) continue; if( pTabList->a[i].zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pTabList->a[i].zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable, | > > > > > > > > > > > > > > > | | 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 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 | /* Identify column names if we will be using them in a callback. This ** step is skipped if the output is going to some other destination. */ if( eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } /* If the destination is SRT_Union, then set the number of columns in ** the records that will be inserted into the temporary table. The caller ** couldn't do this, in case the select statement is of the form ** "SELECT * FROM ....". ** ** We need to do this before we start inserting records into the ** temporary table (which has had OP_KeyAsData executed on it), because ** it is required by the key comparison function. So do it now, even ** though this means that OP_SetNumColumns may be executed on the same ** cursor more than once. */ if( eDest==SRT_Union ){ sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); } /* Generate code for all sub-queries in the FROM clause */ for(i=0; i<pTabList->nSrc; i++){ const char *zSavedAuthContext; int needRestoreContext; if( pTabList->a[i].pSelect==0 ) continue; if( pTabList->a[i].zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pTabList->a[i].zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable, pTabList->a[i].iCursor, p, i, &isAgg, 0); if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; } pTabList = p->pSrc; pWhere = p->pWhere; if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){ pOrderBy = p->pOrderBy; |
︙ | ︙ | |||
2320 2321 2322 2323 2324 2325 2326 | if( pWInfo==0 ) goto select_end; /* Use the standard inner loop if we are not dealing with ** aggregates */ if( !isAgg ){ if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, | | | 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 | if( pWInfo==0 ) goto select_end; /* Use the standard inner loop if we are not dealing with ** aggregates */ if( !isAgg ){ if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){ goto select_end; } } /* If we are dealing with aggregates, then do the special aggregate ** processing. */ |
︙ | ︙ | |||
2379 2380 2381 2382 2383 2384 2385 | int startagg; startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg); pParse->useAgg = 1; if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, startagg, 1); } if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, | | | 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 | int startagg; startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg); pParse->useAgg = 1; if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, startagg, 1); } if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, iParm, startagg, endagg, aff) ){ goto select_end; } sqlite3VdbeAddOp(v, OP_Goto, 0, startagg); sqlite3VdbeResolveLabel(v, endagg); sqlite3VdbeAddOp(v, OP_Noop, 0, 0); pParse->useAgg = 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.76 2004/05/18 09:58:08 danielk1977 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; |
︙ | ︙ | |||
212 213 214 215 216 217 218 | /* If we are trying to update a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView; pView = sqlite3SelectDup(pTab->pSelect); | | | 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | /* If we are trying to update a view, construct that view into ** a temporary table. */ if( isView ){ Select *pView; pView = sqlite3SelectDup(pTab->pSelect); sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0); if( pWInfo==0 ) goto update_cleanup; |
︙ | ︙ | |||
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | sqlite3VdbeAddOp(v, OP_Integer, 0, 0); } if( row_triggers_exist ){ /* Create pseudo-tables for NEW and OLD */ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); /* The top of the update loop for when there are triggers. */ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); | > > | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | sqlite3VdbeAddOp(v, OP_Integer, 0, 0); } if( row_triggers_exist ){ /* Create pseudo-tables for NEW and OLD */ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol); sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol); /* The top of the update loop for when there are triggers. */ sqlite3VdbeAddOp(v, OP_ListRewind, 0, 0); addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); |
︙ | ︙ |
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.298 2004/05/18 09:58:08 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
480 481 482 483 484 485 486 487 488 489 490 491 492 493 | /* Affinity NONE. Do nothing. */ break; default: assert(0); } } #ifdef VDBE_PROFILE /* ** The following routine only works on pentium-class processors. ** It uses the RDTSC opcode to read cycle count value out of the ** processor and returns that value. This can be used for high-res ** profiling. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 | /* Affinity NONE. Do nothing. */ break; default: assert(0); } } static int getBtreeMem( BtCursor *pCur, /* Cursor pointing at record to retrieve. */ int offset, /* Offset from the start of data to return bytes from. */ int amt, /* Number of bytes to return. */ int key, /* If true, retrieve from the btree key, not data. */ Mem *pMem /* OUT: Return data in this Mem structure. */ ){ char *zData; if( key ){ zData = (char *)sqlite3BtreeKeyFetch(pCur, offset+amt); }else{ zData = (char *)sqlite3BtreeDataFetch(pCur, offset+amt); } if( zData ){ pMem->z = &zData[offset]; pMem->n = amt; pMem->flags = MEM_Blob|MEM_Ephem; }else{ int rc; if( amt>NBFS ){ zData = (char *)sqliteMallocRaw(amt); if( !zData ){ return SQLITE_NOMEM; } pMem->flags = MEM_Blob|MEM_Dyn; }else{ zData = &(pMem->zShort[0]); pMem->flags = MEM_Blob|MEM_Short; } pMem->z = zData; if( key ){ rc = sqlite3BtreeKey(pCur, offset, amt, zData); }else{ rc = sqlite3BtreeData(pCur, offset, amt, zData); } if( rc!=SQLITE_OK ){ if( amt>NBFS ){ sqliteFree(zData); } return rc; } } return SQLITE_OK; } #ifdef VDBE_PROFILE /* ** The following routine only works on pentium-class processors. ** It uses the RDTSC opcode to read cycle count value out of the ** processor and returns that value. This can be used for high-res ** profiling. |
︙ | ︙ | |||
2015 2016 2017 2018 2019 2020 2021 | ** If the KeyAsData opcode has previously executed on this cursor, then the ** field might be extracted from the key rather than the data. ** ** If P1 is negative, then the record is stored on the stack rather than in ** a table. For P1==-1, the top of the stack is used. For P1==-2, the ** next on the stack is used. And so forth. The value pushed is always ** just a pointer into the record which is stored further down on the | | > < < < < > > > > < < | > > > > > > > | > > > > > > > | | > > > > > > > > > > | > > > > > > > > > | | 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 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 | ** If the KeyAsData opcode has previously executed on this cursor, then the ** field might be extracted from the key rather than the data. ** ** If P1 is negative, then the record is stored on the stack rather than in ** a table. For P1==-1, the top of the stack is used. For P1==-2, the ** next on the stack is used. And so forth. The value pushed is always ** just a pointer into the record which is stored further down on the ** stack. The column value is not copied. The number of columns in the ** record is stored on the stack just above the record itself. */ case OP_Column: { int payloadSize; /* Number of bytes in the record */ int i = pOp->p1; int p2 = pOp->p2; /* column number to retrieve */ Cursor *pC = 0; char *zRec; /* Pointer to record-data from stack or pseudo-table. */ BtCursor *pCrsr; u64 nField; /* number of fields in the record */ int len; /* The length of the serialized data for the column */ int offset = 0; int nn; char *zData; Mem zMem; zMem.flags = 0; assert( i<p->nCursor ); pTos++; /* If the record is coming from the stack, not from a cursor, then there ** is nowhere to cache the record header infomation. This simplifies ** things greatly, so deal with this case seperately. */ if( i<0 ){ char *zRec; /* Pointer to record data from the stack. */ int off = 0; /* Offset in zRec to start of the columns data. */ int off2 = 0; /* Offset in zRec to the next serial type to read */ u64 colType; /* The serial type of the value being read. */ assert( &pTos[i-1]>=p->aStack ); assert( pTos[i].flags & MEM_Str ); assert( pTos[i-1].flags & MEM_Int ); if( pTos[i].n==0 ){ pTos->flags = MEM_Null; break; } zRec = pTos[i].z; nField = pTos[i-1].i; for( nn=0; nn<nField; nn++ ){ u64 v; off2 += sqlite3GetVarint(&zRec[off2], &v); if( nn==p2 ){ colType = v; }else if( nn<p2 ){ off += sqlite3VdbeSerialTypeLen(v); } } off += off2; sqlite3VdbeSerialGet(&zRec[off], colType, pTos); break; } /* This block sets the variable payloadSize, and if the data is coming ** from the stack or from a pseudo-table zRec. If the data is coming ** from a real cursor, then zRec is left as NULL. */ if( (pC = p->apCsr[i])->pCursor!=0 ){ sqlite3VdbeCursorMoveto(pC); zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; }else if( pC->cacheValid ){ payloadSize = pC->payloadSize; |
︙ | ︙ | |||
2089 2090 2091 2092 2093 2094 2095 | assert( !pC || pC->nField>0 ); assert( p2<pC->nField ); nField = pC->nField; /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ | | < < < < < < < < < < < < < < < < < < < < < < < | < < < < | < > | | | < < < < < < < < < < < < < < < | < < < | < | | | < < < < < > > > < | < < < < < | < | < < < < < < < < | < | < < < < < | < | < < < | < | < | 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 | assert( !pC || pC->nField>0 ); assert( p2<pC->nField ); nField = pC->nField; /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ if( !pC || !pC->cacheValid ){ pC->payloadSize = payloadSize; if( !pC->aType ){ pC->aType = sqliteMallocRaw( nField*sizeof(pC->aType[0]) ); if( pC->aType==0 ){ goto no_mem; } } if( zRec ){ zData = zRec; }else{ /* Estimate the maximum space required by the nField varints by ** assuming the maximum space for each is the length required to store: ** ** (<record length> * 2) + 13 ** ** This is the serial-type for a text object as long as the record ** itself. In almost all cases the length required to store this is ** three bytes or less. */ int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nField; if( max_space>payloadSize ){ max_space = payloadSize; } rc = getBtreeMem(pCrsr, 0, max_space, pC->keyAsData, &zMem); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } zData = zMem.z; } /* Read all the serial types for the record. At the end of this block ** variable offset is set to the offset to the start of Data0 in the record. */ for(nn=0; nn<nField; nn++){ offset += sqlite3GetVarint(&zData[offset], &pC->aType[nn]); } pC->nHeader = offset; pC->cacheValid = 1; Release(&zMem); zMem.flags = 0; } /* Compute the offset from the beginning of the record to the beginning ** of the data. And get the length of the data. */ offset = pC->nHeader; for(nn=0; nn<p2; nn++){ offset += sqlite3VdbeSerialTypeLen(pC->aType[nn]); } if( zRec ){ zData = &zRec[offset]; }else{ len = sqlite3VdbeSerialTypeLen(pC->aType[p2]); getBtreeMem(pCrsr, offset, len, pC->keyAsData, &zMem); zData = zMem.z; } sqlite3VdbeSerialGet(zData, pC->aType[p2], pTos); Release(&zMem); break; } /* Opcode MakeRecord P1 * P3 ** ** This opcode (not yet in use) is a replacement for the current ** OP_MakeRecord that supports the SQLite3 manifest typing feature. |
︙ | ︙ | |||
2289 2290 2291 2292 2293 2294 2295 | Mem *pData0 = &pTos[1-nField]; assert( pData0>=p->aStack ); zAffinity = pOp->p3; /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ | < | 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 | Mem *pData0 = &pTos[1-nField]; assert( pData0>=p->aStack ); zAffinity = pOp->p3; /* Loop through the elements that will make up the record to figure ** out how much space is required for the new record. */ for(pRec=pData0; pRec<=pTos; pRec++){ u64 serial_type; if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0]); } serial_type = sqlite3VdbeSerialType(pRec); nBytes += sqlite3VdbeSerialTypeLen(serial_type); |
︙ | ︙ | |||
2313 2314 2315 2316 2317 2318 2319 | zNewRecord = sqliteMallocRaw(nBytes); if( !zNewRecord ){ goto no_mem; } /* Write the record */ zCsr = zNewRecord; | < | 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 | zNewRecord = sqliteMallocRaw(nBytes); if( !zNewRecord ){ goto no_mem; } /* Write the record */ zCsr = zNewRecord; for(pRec=pData0; pRec<=pTos; pRec++){ u64 serial_type = sqlite3VdbeSerialType(pRec); zCsr += sqlite3PutVarint(zCsr, serial_type); /* serial type */ } for(pRec=pData0; pRec<=pTos; pRec++){ zCsr += sqlite3VdbeSerialPut(zCsr, pRec); /* serial data */ } |
︙ | ︙ | |||
2344 2345 2346 2347 2348 2349 2350 | break; } /* Opcode: MakeKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable | | | | | 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 | break; } /* Opcode: MakeKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. If P2 is zero, then the original ** entries are popped off the stack. If P2 is not zero, the original ** entries remain on the stack. ** ** P3 is interpreted in the same way as for MakeIdxKey. */ /* Opcode: MakeIdxKey P1 P2 P3 ** ** Convert the top P1 entries of the stack into a single entry suitable ** for use as the key in an index. In addition, take one additional integer |
︙ | ︙ | |||
3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 | /* Opcode: KeyAsData P1 P2 * ** ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ** data off of the key rather than the data. This is used for ** processing compound selects. */ case OP_KeyAsData: { int i = pOp->p1; assert( i>=0 && i<p->nCursor ); p->apCsr[i]->keyAsData = pOp->p2; break; } /* Opcode: RowData P1 * * ** ** Push onto the stack the complete row data for cursor P1. ** There is no interpretation of the data. It is just copied | > > > > > | 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 | /* Opcode: KeyAsData P1 P2 * ** ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or ** off (if P2==0). In key-as-data mode, the OP_Column opcode pulls ** data off of the key rather than the data. This is used for ** processing compound selects. ** ** This opcode also instructs the cursor that the keys used will be ** serialized in the record format usually used for table data, not ** the usual index key format. */ case OP_KeyAsData: { int i = pOp->p1; assert( i>=0 && i<p->nCursor ); p->apCsr[i]->keyAsData = pOp->p2; sqlite3BtreeSetCompare(p->apCsr[i]->pCursor, sqlite3VdbeRowCompare, p->apCsr[i]); break; } /* Opcode: RowData P1 * * ** ** Push onto the stack the complete row data for cursor P1. ** There is no interpretation of the data. It is just copied |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
362 363 364 365 366 367 368 | } } while( j>0 && isspace(z[j-1]) ){ j--; } z[j] = 0; } /* | | | > | | | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | } } while( j>0 && isspace(z[j-1]) ){ j--; } z[j] = 0; } /* ** Search the current program starting at instruction addr for the given ** opcode and P2 value. Return the address plus 1 if found and 0 if not ** found. */ int sqlite3VdbeFindOp(Vdbe *p, int addr, int op, int p2){ int i; assert( p->magic==VDBE_MAGIC_INIT ); for(i=addr; i<p->nOp; i++){ if( p->aOp[i].opcode==op && p->aOp[i].p2==p2 ) return i+1; } return 0; } /* ** Return the opcode for a given address. |
︙ | ︙ | |||
1474 1475 1476 1477 1478 1479 1480 | /* ** This function compares the two table row records specified by ** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero ** or positive integer if {nKey1, pKey1} is less than, equal to or ** greater than {nKey2, pKey2}. ** | | > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 | /* ** This function compares the two table row records specified by ** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero ** or positive integer if {nKey1, pKey1} is less than, equal to or ** greater than {nKey2, pKey2}. ** ** This function is pretty inefficient and will probably be replaced ** by something else in the near future. It is currently required ** by compound SELECT operators. */ int sqlite3VdbeRowCompare( void *userData, int nKey1, const void *pKey1, int nKey2, const void *pKey2 ){ Cursor *pC = (Cursor *)userData; int offset1 = 0; int offset2 = 0; int toffset1 = 0; int toffset2 = 0; int i; const unsigned char *aKey1 = (const unsigned char *)pKey1; const unsigned char *aKey2 = (const unsigned char *)pKey2; assert( pC ); assert( pC->nField>0 ); for( i=0; i<pC->nField; i++ ){ u64 dummy; offset1 += sqlite3GetVarint(&aKey1[offset1], &dummy); offset2 += sqlite3GetVarint(&aKey1[offset1], &dummy); } for( i=0; i<pC->nField; i++ ){ Mem mem1; Mem mem2; u64 serial_type1; u64 serial_type2; int rc; /* Read the serial types for the next element in each key. */ toffset1 += sqlite3GetVarint(&aKey1[toffset1], &serial_type1); toffset2 += sqlite3GetVarint(&aKey2[toffset2], &serial_type2); assert( serial_type1 && serial_type2 ); /* Assert that there is enough space left in each key for the blob of ** data to go with the serial type just read. This assert may fail if ** the file is corrupted. Then read the value from each key into mem1 ** and mem2 respectively. */ offset1 += sqlite3VdbeSerialGet(&aKey1[offset1], serial_type1, &mem1); offset2 += sqlite3VdbeSerialGet(&aKey2[offset2], serial_type2, &mem2); rc = sqlite3MemCompare(&mem1, &mem2); if( mem1.flags&MEM_Dyn ){ sqliteFree(mem1.z); } if( mem2.flags&MEM_Dyn ){ sqliteFree(mem2.z); } if( rc!=0 ){ return rc; } } return 0; } /* ** pCur points at an index entry. Read the rowid (varint occuring at ** the end of the entry and store it in *rowid. Return SQLITE_OK if ** everything works, or an error code otherwise. |
︙ | ︙ |