Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | The compound-select merge optimization is mostly working with this check-in. But there are still a few problems and so the optimization is disabled by and "#if 0". This check-in is to synchronize with the other changes happening in parallel. (CVS 5291) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
e2ba324cbcac0ba35bbde50048677e08 |
User & Date: | drh 2008-06-24 00:32:35.000 |
Context
2008-06-24
| ||
09:52 | Fix a typo in the documentation for the sqlite3_bind_XXX() APIs. (CVS 5292) (check-in: 839457f128 user: danielk1977 tags: trunk) | |
00:32 | The compound-select merge optimization is mostly working with this check-in. But there are still a few problems and so the optimization is disabled by and "#if 0". This check-in is to synchronize with the other changes happening in parallel. (CVS 5291) (check-in: e2ba324cbc user: drh tags: trunk) | |
2008-06-23
| ||
22:13 | Update OS/2 mutex implementation: make methods static and don't use them by the old names any more. Held/Notheld should be debug only. (CVS 5290) (check-in: d92418ca50 user: pweilbacher tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.375 2008/06/24 00:32:35 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Return the 'affinity' of the expression pExpr if any. ** |
︙ | ︙ | |||
752 753 754 755 756 757 758 | pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy); pNew->pHaving = sqlite3ExprDup(db, p->pHaving); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy); pNew->op = p->op; pNew->pPrior = sqlite3SelectDup(db, p->pPrior); pNew->pLimit = sqlite3ExprDup(db, p->pLimit); pNew->pOffset = sqlite3ExprDup(db, p->pOffset); | | | | 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 | pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy); pNew->pHaving = sqlite3ExprDup(db, p->pHaving); pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy); pNew->op = p->op; pNew->pPrior = sqlite3SelectDup(db, p->pPrior); pNew->pLimit = sqlite3ExprDup(db, p->pLimit); pNew->pOffset = sqlite3ExprDup(db, p->pOffset); pNew->iLimit = 0; pNew->iOffset = 0; pNew->isResolved = p->isResolved; pNew->isAgg = p->isAgg; pNew->usesEphm = 0; pNew->disallowOrderBy = 0; pNew->pRightmost = 0; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; |
︙ | ︙ | |||
1014 1015 1016 1017 1018 1019 1020 1021 1022 | /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ int sqlite3ExprIsInteger(Expr *p, int *pValue){ switch( p->op ){ case TK_INTEGER: { | > > > > > | < < | | > > > > > | | 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 | /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; if( p->flags & EP_IntValue ){ *pValue = p->iTable; return 1; } switch( p->op ){ case TK_INTEGER: { rc = sqlite3GetInt32((char*)p->token.z, pValue); break; } case TK_UPLUS: { rc = sqlite3ExprIsInteger(p->pLeft, pValue); } case TK_UMINUS: { int v; if( sqlite3ExprIsInteger(p->pLeft, &v) ){ *pValue = -v; rc = 1; } break; } default: break; } if( rc ){ p->op = TK_INTEGER; p->flags |= EP_IntValue; p->iTable = *pValue; } return rc; } /* ** Return TRUE if the given string is a row-id column name. */ int sqlite3IsRowid(const char *z){ if( sqlite3StrICmp(z, "_ROWID_")==0 ) return 1; |
︙ | ︙ | |||
1982 1983 1984 1985 1986 1987 1988 | ** Generate an instruction that will put the integer describe by ** text z[0..n-1] into register iMem. ** ** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ | | > > > > | | > | 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 | ** Generate an instruction that will put the integer describe by ** text z[0..n-1] into register iMem. ** ** The z[] string will probably not be zero-terminated. But the ** z[n] character is guaranteed to be something that does not look ** like the continuation of the number. */ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ const char *z; if( pExpr->flags & EP_IntValue ){ int i = pExpr->iTable; if( negFlag ) i = -i; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); }else if( (z = (char*)pExpr->token.z)!=0 ){ int i; int n = pExpr->token.n; assert( !isdigit(z[n]) ); if( sqlite3GetInt32(z, &i) ){ if( negFlag ) i = -i; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); }else if( sqlite3FitsIn64Bits(z, negFlag) ){ i64 value; char *zV; |
︙ | ︙ | |||
2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 | for(i=0; i<pParse->nColCache; i++){ int x = pParse->aColCache[i].iReg; if( x>=iFrom && x<iFrom+nReg ){ pParse->aColCache[i].iReg += iTo-iFrom; } } } /* ** Return true if any register in the range iFrom..iTo (inclusive) ** is used as part of the column cache. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; | > > > > > > > > > > > > | 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 | for(i=0; i<pParse->nColCache; i++){ int x = pParse->aColCache[i].iReg; if( x>=iFrom && x<iFrom+nReg ){ pParse->aColCache[i].iReg += iTo-iFrom; } } } /* ** Generate code to copy content from registers iFrom...iFrom+nReg-1 ** over to iTo..iTo+nReg-1. */ void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){ int i; if( iFrom==iTo ) return; for(i=0; i<nReg; i++){ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i); } } /* ** Return true if any register in the range iFrom..iTo (inclusive) ** is used as part of the column cache. */ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){ int i; |
︙ | ︙ | |||
2242 2243 2244 2245 2246 2247 2248 | inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, pExpr->iTable, target, pExpr->flags & EP_AnyAff); } break; } case TK_INTEGER: { | | | 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 | inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab, pExpr->iColumn, pExpr->iTable, target, pExpr->flags & EP_AnyAff); } break; } case TK_INTEGER: { codeInteger(v, pExpr, 0, target); break; } case TK_FLOAT: { codeReal(v, (char*)pExpr->token.z, pExpr->token.n, 0, target); break; } case TK_STRING: { |
︙ | ︙ | |||
2380 2381 2382 2383 2384 2385 2386 | testcase( regFree2==0 ); break; } case TK_UMINUS: { Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ | < | | | 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 | testcase( regFree2==0 ); break; } case TK_UMINUS: { Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT || pLeft->op==TK_INTEGER ){ if( pLeft->op==TK_FLOAT ){ codeReal(v, (char*)pLeft->token.z, pLeft->token.n, 1, target); }else{ codeInteger(v, pLeft, 1, target); } }else{ regFree1 = r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_Integer, 0, r1); r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2); sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target); testcase( regFree2==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.242 2008/06/24 00:32:35 drh Exp $ */ #include "sqliteInt.h" /* ** Set P4 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: |
︙ | ︙ | |||
519 520 521 522 523 524 525 | ** the SELECT completes, it sets the EOF flag stored in regEof. */ int rc, j1; regEof = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ VdbeComment((v, "SELECT eof flag")); | | < | | | 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 545 | ** the SELECT completes, it sets the EOF flag stored in regEof. */ int rc, j1; regEof = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, regEof); /* EOF <- 0 */ VdbeComment((v, "SELECT eof flag")); sqlite3SelectDestInit(&dest, SRT_Coroutine, ++pParse->nMem); addrSelect = sqlite3VdbeCurrentAddr(v)+2; sqlite3VdbeAddOp2(v, OP_Integer, addrSelect-1, dest.iParm); j1 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); VdbeComment((v, "Jump over SELECT coroutine")); /* 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; } sqlite3VdbeAddOp2(v, OP_Integer, 1, regEof); /* EOF <- 1 */ sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); /* yield X */ sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_INTERNAL, OE_Abort); VdbeComment((v, "End of SELECT coroutine")); sqlite3VdbeJumpHere(v, j1); /* label B: */ regFromSelect = dest.iMem; assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; |
︙ | ︙ | |||
576 577 578 579 580 581 582 | int addrTop; /* Label "L" */ int addrIf; /* Address of jump to M */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); | | | 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 | int addrTop; /* Label "L" */ int addrIf; /* Address of jump to M */ srcTab = pParse->nTab++; regRec = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); addrTop = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); addrIf = sqlite3VdbeAddOp1(v, OP_If, regEof); sqlite3VdbeAddOp3(v, OP_MakeRecord, regFromSelect, nColumn, regRec); sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); sqlite3VdbeJumpHere(v, addrIf); sqlite3ReleaseTempReg(pParse, regRec); |
︙ | ︙ | |||
721 722 723 724 725 726 727 | ** ** C: yield X ** if EOF goto D ** insert the select result into <table> from R..R+n ** goto C ** D: ... */ | | | 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 | ** ** C: yield X ** if EOF goto D ** insert the select result into <table> from R..R+n ** goto C ** D: ... */ addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iParm); addrInsTop = sqlite3VdbeAddOp1(v, OP_If, regEof); } /* Allocate registers for holding the rowid of the new row, ** the content of the new row, and the assemblied row record. */ regRecord = ++pParse->nMem; |
︙ | ︙ |
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.434 2008/06/24 00:32:36 drh Exp $ */ #include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. |
︙ | ︙ | |||
35 36 37 38 39 40 41 | /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = eDest; pDest->iParm = iParm; | < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = eDest; pDest->iParm = iParm; pDest->affinity = 0; pDest->iMem = 0; pDest->nMem = 0; } /* |
︙ | ︙ | |||
81 82 83 84 85 86 87 | pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->isDistinct = isDistinct; pNew->op = TK_SELECT; assert( pOffset==0 || pLimit!=0 ); pNew->pLimit = pLimit; pNew->pOffset = pOffset; | < < | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | pNew->pHaving = pHaving; pNew->pOrderBy = pOrderBy; pNew->isDistinct = isDistinct; pNew->op = TK_SELECT; assert( pOffset==0 || pLimit!=0 ); pNew->pLimit = pLimit; pNew->pOffset = pOffset; pNew->addrOpenEphm[0] = -1; pNew->addrOpenEphm[1] = -1; pNew->addrOpenEphm[2] = -1; if( pNew==&standin) { clearSelect(pNew); pNew = 0; } |
︙ | ︙ | |||
426 427 428 429 430 431 432 | sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); | | | | | 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 | sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr); sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nExpr+2); if( pSelect->iLimit ){ int addr1, addr2; int iLimit; if( pSelect->pOffset ){ iLimit = pSelect->iOffset+1; }else{ iLimit = pSelect->iLimit; } addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); addr2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor); sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor); sqlite3VdbeJumpHere(v, addr2); pSelect->iLimit = 0; } } /* ** Add code to implement the OFFSET */ static void codeOffset( Vdbe *v, /* Generate code into this VM */ Select *p, /* The SELECT statement being coded */ int iContinue /* Jump here to skip the current record */ ){ if( p->iOffset && iContinue!=0 ){ int addr; sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1); addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); VdbeComment((v, "skip OFFSET records")); sqlite3VdbeJumpHere(v, addr); } |
︙ | ︙ | |||
708 709 710 711 712 713 714 | case SRT_Callback: { if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Coroutine ){ | | | 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 | case SRT_Callback: { if( pOrderBy ){ int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); }else{ sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); } break; } |
︙ | ︙ | |||
731 732 733 734 735 736 737 | break; } #endif } /* Jump to the end of the loop if the LIMIT is reached. */ | | | 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | break; } #endif } /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit && pOrderBy==0 ){ sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak); } } /* ** Given an expression list, generate a KeyInfo structure that records |
︙ | ︙ | |||
855 856 857 858 859 860 861 | assert( regRow!=pDest->iMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); } if( eDest==SRT_Callback ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); }else if( eDest==SRT_Coroutine ){ | | | | 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 | assert( regRow!=pDest->iMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); } if( eDest==SRT_Callback ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); }else if( eDest==SRT_Coroutine ){ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); } break; } default: { /* Do nothing */ break; } } sqlite3ReleaseTempReg(pParse, regRow); sqlite3ReleaseTempReg(pParse, regRowid); /* Jump to the end of the loop when the LIMIT is reached */ if( p->iLimit ){ sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, brk); } /* The bottom of the loop */ sqlite3VdbeResolveLabel(v, cont); |
︙ | ︙ | |||
1504 1505 1506 1507 1508 1509 1510 | return rc; } /* ** pE is a pointer to an expression which is a single term in ** ORDER BY or GROUP BY clause. ** | > | < | | 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 | return rc; } /* ** pE is a pointer to an expression which is a single term in ** ORDER BY or GROUP BY clause. ** ** At the point this routine is called, we already know that the ** ORDER BY term is not an integer index into the result set. That ** casee is handled by the calling routine. ** ** If pE is a well-formed expression and the SELECT statement ** is not compound, then return 0. This indicates to the ** caller that it should sort by the value of the ORDER BY ** expression. ** ** If the SELECT is compound, then attempt to match pE against |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 | int isCompound, /* True if this is a compound SELECT */ u8 *pHasAgg /* True if expression contains aggregate functions */ ){ int i; /* Loop counter */ ExprList *pEList; /* The columns of the result set */ NameContext nc; /* Name context for resolving pE */ | | < < < < < < < < < < < < | 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | int isCompound, /* True if this is a compound SELECT */ u8 *pHasAgg /* True if expression contains aggregate functions */ ){ int i; /* Loop counter */ ExprList *pEList; /* The columns of the result set */ NameContext nc; /* Name context for resolving pE */ assert( sqlite3ExprIsInteger(pE, &i)==0 ); pEList = pSelect->pEList; /* If the term is a simple identifier that try to match that identifier ** against a column name in the result set. */ if( pE->op==TK_ID || (pE->op==TK_STRING && pE->token.z[0]!='\'') ){ sqlite3 *db = pParse->db; char *zCol = sqlite3NameFromToken(db, &pE->token); |
︙ | ︙ | |||
1634 1635 1636 1637 1638 1639 1640 | pEList = pSelect->pEList; if( pEList==0 ){ return 0; } for(i=0; i<pOrderBy->nExpr; i++){ int iCol; Expr *pE = pOrderBy->a[i].pExpr; | < | < < | | | | | | > > > > > > | | | > | < | 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 | pEList = pSelect->pEList; if( pEList==0 ){ return 0; } for(i=0; i<pOrderBy->nExpr; i++){ int iCol; Expr *pE = pOrderBy->a[i].pExpr; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ const char *zType = isOrder ? "ORDER" : "GROUP"; sqlite3ErrorMsg(pParse, "%r %s BY term out of range - should be " "between 1 and %d", i+1, zType, pEList->nExpr); return 1; } }else{ iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 0, pHasAgg); if( iCol<0 ){ return 1; } } if( iCol>0 ){ CollSeq *pColl = pE->pColl; int flags = pE->flags & EP_ExpCollate; sqlite3ExprDelete(pE); pE = sqlite3ExprDup(db, pEList->a[iCol-1].pExpr); pOrderBy->a[i].pExpr = pE; if( pE && pColl && flags ){ pE->pColl = pColl; pE->flags |= flags; } } } return 0; } /* ** Analyze and ORDER BY or GROUP BY clause in a SELECT statement. Return ** the number of errors seen. ** ** If iTable>0 then make the N-th term of the ORDER BY clause refer to ** the N-th column of table iTable. ** ** If iTable==0 then transform each term of the ORDER BY clause to refer ** to a column of the result set by number. */ static int processCompoundOrderBy( Parse *pParse, /* Parsing context. Leave error messages here */ Select *pSelect, /* The SELECT statement containing the ORDER BY */ int iTable /* Output table for compound SELECT statements */ ){ int i; |
︙ | ︙ | |||
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 | pOrderBy->a[i].done = 0; } while( pSelect->pPrior ){ pSelect = pSelect->pPrior; } while( pSelect && moreToDo ){ moreToDo = 0; for(i=0; i<pOrderBy->nExpr; i++){ int iCol = -1; Expr *pE, *pDup; if( pOrderBy->a[i].done ) continue; pE = pOrderBy->a[i].pExpr; | > > > > > > > > > > > > | | | | | | | | | < < < | < < < < < | | | | | | > > > > > | 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 | pOrderBy->a[i].done = 0; } while( pSelect->pPrior ){ pSelect = pSelect->pPrior; } while( pSelect && moreToDo ){ moreToDo = 0; pEList = pSelect->pEList; if( pEList==0 ){ return 1; } for(i=0; i<pOrderBy->nExpr; i++){ int iCol = -1; Expr *pE, *pDup; if( pOrderBy->a[i].done ) continue; pE = pOrderBy->a[i].pExpr; if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<0 || iCol>pEList->nExpr ){ sqlite3ErrorMsg(pParse, "%r ORDER BY term out of range - should be " "between 1 and %d", i+1, pEList->nExpr); return 1; } }else{ pDup = sqlite3ExprDup(db, pE); if( !db->mallocFailed ){ assert(pDup); iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0); } sqlite3ExprDelete(pDup); if( iCol<0 ){ return 1; } } if( iCol>0 ){ if( iTable ){ pE->op = TK_COLUMN; pE->iTable = iTable; pE->iAgg = -1; pE->iColumn = iCol-1; pE->pTab = 0; }else{ pE->op = TK_INTEGER; pE->flags |= EP_IntValue; pE->iTable = iCol; } pOrderBy->a[i].done = 1; }else{ moreToDo = 1; } } pSelect = pSelect->pNext; } |
︙ | ︙ | |||
1985 1986 1987 1988 1989 1990 1991 | p->pOffset = 0; if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; | | | 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 | p->pOffset = 0; if( rc ){ goto multi_select_end; } p->pPrior = 0; p->iLimit = pPrior->iLimit; p->iOffset = pPrior->iOffset; if( p->iLimit ){ addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); 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; |
︙ | ︙ | |||
2071 2072 2073 2074 2075 2076 2077 | ** 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; | | | | 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 | ** 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 = 0; p->iOffset = 0; if( rc ){ goto multi_select_end; } /* Convert the data in the temporary table into whatever form ** it is that we currently need. |
︙ | ︙ | |||
2309 2310 2311 2312 2313 2314 2315 | multi_select_end: pDest->iMem = dest.iMem; pDest->nMem = dest.nMem; return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ | < | > | | > > > > | < | | < > | | | | | > | | | | | | | | | > | > > | > > | > | | < > > > > > > > > > > > > > > > > > > | 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 | multi_select_end: pDest->iMem = dest.iMem; pDest->nMem = dest.nMem; return rc; } #endif /* SQLITE_OMIT_COMPOUND_SELECT */ /* ** Code an output subroutine for a coroutine implementation of a ** SELECT statment. */ static int outputSubroutine( Parse *pParse, /* Parsing context */ Select *p, /* The SELECT statement */ SelectDest *pIn, /* Coroutine supplying data */ SelectDest *pDest, /* Where to send the data */ int regReturn, /* The return address register */ int iBreak /* Jump here if we hit the LIMIT */ ){ Vdbe *v = pParse->pVdbe; int iContinue; int addr; if( v==0 ) return 0; addr = sqlite3VdbeCurrentAddr(v); iContinue = sqlite3VdbeMakeLabel(v); codeOffset(v, p, iContinue); switch( pDest->eDest ){ /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1); sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); sqlite3ReleaseTempReg(pParse, r1); break; } #ifndef SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int addr2, r1; assert( pIn->nMem==1 ); addr2 = sqlite3VdbeAddOp1(v, OP_IsNull, pIn->iMem); p->affinity = sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1); sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iParm, r1); sqlite3ReleaseTempReg(pParse, r1); sqlite3VdbeJumpHere(v, addr2); break; } /* If any row exist in the result set, record that fact and abort. */ case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iParm); /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Mem: { assert( pIn->nMem==1 ); sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; } #endif /* #ifndef SQLITE_OMIT_SUBQUERY */ /* Send the data to the callback function or to a subroutine. In the ** case of a subroutine, the subroutine itself is responsible for ** popping the data from the stack. */ case SRT_Coroutine: { if( pDest->iMem==0 ){ pDest->iMem = sqlite3GetTempRange(pParse, pIn->nMem); pDest->nMem = pIn->nMem; } sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem); sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); break; } case SRT_Callback: { sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem); sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem); break; } #if !defined(SQLITE_OMIT_TRIGGER) /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call ** user-defined functions that have side effects. We do not care ** about the actual results of the select. */ default: { break; } #endif } /* Jump to the end of the loop if the LIMIT is reached. */ if( p->iLimit ){ sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak); } /* Advance the coroutine to its next value. */ sqlite3VdbeResolveLabel(v, iContinue); sqlite3VdbeAddOp1(v, OP_Yield, pIn->iParm); /* Generate the subroutine return */ sqlite3VdbeAddOp1(v, OP_Return, regReturn); return addr; } /* ** Alternative compound select code generator for cases when there ** is an ORDER BY clause. ** ** We assume a query of the following form: |
︙ | ︙ | |||
2494 2495 2496 2497 2498 2499 2500 | */ static int multiSelectOrderBy( 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 */ ){ | < < < < < | | | | | | | | | | | | | | | > > > > | | | > > > > | > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < > | | > > > < > > > > | > > | > > > > | > > > > | > > > | > > | < < < < | < | > > | > > > > | < | | > | | | > > > > > > > > > > > | < < < < < < < < < > > | > > < | > > > > > | < | | | | > | | | | > > > > | | > > > | | > | > > | | < > > > | | > | > > > | > > > > > > | | > > > > > > > > > > > | 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 | */ static int multiSelectOrderBy( 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 */ ){ Select *pPrior; /* Another SELECT immediately to our left */ Vdbe *v; /* Generate code to this VDBE */ SelectDest destA; /* Destination for coroutine A */ SelectDest destB; /* Destination for coroutine B */ int regAddrA; /* Address register for select-A coroutine */ int regEofA; /* Flag to indicate when select-A is complete */ int regAddrB; /* Address register for select-B coroutine */ int regEofB; /* Flag to indicate when select-B is complete */ int addrSelectA; /* Address of the select-A coroutine */ int addrSelectB; /* Address of the select-B coroutine */ int regOutA; /* Address register for the output-A subroutine */ int regOutB; /* Address register for the output-B subroutine */ int addrOutA; /* Address of the output-A subroutine */ int addrOutB; /* Address of the output-B subroutine */ int addrEofA; /* Address of the select-A-exhausted subroutine */ int addrEofB; /* Address of the select-B-exhausted subroutine */ int addrAltB; /* Address of the A<B subroutine */ int addrAeqB; /* Address of the A==B subroutine */ int addrAgtB; /* Address of the A>B subroutine */ int regLimitA; /* Limit register for select-A */ int regLimitB; /* Limit register for select-A */ int savedLimit; /* Saved value of p->iLimit */ int savedOffset; /* Saved value of p->iOffset */ int labelCmpr; /* Label for the start of the merge algorithm */ int labelEnd; /* Label for the end of the overall SELECT stmt */ int j1, j2, j3; /* Jump instructions that get retargetted */ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ KeyInfo *pKeyInfo; /* Type data for comparisons */ int p4type; /* P4 type used for pKeyInfo */ u8 NotUsed; /* Dummy variable */ assert( p->pOrderBy!=0 ); v = pParse->pVdbe; if( v==0 ) return SQLITE_NOMEM; labelEnd = sqlite3VdbeMakeLabel(v); labelCmpr = sqlite3VdbeMakeLabel(v); pKeyInfo = keyInfoFromExprList(pParse, p->pEList); p4type = P4_KEYINFO_HANDOFF; /* Patch up the ORDER BY clause */ op = p->op; pPrior = p->pPrior; assert( pPrior->pOrderBy==0 ); if( processCompoundOrderBy(pParse, p, 0) ){ return SQLITE_ERROR; } pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy); /* Separate the left and the right query from one another */ p->pPrior = 0; pPrior->pRightmost = 0; processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed); processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed); /* Compute the limit registers */ computeLimitRegisters(pParse, p, labelEnd); if( p->iLimit ){ regLimitA = ++pParse->nMem; regLimitB = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit, regLimitA); sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB); }else{ regLimitA = regLimitB = 0; } regAddrA = ++pParse->nMem; regEofA = ++pParse->nMem; regAddrB = ++pParse->nMem; regEofB = ++pParse->nMem; regOutA = ++pParse->nMem; regOutB = ++pParse->nMem; sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB); /* Jump past the various subroutines and coroutines to the main ** merge loop */ j1 = sqlite3VdbeAddOp0(v, OP_Goto); addrSelectA = sqlite3VdbeCurrentAddr(v); /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. */ VdbeNoopComment((v, "Begin coroutine for left SELECT")); pPrior->iLimit = regLimitA; sqlite3Select(pParse, pPrior, &destA, 0, 0, 0, 0); sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA); sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); VdbeNoopComment((v, "End coroutine for left SELECT")); /* Generate a coroutine to evaluate the SELECT statement on ** the right - the "B" select */ addrSelectB = sqlite3VdbeCurrentAddr(v); VdbeNoopComment((v, "Begin coroutine for right SELECT")); savedLimit = p->iLimit; savedOffset = p->iOffset; p->iLimit = regLimitB; p->iOffset = 0; sqlite3Select(pParse, p, &destB, 0, 0, 0, 0); p->iLimit = savedLimit; p->iOffset = savedOffset; sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB); sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); VdbeNoopComment((v, "End coroutine for right SELECT")); /* Generate a subroutine that outputs the current row of the A ** select as the next output row of the compound select and then ** advances the A select to its next row */ VdbeNoopComment((v, "Output routine for A")); addrOutA = outputSubroutine(pParse, p, &destA, pDest, regOutA, labelEnd); /* Generate a subroutine that outputs the current row of the B ** select as the next output row of the compound select and then ** advances the B select to its next row */ VdbeNoopComment((v, "Output routine for B")); addrOutB = outputSubroutine(pParse, p, &destB, pDest, regOutB, labelEnd); /* Generate a subroutine to run when the results from select A ** are exhausted and only data in select B remains. */ VdbeNoopComment((v, "eof-A subroutine")); addrEofA = sqlite3VdbeCurrentAddr(v); if( op==TK_EXCEPT || op==TK_INTERSECT ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd); }else{ if( op==TK_ALL ){ j2 = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd); sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); }else{ assert( op==TK_UNION ); sqlite3ExprCodeCopy(pParse, destB.iMem, destA.iMem, destB.nMem); j2 = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd); sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destB.nMem, (char*)pKeyInfo, p4type); p4type = P4_KEYINFO_STATIC; sqlite3VdbeAddOp3(v, OP_Jump, j2, j2+4, j2); sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); sqlite3VdbeAddOp2(v, OP_Goto, 0, j2+1); } } /* Generate a subroutine to run when the results from select B ** are exhausted and only data in select A remains. */ if( op==TK_INTERSECT ){ addrEofB = addrEofA; }else{ VdbeNoopComment((v, "eof-B subroutine")); addrEofB = sqlite3VdbeCurrentAddr(v); if( op==TK_ALL || op==TK_EXCEPT ){ j2 = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); sqlite3VdbeAddOp2(v, OP_Goto, 0, j2); }else{ assert( op==TK_UNION ); sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); sqlite3ExprCodeCopy(pParse, destA.iMem, destB.iMem, destA.nMem); j2 = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destB.nMem, (char*)pKeyInfo, p4type); p4type = P4_KEYINFO_STATIC; sqlite3VdbeAddOp3(v, OP_Jump, j2, j2+4, j2); sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); sqlite3VdbeAddOp2(v, OP_Goto, 0, j2+1); } } /* Generate code to handle the case of A<B */ VdbeNoopComment((v, "A-lt-B subroutine")); addrAltB = sqlite3VdbeCurrentAddr(v); if( op==TK_INTERSECT ){ sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); }else{ sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); } sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* Generate code to handle the case of A==B */ if( op==TK_ALL ){ addrAeqB = addrAltB; }else{ VdbeNoopComment((v, "A-eq-B subroutine")); addrAeqB = sqlite3VdbeCurrentAddr(v); if( op==TK_INTERSECT ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); j2 = sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destA.nMem, (char*)pKeyInfo, p4type); p4type = P4_KEYINFO_STATIC; j3 = sqlite3VdbeCurrentAddr(v)+1; sqlite3VdbeAddOp3(v, OP_Jump, j3, j2, j3); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); }else{ sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); } } /* Generate code to handle the case of A>B */ VdbeNoopComment((v, "A-gt-B subroutine")); addrAgtB = sqlite3VdbeCurrentAddr(v); if( op==TK_ALL || op==TK_UNION ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); }else{ sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); } sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA); sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB); sqlite3VdbeAddOp2(v, OP_Integer, addrSelectB, regAddrB); sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA); sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destA.nMem, (char*)pKeyInfo, p4type); p4type = P4_KEYINFO_STATIC; sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Jump to the this point in order to terminate the query. */ sqlite3VdbeResolveLabel(v, labelEnd); /* Set the number of output columns */ if( pDest->eDest==SRT_Callback ){ Select *pFirst = p; while( pFirst->pPrior ) pFirst = pFirst->pPrior; generateColumnNames(pParse, 0, pFirst->pEList); } /* Free the KeyInfo if unused. */ if( p4type==P4_KEYINFO_HANDOFF ){ sqlite3_free(pKeyInfo); } /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ return SQLITE_OK; } #ifndef SQLITE_OMIT_VIEW /* Forward Declarations */ static void substExprList(sqlite3*, ExprList*, int, ExprList*); static void substSelect(sqlite3*, Select *, int, ExprList *); /* |
︙ | ︙ |
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.725 2008/06/24 00:32:36 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build |
︙ | ︙ | |||
1157 1158 1159 1160 1161 1162 1163 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_Dequoted 0x0040 /* True if the string has been dequoted */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ #define EP_FixedDest 0x0400 /* Result needed in a specific register */ | | | 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 | #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_Dequoted 0x0040 /* True if the string has been dequoted */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ #define EP_FixedDest 0x0400 /* Result needed in a specific register */ #define EP_IntValue 0x0800 /* Integer value contained in iTable */ /* ** These macros can be used to test, set, or clear bits in the ** Expr.flags field. */ #define ExprHasProperty(E,P) (((E)->flags&(P))==(P)) #define ExprHasAnyProperty(E,P) (((E)->flags&(P))!=0) #define ExprSetProperty(E,P) (E)->flags|=(P) |
︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 | ** comments above sqlite3Select() for details. */ typedef struct SelectDest SelectDest; struct SelectDest { u8 eDest; /* How to dispose of the results */ u8 affinity; /* Affinity used when eDest==SRT_Set */ int iParm; /* A parameter used by the eDest disposal method */ | < < | 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 | ** comments above sqlite3Select() for details. */ typedef struct SelectDest SelectDest; struct SelectDest { u8 eDest; /* How to dispose of the results */ u8 affinity; /* Affinity used when eDest==SRT_Set */ int iParm; /* A parameter used by the eDest disposal method */ int iMem; /* Base register where results are written */ int nMem; /* Number of registers allocated */ }; /* ** 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. ** |
︙ | ︙ | |||
1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 | void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprCacheAffinityChange(Parse*, int, int); int sqlite3ExprWritableRegister(Parse*,int,int); void sqlite3ExprHardCopy(Parse*,int,int); int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); | > | 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 | void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8); void sqlite3WhereEnd(WhereInfo*); int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCodeCopy(Parse*, int, int, int); void sqlite3ExprClearColumnCache(Parse*, int); void sqlite3ExprCacheAffinityChange(Parse*, int, int); int sqlite3ExprWritableRegister(Parse*,int,int); void sqlite3ExprHardCopy(Parse*,int,int); int sqlite3ExprCode(Parse*, Expr*, int); int sqlite3ExprCodeTemp(Parse*, Expr*, int*); int sqlite3ExprCodeTarget(Parse*, Expr*, int); |
︙ | ︙ |
Changes to test/select1.test.
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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # | | | 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. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # # $Id: select1.test,v 1.59 2008/06/24 00:32:36 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Try to select on a non-existant table. # do_test select1-1.1 { |
︙ | ︙ | |||
540 541 542 543 544 545 546 547 548 549 550 551 552 553 | execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY 1 DESC LIMIT 1) } } {d} do_test select1-6.22 { execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY b LIMIT 2) ORDER BY a; } } {a b} | > | 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 | execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY 1 DESC LIMIT 1) } } {d} do_test select1-6.22 { breakpoint execsql { SELECT a FROM t6 WHERE b IN (SELECT b FROM t6 WHERE a<='b' UNION SELECT '3' AS x ORDER BY b LIMIT 2) ORDER BY a; } } {a b} |
︙ | ︙ | |||
928 929 930 931 932 933 934 | do_test select1-14.2 { execsql { SELECT 10 IN (SELECT rowid FROM sqlite_master); } } {0} finish_test | < | 929 930 931 932 933 934 935 | do_test select1-14.2 { execsql { SELECT 10 IN (SELECT rowid FROM sqlite_master); } } {0} finish_test |