Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Combine the eDest and iParm arguments to sqlite3Select() into a single type - "SelectDest". (CVS 4657) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
86dcdfe6d7d629618ccb3c3ff0ca09f2 |
User & Date: | danielk1977 2008-01-02 16:27:10.000 |
Context
2008-01-02
| ||
17:11 | Minor optimizations for sub-selects in EXISTS(...) expressions: Discard any DISTINCT or ORDER BY clauses and do not calculate any column values. (CVS 4658) (check-in: fbd17a8976 user: danielk1977 tags: trunk) | |
16:27 | Combine the eDest and iParm arguments to sqlite3Select() into a single type - "SelectDest". (CVS 4657) (check-in: 86dcdfe6d7 user: danielk1977 tags: trunk) | |
14:28 | Add opcodes OP_ResultRow and OP_RegMakeRec which are register-based equivalents to OP_Callback and OP_MakeRecord. Use the new opcodes. (CVS 4656) (check-in: 4c7f35da77 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.452 2008/01/02 16:27:10 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. |
︙ | ︙ | |||
1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 | ** ** A shared-cache write-lock is not required to write to the new table, ** as a schema-lock must have already been obtained to create it. Since ** a schema-lock excludes all other database users, the write-lock would ** be redundant. */ if( pSelect ){ Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; | > | | 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 | ** ** A shared-cache write-lock is not required to write to the new table, ** as a schema-lock must have already been obtained to create it. Since ** a schema-lock excludes all other database users, the write-lock would ** be redundant. */ if( pSelect ){ SelectDest dest = {SRT_Table, 1, 0}; Table *pSelTab; sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Integer, iDb, 0); sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0); pParse->nTab = 2; sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); sqlite3VdbeAddOp(v, OP_Close, 1, 0); if( pParse->nErr==0 ){ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect); if( pSelTab==0 ) return; assert( p->aCol==0 ); p->nCol = pSelTab->nCol; p->aCol = pSelTab->aCol; |
︙ | ︙ |
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 ** in order to generate code for 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 ** in order to generate code for DELETE FROM statements. ** ** $Id: delete.c,v 1.139 2008/01/02 16:27:10 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. |
︙ | ︙ | |||
216 217 218 219 220 221 222 223 224 | sqlite3VdbeJumpHere(v, iGoto); } /* If we are trying to delete from a view, realize that view into ** a ephemeral table. */ if( isView ){ Select *pView = sqlite3SelectDup(db, pTab->pSelect); sqlite3SelectMask(pParse, pView, old_col_mask); | > > | | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | sqlite3VdbeJumpHere(v, iGoto); } /* If we are trying to delete from a view, realize that view into ** a ephemeral table. */ if( isView ){ SelectDest dest = {SRT_EphemTab, 0, 0}; Select *pView = sqlite3SelectDup(db, pTab->pSelect); sqlite3SelectMask(pParse, pView, old_col_mask); dest.iParm = iCur; sqlite3Select(pParse, pView, &dest, 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 ){ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.324 2008/01/02 16:27:10 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
1734 1735 1736 1737 1738 1739 1740 | if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ | > | > | | 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 | if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) ** ** Generate code to write the results of the select into the temporary ** table allocated and opened above. */ SelectDest dest = {SRT_Set, 0, 0}; dest.iParm = pExpr->iTable; dest.affinity = (int)affinity; ExprList *pEList; assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable ); if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0, 0) ){ return; } pEList = pExpr->pSelect->pEList; if( pEList && pEList->nExpr>0 ){ keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pEList->a[0].pExpr); } |
︙ | ︙ | |||
1794 1795 1796 1797 1798 1799 1800 | case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ static const Token one = { (u8*)"1", 0, 1 }; Select *pSel; | | < | | | | | | | | 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 | case TK_SELECT: { /* This has to be a scalar SELECT. Generate code to put the ** value of this select in a memory cell and record the number ** of the memory cell in iColumn. */ static const Token one = { (u8*)"1", 0, 1 }; Select *pSel; SelectDest dest; pSel = pExpr->pSelect; dest.iParm = pParse->nMem++; if( pExpr->op==TK_SELECT ){ dest.eDest = SRT_Mem; sqlite3VdbeAddOp(v, OP_MemNull, 0, dest.iParm); VdbeComment((v, "Init subquery result")); }else{ dest.eDest = SRT_Exists; sqlite3VdbeAddOp(v, OP_MemInt, 0, dest.iParm); VdbeComment((v, "Init EXISTS result")); } sqlite3ExprDelete(pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one); if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0, 0) ){ return; } pExpr->iColumn = dest.iParm; break; } } if( testAddr ){ sqlite3VdbeJumpHere(v, testAddr); } |
︙ | ︙ |
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.201 2008/01/02 16:27:10 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: |
︙ | ︙ | |||
472 473 474 475 476 477 478 479 480 481 482 483 484 | ** statement uses the the table that is being inserted into, then the ** subroutine is also coded here. That subroutine stores the SELECT ** results in a temporary table. (Template 3.) */ 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); /* Resolve the expressions in the SELECT statement and execute it. */ | > > | | 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | ** statement uses the the table that is being inserted into, then the ** subroutine is also coded here. That subroutine stores the SELECT ** results in a temporary table. (Template 3.) */ if( pSelect ){ /* Data is coming from a SELECT. Generate code to implement that SELECT */ SelectDest dest = {SRT_Subroutine, 0, 0}; int rc, iInitCode; iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0); iSelectLoop = sqlite3VdbeCurrentAddr(v); iInsertBlock = sqlite3VdbeMakeLabel(v); dest.iParm = iInsertBlock; /* Resolve the expressions in the SELECT statement and execute it. */ rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); if( rc || pParse->nErr || db->mallocFailed ){ goto insert_cleanup; } iCleanup = sqlite3VdbeMakeLabel(v); sqlite3VdbeAddOp(v, OP_Goto, 0, iCleanup); assert( pSelect->pEList ); |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.237 2008/01/02 16:27:10 danielk1977 Exp $ */ // All token codes are small integers with #defines that begin with "TK_" %token_prefix TK_ // The type of the data attached to each token is Token. This is also the // default type for non-terminals. |
︙ | ︙ | |||
361 362 363 364 365 366 367 | sqlite3DropTable(pParse, X, 1, E); } %endif SQLITE_OMIT_VIEW //////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { | > | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 | sqlite3DropTable(pParse, X, 1, E); } %endif SQLITE_OMIT_VIEW //////////////////////// The SELECT statement ///////////////////////////////// // cmd ::= select(X). { SelectDest dest = {SRT_Callback, 0, 0}; sqlite3Select(pParse, X, &dest, 0, 0, 0, 0); sqlite3SelectDelete(X); } %type select {Select*} %destructor select {sqlite3SelectDelete($$);} %type oneselect {Select*} %destructor oneselect {sqlite3SelectDelete($$);} |
︙ | ︙ |
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.376 2008/01/02 16:27:10 danielk1977 Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
475 476 477 478 479 480 481 | /* ** Generate an error message when a SELECT is used within a subexpression ** (example: "a IN (SELECT * FROM table)") but it has more than 1 result ** column. We do this in a subroutine because the error occurs in multiple ** places. */ | | > > > > > | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | /* ** Generate an error message when a SELECT is used within a subexpression ** (example: "a IN (SELECT * FROM table)") but it has more than 1 result ** column. We do this in a subroutine because the error occurs in multiple ** places. */ static int checkForMultiColumnSelectError( Parse *pParse, /* Parse context. */ SelectDest *pDest, /* Destination of SELECT results */ int nExpr /* Number of result columns returned by SELECT */ ){ int eDest = pDest->eDest; if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){ sqlite3ErrorMsg(pParse, "only a single result allowed for " "a SELECT that is part of an expression"); return 1; }else{ return 0; } |
︙ | ︙ | |||
502 503 504 505 506 507 508 | Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ 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 */ | | < > > | 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 | Parse *pParse, /* The parser context */ Select *p, /* The complete select statement being coded */ ExprList *pEList, /* List of values being extracted */ 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 */ SelectDest *pDest, /* How to dispose of the results */ 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, n; int hasDistinct; /* True if the DISTINCT keyword is present */ int iMem; /* Start of memory holding result set */ int eDest = pDest->eDest; int iParm = pDest->iParm; if( v==0 ) return 0; assert( pEList!=0 ); /* If there was a LIMIT clause on the SELECT statement, then do the check ** to see if this row should be output. */ |
︙ | ︙ | |||
558 559 560 561 562 563 564 | assert( pEList->nExpr==nColumn ); codeDistinct(v, distinct, iContinue, iMem); if( pOrderBy==0 ){ codeOffset(v, p, iContinue, nColumn); } } | | | 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 | assert( pEList->nExpr==nColumn ); codeDistinct(v, distinct, iContinue, iMem); if( pOrderBy==0 ){ codeOffset(v, p, iContinue, nColumn); } } if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ return 0; } switch( eDest ){ /* In this mode, write each query result to the key of the temporary ** table iParm. */ |
︙ | ︙ | |||
615 616 617 618 619 620 621 | ** item into the set table with bogus data. */ case SRT_Set: { int addr2; assert( nColumn==1 ); addr2 = sqlite3VdbeAddOp(v, OP_IfMemNull, iMem+1, 0); | | | | 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 | ** item into the set table with bogus data. */ case SRT_Set: { int addr2; assert( nColumn==1 ); addr2 = sqlite3VdbeAddOp(v, OP_IfMemNull, iMem+1, 0); p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity); if( pOrderBy ){ /* At first glance you would think we could optimize out the ** ORDER BY in this case since the order of entries in the set ** does not matter. But there might be a LIMIT clause, in which ** case the order does matter */ sqlite3VdbeAddOp(v, OP_MemLoad, iMem+1, 0); pushOntoSorter(pParse, pOrderBy, p); }else{ sqlite3VdbeOp3(v, OP_RegMakeRec, iMem, 0, &p->affinity, 1); sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0); } sqlite3VdbeJumpHere(v, addr2); break; } /* If any row exist in the result set, record that fact and abort. */ |
︙ | ︙ | |||
745 746 747 748 749 750 751 | /* ** If the inner loop was generated using a non-null pOrderBy argument, ** then the results were placed in a sorter. After the loop is terminated ** we need to run the sorter and output the results. The following ** routine generates the code needed to do that. */ static void generateSortTail( | | | | | | < > > > | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 | /* ** If the inner loop was generated using a non-null pOrderBy argument, ** then the results were placed in a sorter. After the loop is terminated ** we need to run the sorter and output the results. The following ** routine generates the code needed to do that. */ static void generateSortTail( Parse *pParse, /* Parsing context */ Select *p, /* The SELECT statement */ Vdbe *v, /* Generate code into this VDBE */ int nColumn, /* Number of columns of data */ SelectDest *pDest /* Write the sorted results here */ ){ int brk = sqlite3VdbeMakeLabel(v); int cont = sqlite3VdbeMakeLabel(v); int addr; int iTab; int pseudoTab = 0; ExprList *pOrderBy = p->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iParm; iTab = pOrderBy->iECursor; if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ pseudoTab = pParse->nTab++; sqlite3VdbeAddOp(v, OP_OpenPseudo, pseudoTab, 0); sqlite3VdbeAddOp(v, OP_SetNumColumns, pseudoTab, nColumn); } |
︙ | ︙ | |||
786 787 788 789 790 791 792 | #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1); | | | 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 | #ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeAddOp(v, OP_Pop, 1, 0); sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3); sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1); sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0); break; } case SRT_Mem: { assert( nColumn==1 ); sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); /* The LIMIT clause will terminate the loop for us */ break; |
︙ | ︙ | |||
1842 1843 1844 1845 1846 1847 1848 | ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ static int multiSelect( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ | | < > > > > > | 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 | ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ static int multiSelect( Parse *pParse, /* Parsing context */ Select *p, /* The right-most of SELECTs to be coded */ SelectDest *pDest, /* What to do with query results */ 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 */ int nCol; /* Number of columns in the result set */ ExprList *pOrderBy; /* The ORDER BY clause on p */ int aSetP2[2]; /* Set P2 value of these op to number of columns */ int nSetP2 = 0; /* Number of slots in aSetP2[] used */ SelectDest dest; dest.eDest = pDest->eDest; dest.iParm = pDest->iParm; dest.affinity = pDest->affinity; /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. */ if( p==0 || p->pPrior==0 ){ rc = 1; goto multi_select_end; } |
︙ | ︙ | |||
1887 1888 1889 1890 1891 1892 1893 | if( v==0 ){ rc = 1; goto multi_select_end; } /* Create the destination temporary table if necessary */ | | | | | | > | | | 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 | if( v==0 ){ rc = 1; goto multi_select_end; } /* Create the destination temporary table if necessary */ if( dest.eDest==SRT_EphemTab ){ assert( p->pEList ); assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) ); aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, dest.iParm, 0); dest.eDest = SRT_Table; } /* Generate code for the left and right SELECT statements. */ pOrderBy = p->pOrderBy; switch( p->op ){ case TK_ALL: { if( pOrderBy==0 ){ int addr = 0; assert( !pPrior->pLimit ); pPrior->pLimit = p->pLimit; pPrior->pOffset = p->pOffset; rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0, aff); p->pLimit = 0; p->pOffset = 0; if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit>=0 ){ addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0); VdbeComment((v, "Jump ahead if LIMIT reached")); } rc = sqlite3Select(pParse, p, &dest, 0, 0, 0, aff); p->pPrior = pPrior; if( rc ){ goto multi_select_end; } if( addr ){ sqlite3VdbeJumpHere(v, addr); } 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 */ int op = 0; /* One of the SRT_ operations to apply to self */ int priorOp; /* The SRT_ operation to apply to prior selects */ Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ int addr; SelectDest uniondest; priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; if( dest.eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){ /* We can reuse a temporary table generated by a SELECT to our ** right. */ unionTab = dest.iParm; }else{ /* We will need to create our own temporary table to hold the ** intermediate results. */ unionTab = pParse->nTab++; if( processCompoundOrderBy(pParse, p, unionTab) ){ rc = 1; |
︙ | ︙ | |||
1968 1969 1970 1971 1972 1973 1974 | createSortingIndex(pParse, p, pOrderBy); assert( p->pEList ); } /* Code the SELECT statements to our left */ assert( !pPrior->pOrderBy ); | > > | > | | | < | > | 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 | createSortingIndex(pParse, p, pOrderBy); assert( p->pEList ); } /* Code the SELECT statements to our left */ assert( !pPrior->pOrderBy ); uniondest.eDest = priorOp; uniondest.iParm = unionTab; rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* 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; p->pOrderBy = 0; p->disallowOrderBy = pOrderBy!=0; pLimit = p->pLimit; p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; uniondest.eDest = op; rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0, aff); /* Query flattening in sqlite3Select() might refill p->pOrderBy. ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */ sqlite3ExprListDelete(p->pOrderBy); p->pPrior = pPrior; p->pOrderBy = pOrderBy; sqlite3ExprDelete(p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; p->iLimit = -1; p->iOffset = -1; if( rc ){ goto multi_select_end; } /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ if( dest.eDest!=priorOp || unionTab!=dest.iParm ){ int iCont, iBreak, iStart; assert( p->pEList ); if( dest.eDest==SRT_Callback ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; generateColumnNames(pParse, 0, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak); iStart = sqlite3VdbeCurrentAddr(v); rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, pOrderBy, -1, &dest, 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); } break; } case TK_INTERSECT: { int tab1, tab2; int iCont, iBreak, iStart; Expr *pLimit, *pOffset; int addr; SelectDest intersectdest = {SRT_Union, 0, 0}; /* 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++; |
︙ | ︙ | |||
2059 2060 2061 2062 2063 2064 2065 | assert( p->addrOpenEphm[0] == -1 ); p->addrOpenEphm[0] = addr; p->pRightmost->usesEphm = 1; assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ | > | > | | < | | 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 | assert( p->addrOpenEphm[0] == -1 ); p->addrOpenEphm[0] = addr; p->pRightmost->usesEphm = 1; assert( p->pEList ); /* Code the SELECTs to our left into temporary table "tab1". */ intersectdest.iParm = tab1; rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0, aff); if( rc ){ goto multi_select_end; } /* Code the current SELECT into temporary table "tab2" */ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0); assert( p->addrOpenEphm[1] == -1 ); p->addrOpenEphm[1] = addr; p->pPrior = 0; pLimit = p->pLimit; p->pLimit = 0; pOffset = p->pOffset; p->pOffset = 0; intersectdest.iParm = tab2; rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0, aff); p->pPrior = pPrior; sqlite3ExprDelete(p->pLimit); p->pLimit = pLimit; p->pOffset = pOffset; if( rc ){ goto multi_select_end; } /* Generate code to take the intersection of the two temporary ** tables. */ assert( p->pEList ); if( dest.eDest==SRT_Callback ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; generateColumnNames(pParse, 0, pFirst->pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak); iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0); sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont); rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, pOrderBy, -1, &dest, iCont, iBreak, 0); if( rc ){ rc = 1; goto multi_select_end; } sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp(v, OP_Next, tab1, iStart); sqlite3VdbeResolveLabel(v, iBreak); |
︙ | ︙ | |||
2225 2226 2227 2228 2229 2230 2231 | assert( p->pRightmost==p ); assert( p->addrOpenEphm[2]>=0 ); addr = p->addrOpenEphm[2]; sqlite3VdbeChangeP2(v, addr, p->pOrderBy->nExpr+2); pKeyInfo->nField = nOrderByExpr; sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); pKeyInfo = 0; | | | 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 | assert( p->pRightmost==p ); assert( p->addrOpenEphm[2]>=0 ); addr = p->addrOpenEphm[2]; sqlite3VdbeChangeP2(v, addr, p->pOrderBy->nExpr+2); pKeyInfo->nField = nOrderByExpr; sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); pKeyInfo = 0; generateSortTail(pParse, p, v, p->pEList->nExpr, &dest); } sqlite3_free(pKeyInfo); } multi_select_end: return rc; |
︙ | ︙ | |||
2621 2622 2623 2624 2625 2626 2627 | ** can be no GROUP BY or HAVING or WHERE clauses. The result set must ** be the min() or max() of a single column of the table. The column ** in the min() or max() function must be indexed. ** ** The parameters to this routine are the same as for sqlite3Select(). ** See the header comment on that routine for additional information. */ | | | 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 | ** can be no GROUP BY or HAVING or WHERE clauses. The result set must ** be the min() or max() of a single column of the table. The column ** in the min() or max() function must be indexed. ** ** The parameters to this routine are the same as for sqlite3Select(). ** See the header comment on that routine for additional information. */ static int simpleMinMaxQuery(Parse *pParse, Select *p, SelectDest *pDest){ Expr *pExpr; int iCol; Table *pTab; Index *pIdx; int base; Vdbe *v; int seekOp; |
︙ | ︙ | |||
2693 2694 2695 2696 2697 2698 2699 | ** The column names have already been generated in the calling function. */ v = sqlite3GetVdbe(pParse); if( v==0 ) return 0; /* If the output is destined for a temporary table, open that table. */ | | | | 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 | ** The column names have already been generated in the calling function. */ v = sqlite3GetVdbe(pParse); if( v==0 ) return 0; /* If the output is destined for a temporary table, open that table. */ if( pDest->eDest==SRT_EphemTab ){ sqlite3VdbeAddOp(v, OP_OpenEphemeral, pDest->iParm, 1); } /* Generating code to find the min or the max. Basically all we have ** to do is find the first or the last entry in the chosen index. If ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first ** or last entry in the main table. */ |
︙ | ︙ | |||
2752 2753 2754 2755 2756 2757 2758 | sqlite3VdbeAddOp(v, OP_Close, iIdx, 0); sqlite3VdbeAddOp(v, OP_MoveGe, base, 0); } eList.nExpr = 1; memset(&eListItem, 0, sizeof(eListItem)); eList.a = &eListItem; eList.a[0].pExpr = pExpr; | | | 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 | sqlite3VdbeAddOp(v, OP_Close, iIdx, 0); sqlite3VdbeAddOp(v, OP_MoveGe, 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, pDest, brk, brk, 0); sqlite3VdbeResolveLabel(v, brk); sqlite3VdbeAddOp(v, OP_Close, base, 0); return 1; } /* |
︙ | ︙ | |||
3023 3024 3025 3026 3027 3028 3029 | } #endif /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the | > | | | | > | | | < > > > > > > > > > > > > > | | | 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 | } #endif /* ** Generate code for the given SELECT statement. ** ** The results are distributed in various ways depending on the ** contents of the SelectDest structure pointed to by argument pDest ** as follows: ** ** pDest->eDest Result ** ------------ ------------------------------------------- ** SRT_Callback Invoke the callback for each row of the result. ** ** SRT_Mem Store first result in memory cell pDest->iParm ** ** SRT_Set Store non-null results as keys of table pDest->iParm. ** Apply the affinity pDest->affinity before storing them. ** ** SRT_Union Store results as a key in a temporary table pDest->iParm. ** ** SRT_Except Remove results from the temporary table pDest->iParm. ** ** SRT_Table Store results in temporary table pDest->iParm ** ** SRT_EphemTab Create an temporary table pDest->iParm and store ** the result there. The cursor is left open after ** returning. ** ** SRT_Subroutine For each row returned, push the results onto the ** vdbe stack and call the subroutine (via OP_Gosub) ** at address pDest->iParm. ** ** SRT_Exists Store a 1 in memory cell pDest->iParm if the result ** set is not empty. ** ** SRT_Discard Throw the results away. ** ** See the selectInnerLoop() function for a canonical listing of the ** allowed values of eDest and their meanings. ** ** This routine returns the number of errors. If any errors are ** encountered, then an appropriate error message is left in ** pParse->zErrMsg. ** ** This routine does NOT free the Select structure passed in. The ** calling function needs to do that. |
︙ | ︙ | |||
3074 3075 3076 3077 3078 3079 3080 | ** call, pParent will point to the outer query. Because the subquery is ** the second element in a three-way join, the parentTab parameter will ** be 1 (the 2nd value of a 0-indexed array.) */ int sqlite3Select( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ | | < | 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 | ** call, pParent will point to the outer query. Because the subquery is ** the second element in a three-way join, the parentTab parameter will ** be 1 (the 2nd value of a 0-indexed array.) */ int sqlite3Select( Parse *pParse, /* The parser context */ Select *p, /* The SELECT statement being coded. */ SelectDest *pDest, /* What to do with the query results */ 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, j; /* Loop counters */ WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ |
︙ | ︙ | |||
3107 3108 3109 3110 3111 3112 3113 | if( p==0 || db->mallocFailed || pParse->nErr ){ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); pOrderBy = p->pOrderBy; | | | 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 | if( p==0 || db->mallocFailed || pParse->nErr ){ return 1; } if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; memset(&sAggInfo, 0, sizeof(sAggInfo)); pOrderBy = p->pOrderBy; if( IgnorableOrderby(pDest) ){ p->pOrderBy = 0; } if( sqlite3SelectResolve(pParse, p, 0) ){ goto select_end; } p->pOrderBy = pOrderBy; |
︙ | ︙ | |||
3132 3133 3134 3135 3136 3137 3138 | pRight = pLoop; } if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); return 1; } } | | | 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 | pRight = pLoop; } if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); return 1; } } return multiSelect(pParse, p, pDest, aff); } #endif /* Make local copies of the parameters for this query. */ pTabList = p->pSrc; pWhere = p->pWhere; |
︙ | ︙ | |||
3157 3158 3159 3160 3161 3162 3163 | */ if( pParse->nErr>0 ) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ #ifndef SQLITE_OMIT_SUBQUERY | | | > > | < | | | 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 | */ if( pParse->nErr>0 ) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ #ifndef SQLITE_OMIT_SUBQUERY if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ goto select_end; } #endif /* ORDER BY is ignored for some destinations. */ if( IgnorableOrderby(pDest) ){ pOrderBy = 0; } /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto select_end; /* Generate code for all sub-queries in the FROM clause */ #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; i<pTabList->nSrc; i++){ const char *zSavedAuthContext = 0; int needRestoreContext; struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest = {SRT_EphemTab, 0, 0}; if( pItem->pSelect==0 || pItem->isPopulated ) continue; if( pItem->zName!=0 ){ zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; needRestoreContext = 1; }else{ needRestoreContext = 0; } #if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 /* Increment Parse.nHeight by the height of the largest expression ** tree refered to by this, the parent select. The child select ** may contain expression trees of at most ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit ** more conservative than necessary, but much easier than enforcing ** an exact limit. */ pParse->nHeight += sqlite3SelectExprHeight(p); #endif dest.iParm = pItem->iCursor; sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0); if( db->mallocFailed ){ goto select_end; } #if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0 pParse->nHeight -= sqlite3SelectExprHeight(p); #endif if( needRestoreContext ){ pParse->zAuthContext = zSavedAuthContext; } pTabList = p->pSrc; pWhere = p->pWhere; if( !IgnorableOrderby(pDest) ){ pOrderBy = p->pOrderBy; } pGroupBy = p->pGroupBy; pHaving = p->pHaving; isDistinct = p->isDistinct; } #endif /* Check for the special case of a min() or max() function by itself ** in the result set. */ if( simpleMinMaxQuery(pParse, p, pDest) ){ rc = 0; goto select_end; } /* Check to see if this is a subquery that can be "flattened" into its parent. ** If flattening is a possiblity, do so and return immediately. */ |
︙ | ︙ | |||
3272 3273 3274 3275 3276 3277 3278 | sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); }else{ addrSortIndex = -1; } /* If the output is destined for a temporary table, open that table. */ | | | | 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 | sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); }else{ addrSortIndex = -1; } /* If the output is destined for a temporary table, open that table. */ if( pDest->eDest==SRT_EphemTab ){ sqlite3VdbeAddOp(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr); } /* Set the limiter. */ iEnd = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iEnd); |
︙ | ︙ | |||
3314 3315 3316 3317 3318 3319 3320 | sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); p->addrOpenEphm[2] = -1; } /* Use the standard inner loop */ assert(!isDistinct); | | | | 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 | sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); p->addrOpenEphm[2] = -1; } /* Use the standard inner loop */ assert(!isDistinct); if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest, pWInfo->iContinue, pWInfo->iBreak, aff) ){ goto select_end; } /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); }else{ |
︙ | ︙ | |||
3434 3435 3436 3437 3438 3439 3440 | VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); } rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, | | | 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 | VdbeComment((v, "Groupby result generator entry point")); sqlite3VdbeAddOp(v, OP_Return, 0, 0); finalizeAggFunctions(pParse, &sAggInfo); if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); } rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, distinct, pDest, addrOutputRow+1, addrSetAbort, aff); if( rc ){ goto select_end; } sqlite3VdbeAddOp(v, OP_Return, 0, 0); VdbeComment((v, "end groupby result generator")); |
︙ | ︙ | |||
3575 3576 3577 3578 3579 3580 3581 | sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); pOrderBy = 0; if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1); } selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, | | | | 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 | sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); pOrderBy = 0; if( pHaving ){ sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1); } selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, pDest, addrEnd, addrEnd, aff); } sqlite3VdbeResolveLabel(v, addrEnd); } /* endif aggregate query */ /* If there is an ORDER BY clause, then we need to sort the results ** and send them to the callback one by one. */ if( pOrderBy ){ generateSortTail(pParse, p, v, pEList->nExpr, pDest); } #ifndef SQLITE_OMIT_SUBQUERY /* If this was a subquery, we have now converted the subquery into a ** temporary table. So set the SrcList_item.isPopulated flag to prevent ** this subquery from being evaluated again and to force the use of ** the temporary table. |
︙ | ︙ | |||
3618 3619 3620 3621 3622 3623 3624 | ** successful coding of the SELECT. */ select_end: /* 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. */ | | | 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 | ** successful coding of the SELECT. */ select_end: /* 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( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){ generateColumnNames(pParse, pTabList, pEList); } sqlite3_free(sAggInfo.aCol); sqlite3_free(sAggInfo.aFunc); return rc; } |
︙ | ︙ |
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.629 2008/01/02 16:27:10 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** The macro unlikely() is a hint that surrounds a boolean ** expression that is usually false. Macro likely() surrounds |
︙ | ︙ | |||
1329 1330 1331 1332 1333 1334 1335 | ** The results of a select can be distributed in several ways. */ #define SRT_Union 1 /* Store result as keys in an index */ #define SRT_Except 2 /* Remove result from a UNION index */ #define SRT_Discard 3 /* Do not save the results anywhere */ /* The ORDER BY clause is ignored for all of the above */ | | > > > > > > > > > > > | 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 | ** The results of a select can be distributed in several ways. */ #define SRT_Union 1 /* Store result as keys in an index */ #define SRT_Except 2 /* Remove result from a UNION index */ #define SRT_Discard 3 /* Do not save the results anywhere */ /* The ORDER BY clause is ignored for all of the above */ #define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard) #define SRT_Callback 4 /* Invoke a callback with each row of result */ #define SRT_Mem 5 /* Store result in a memory cell */ #define SRT_Set 6 /* Store non-null results as keys in an index */ #define SRT_Table 7 /* Store result as data with an automatic rowid */ #define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */ #define SRT_Subroutine 9 /* Call a subroutine to handle results */ #define SRT_Exists 10 /* Store 1 if the result is not empty */ /* ** A structure used to customize the behaviour of sqlite3Select(). See ** comments above sqlite3Select() for details. */ typedef struct SelectDest SelectDest; struct SelectDest { int eDest; /* How to dispose of the results */ int iParm; /* A parameter used by the eDest disposal method */ int affinity; /* Affinity used when eDest==SRT_Set */ }; /* ** An SQL parser context. A copy of this structure is passed through ** the parser and down into all the parser action routine in order to ** carry around information that is global to the entire parse. ** ** The structure is divided into two parts. When the parser and code |
︙ | ︙ | |||
1710 1711 1712 1713 1714 1715 1716 | void sqlite3SrcListShiftJoinType(SrcList*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*, int, int); void sqlite3DropIndex(Parse*, SrcList*, int); | | | 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | void sqlite3SrcListShiftJoinType(SrcList*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); void sqlite3IdListDelete(IdList*); void sqlite3SrcListDelete(SrcList*); void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*, Token*, int, int); void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*, char *aff); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,int,Expr*,Expr*); void sqlite3SelectDelete(Select*); int sqlite3SelectMask(Parse *, Select *, u32); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
681 682 683 684 685 686 687 688 | while( pTriggerStep ){ orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect); if( ss ){ sqlite3SelectResolve(pParse, ss, 0); | > | | 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 | while( pTriggerStep ){ orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin; pParse->trigStack->orconf = orconf; switch( pTriggerStep->op ){ case TK_SELECT: { Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect); if( ss ){ SelectDest dest = {SRT_Discard, 0, 0}; sqlite3SelectResolve(pParse, ss, 0); sqlite3Select(pParse, ss, &dest, 0, 0, 0, 0); sqlite3SelectDelete(ss); } break; } case TK_UPDATE: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); |
︙ | ︙ |
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.148 2008/01/02 16:27:10 danielk1977 Exp $ */ #include "sqliteInt.h" #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declaration */ static void updateVirtualTable( Parse *pParse, /* The parsing context */ |
︙ | ︙ | |||
325 326 327 328 329 330 331 332 333 | } /* If we are trying to update a view, realize that view into ** a ephemeral table. */ if( isView ){ Select *pView; pView = sqlite3SelectDup(db, pTab->pSelect); sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask); | > > | | 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | } /* If we are trying to update a view, realize that view into ** a ephemeral table. */ if( isView ){ Select *pView; SelectDest dest = {SRT_EphemTab, 0, 0}; pView = sqlite3SelectDup(db, pTab->pSelect); sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask); dest.iParm = iCur; sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0); sqlite3SelectDelete(pView); } /* Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); if( pWInfo==0 ) goto update_cleanup; |
︙ | ︙ | |||
593 594 595 596 597 598 599 600 601 602 603 604 605 606 | ExprList *pEList = 0; /* The result set of the SELECT statement */ Select *pSelect = 0; /* The SELECT statement */ Expr *pExpr; /* Temporary expression */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ int addr; /* Address of top of loop */ sqlite3 *db = pParse->db; /* Database connection */ /* Construct the SELECT statement that will find the new values for ** all updated rows. */ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3CreateIdExpr(pParse, "_rowid_"), 0); if( pRowid ){ | > | 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | ExprList *pEList = 0; /* The result set of the SELECT statement */ Select *pSelect = 0; /* The SELECT statement */ Expr *pExpr; /* Temporary expression */ int ephemTab; /* Table holding the result of the SELECT */ int i; /* Loop counter */ int addr; /* Address of top of loop */ sqlite3 *db = pParse->db; /* Database connection */ SelectDest dest = {SRT_Table, 0, 0}; /* Construct the SELECT statement that will find the new values for ** all updated rows. */ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3CreateIdExpr(pParse, "_rowid_"), 0); if( pRowid ){ |
︙ | ︙ | |||
623 624 625 626 627 628 629 | */ assert( v ); ephemTab = pParse->nTab++; sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); /* fill the ephemeral table */ | > | | 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 | */ assert( v ); ephemTab = pParse->nTab++; sqlite3VdbeAddOp(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0)); /* fill the ephemeral table */ dest.iParm = ephemTab; sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0); /* ** Generate code to scan the ephemeral table and call VDelete and ** VInsert */ sqlite3VdbeAddOp(v, OP_Rewind, ephemTab, 0); addr = sqlite3VdbeCurrentAddr(v); |
︙ | ︙ |