Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5)

Unified Diff: third_party/sqlite/src/src/select.c

Issue 2751253002: [sql] Import SQLite 3.17.0. (Closed)
Patch Set: also clang on Linux i386 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/sqlite/src/src/rowset.c ('k') | third_party/sqlite/src/src/shell.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/sqlite/src/src/select.c
diff --git a/third_party/sqlite/src/src/select.c b/third_party/sqlite/src/src/select.c
index 85f8518cf1c38f0cc49dc159a726dfef1a204540..d817ebd074f39c616d5287af89cd2397655dc061 100644
--- a/third_party/sqlite/src/src/select.c
+++ b/third_party/sqlite/src/src/select.c
@@ -56,6 +56,7 @@ struct SortCtx {
int addrSortIndex; /* Address of the OP_SorterOpen or OP_OpenEphemeral */
int labelDone; /* Jump here when done, ex: LIMIT reached */
u8 sortFlags; /* Zero or more SORTFLAG_* bits */
+ u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */
};
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
@@ -74,7 +75,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
sqlite3ExprListDelete(db, p->pOrderBy);
sqlite3ExprDelete(db, p->pLimit);
sqlite3ExprDelete(db, p->pOffset);
- sqlite3WithDelete(db, p->pWith);
+ if( p->pWith ) sqlite3WithDelete(db, p->pWith);
if( bFree ) sqlite3DbFree(db, p);
p = pPrior;
bFree = 1;
@@ -87,7 +88,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
pDest->eDest = (u8)eDest;
pDest->iSDParm = iParm;
- pDest->affSdst = 0;
+ pDest->zAffSdst = 0;
pDest->iSdst = 0;
pDest->nSdst = 0;
}
@@ -105,36 +106,44 @@ Select *sqlite3SelectNew(
ExprList *pGroupBy, /* the GROUP BY clause */
Expr *pHaving, /* the HAVING clause */
ExprList *pOrderBy, /* the ORDER BY clause */
- u16 selFlags, /* Flag parameters, such as SF_Distinct */
+ u32 selFlags, /* Flag parameters, such as SF_Distinct */
Expr *pLimit, /* LIMIT value. NULL means not used */
Expr *pOffset /* OFFSET value. NULL means no offset */
){
Select *pNew;
Select standin;
sqlite3 *db = pParse->db;
- pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
+ pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew) );
if( pNew==0 ){
assert( db->mallocFailed );
pNew = &standin;
- memset(pNew, 0, sizeof(*pNew));
}
if( pEList==0 ){
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0));
}
pNew->pEList = pEList;
+ pNew->op = TK_SELECT;
+ pNew->selFlags = selFlags;
+ pNew->iLimit = 0;
+ pNew->iOffset = 0;
+#if SELECTTRACE_ENABLED
+ pNew->zSelName[0] = 0;
+#endif
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->nSelectRow = 0;
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc));
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
- pNew->selFlags = selFlags;
- pNew->op = TK_SELECT;
+ pNew->pPrior = 0;
+ pNew->pNext = 0;
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
+ pNew->pWith = 0;
assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
- pNew->addrOpenEphm[0] = -1;
- pNew->addrOpenEphm[1] = -1;
if( db->mallocFailed ) {
clearSelect(db, pNew, pNew!=&standin);
pNew = 0;
@@ -161,7 +170,7 @@ void sqlite3SelectSetName(Select *p, const char *zName){
** Delete the given Select structure and all of its substructures.
*/
void sqlite3SelectDelete(sqlite3 *db, Select *p){
- clearSelect(db, p, 1);
+ if( p ) clearSelect(db, p, 1);
}
/*
@@ -325,7 +334,7 @@ static void addWhereTerm(
pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
- pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
+ pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2);
if( pEq && isOuterJoin ){
ExprSetProperty(pEq, EP_FromJoin);
assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) );
@@ -512,7 +521,7 @@ static void pushOntoSorter(
int iLimit; /* LIMIT counter */
assert( bSeq==0 || bSeq==1 );
- assert( nData==1 || regData==regOrigData );
+ assert( nData==1 || regData==regOrigData || regOrigData==0 );
if( nPrefixReg ){
assert( nPrefixReg==nExpr+bSeq );
regBase = regData - nExpr - bSeq;
@@ -524,11 +533,11 @@ static void pushOntoSorter(
iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
pSort->labelDone = sqlite3VdbeMakeLabel(v);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
- SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
+ SQLITE_ECEL_DUP | (regOrigData? SQLITE_ECEL_REF : 0));
if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
- if( nPrefixReg==0 ){
+ if( nPrefixReg==0 && nData>0 ){
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
@@ -578,12 +587,34 @@ static void pushOntoSorter(
}else{
op = OP_IdxInsert;
}
- sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
+ sqlite3VdbeAddOp4Int(v, op, pSort->iECursor, regRecord,
+ regBase+nOBSat, nBase-nOBSat);
if( iLimit ){
int addr;
- addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
+ int r1 = 0;
+ /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit
+ ** register is initialized with value of LIMIT+OFFSET.) After the sorter
+ ** fills up, delete the least entry in the sorter after each insert.
+ ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */
+ addr = sqlite3VdbeAddOp1(v, OP_IfNotZero, iLimit); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
+ if( pSort->bOrderedInnerLoop ){
+ r1 = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1);
+ VdbeComment((v, "seq"));
+ }
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
+ if( pSort->bOrderedInnerLoop ){
+ /* If the inner loop is driven by an index such that values from
+ ** the same iteration of the inner loop are in sorted order, then
+ ** immediately jump to the next iteration of an inner loop if the
+ ** entry from the current iteration does not fit into the top
+ ** LIMIT+OFFSET entries of the sorter. */
+ int iBrk = sqlite3VdbeCurrentAddr(v) + 2;
+ sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1);
+ sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
+ VdbeCoverage(v);
+ }
sqlite3VdbeJumpHere(v, addr);
}
}
@@ -625,34 +656,11 @@ static void codeDistinct(
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4Int(v, OP_Found, iTab, addrRepeat, iMem, N); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r1, iMem, N);
+ sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, r1);
}
-#ifndef SQLITE_OMIT_SUBQUERY
-/*
-** 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 used to occur
-** in multiple places. (The error only occurs in one place now, but we
-** retain the subroutine to minimize code disruption.)
-*/
-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;
- }
-}
-#endif
-
/*
** This routine generates the code for the inside of the inner loop
** of a SELECT.
@@ -660,7 +668,7 @@ static int checkForMultiColumnSelectError(
** If srcTab is negative, then the pEList expressions
** are evaluated in order to get the data for this row. If srcTab is
** zero or more, then data is pulled from srcTab and pEList is used only
-** to get number columns and the datatype for each column.
+** to get the number of columns and the collation sequence for each column.
*/
static void selectInnerLoop(
Parse *pParse, /* The parser context */
@@ -675,13 +683,20 @@ static void selectInnerLoop(
){
Vdbe *v = pParse->pVdbe;
int i;
- int hasDistinct; /* True if the DISTINCT keyword is present */
- int regResult; /* Start of memory holding result set */
+ int hasDistinct; /* True if the DISTINCT keyword is present */
int eDest = pDest->eDest; /* How to dispose of results */
int iParm = pDest->iSDParm; /* First argument to disposal method */
int nResultCol; /* Number of result columns */
int nPrefixReg = 0; /* Number of extra registers before regResult */
+ /* Usually, regResult is the first cell in an array of memory cells
+ ** containing the current result row. In this case regOrig is set to the
+ ** same value. However, if the results are being sent to the sorter, the
+ ** values for any expressions that are also part of the sort-key are omitted
+ ** from this array. In this case regOrig is set to zero. */
+ int regResult; /* Start of memory holding current results */
+ int regOrig; /* Start of memory holding full result (or 0) */
+
assert( v );
assert( pEList!=0 );
hasDistinct = pDistinct ? pDistinct->eTnctType : WHERE_DISTINCT_NOOP;
@@ -712,7 +727,7 @@ static void selectInnerLoop(
pParse->nMem += nResultCol;
}
pDest->nSdst = nResultCol;
- regResult = pDest->iSdst;
+ regOrig = regResult = pDest->iSdst;
if( srcTab>=0 ){
for(i=0; i<nResultCol; i++){
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
@@ -728,7 +743,25 @@ static void selectInnerLoop(
}else{
ecelFlags = 0;
}
- sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags);
+ if( pSort && hasDistinct==0 && eDest!=SRT_EphemTab && eDest!=SRT_Table ){
+ /* For each expression in pEList that is a copy of an expression in
+ ** the ORDER BY clause (pSort->pOrderBy), set the associated
+ ** iOrderByCol value to one more than the index of the ORDER BY
+ ** expression within the sort-key that pushOntoSorter() will generate.
+ ** This allows the pEList field to be omitted from the sorted record,
+ ** saving space and CPU cycles. */
+ ecelFlags |= (SQLITE_ECEL_OMITREF|SQLITE_ECEL_REF);
+ for(i=pSort->nOBSat; i<pSort->pOrderBy->nExpr; i++){
+ int j;
+ if( (j = pSort->pOrderBy->a[i].u.x.iOrderByCol)>0 ){
+ pEList->a[j-1].u.x.iOrderByCol = i+1-pSort->nOBSat;
+ }
+ }
+ regOrig = 0;
+ assert( eDest==SRT_Set || eDest==SRT_Mem
+ || eDest==SRT_Coroutine || eDest==SRT_Output );
+ }
+ nResultCol = sqlite3ExprCodeExprList(pParse,pEList,regResult,0,ecelFlags);
}
/* If the DISTINCT keyword was present on the SELECT statement
@@ -802,7 +835,7 @@ static void selectInnerLoop(
int r1;
r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -839,7 +872,7 @@ static void selectInnerLoop(
int addr = sqlite3VdbeCurrentAddr(v) + 4;
sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0);
VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm+1, r1,regResult,nResultCol);
assert( pSort==0 );
}
#endif
@@ -862,20 +895,20 @@ static void selectInnerLoop(
** item into the set table with bogus data.
*/
case SRT_Set: {
- assert( nResultCol==1 );
- pDest->affSdst =
- sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affSdst);
if( pSort ){
/* 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 */
- pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg);
+ pushOntoSorter(
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
int r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
- sqlite3ExprCacheAffinityChange(pParse, regResult, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ assert( sqlite3Strlen30(pDest->zAffSdst)==nResultCol );
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, nResultCol,
+ r1, pDest->zAffSdst, nResultCol);
+ sqlite3ExprCacheAffinityChange(pParse, regResult, nResultCol);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, nResultCol);
sqlite3ReleaseTempReg(pParse, r1);
}
break;
@@ -890,14 +923,16 @@ static void selectInnerLoop(
}
/* 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.
+ ** store the results in the appropriate memory cell or array of
+ ** memory cells and break out of the scan loop.
*/
case SRT_Mem: {
- assert( nResultCol==1 );
if( pSort ){
- pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg);
+ assert( nResultCol<=pDest->nSdst );
+ pushOntoSorter(
+ pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
+ assert( nResultCol==pDest->nSdst );
assert( regResult==iParm );
/* The LIMIT clause will jump out of the loop for us */
}
@@ -910,7 +945,7 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pSort ){
- pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol,
+ pushOntoSorter(pParse, pSort, p, regResult, regOrig, nResultCol,
nPrefixReg);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
@@ -960,7 +995,7 @@ static void selectInnerLoop(
}
sqlite3VdbeAddOp2(v, OP_Sequence, iParm, r2+nKey);
sqlite3VdbeAddOp3(v, OP_MakeRecord, r2, nKey+2, r1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, r2, nKey+2);
if( addrTest ) sqlite3VdbeJumpHere(v, addrTest);
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempRange(pParse, r2, nKey+2);
@@ -997,8 +1032,8 @@ static void selectInnerLoop(
** X extra columns.
*/
KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- KeyInfo *p = sqlite3DbMallocZero(0,
- sizeof(KeyInfo) + (N+X)*(sizeof(CollSeq*)+1));
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1);
+ KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
if( p ){
p->aSortOrder = (u8*)&p->aColl[N+X];
p->nField = (u16)N;
@@ -1006,8 +1041,9 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
p->enc = ENC(db);
p->db = db;
p->nRef = 1;
+ memset(&p[1], 0, nExtra);
}else{
- db->mallocFailed = 1;
+ sqlite3OomFault(db);
}
return p;
}
@@ -1019,7 +1055,7 @@ void sqlite3KeyInfoUnref(KeyInfo *p){
if( p ){
assert( p->nRef>0 );
p->nRef--;
- if( p->nRef==0 ) sqlite3DbFree(0, p);
+ if( p->nRef==0 ) sqlite3DbFree(p->db, p);
}
}
@@ -1194,14 +1230,13 @@ static void generateSortTail(
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
+ int iCol;
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
int i;
int bSeq; /* True if sorter record includes seq. no. */
-#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
struct ExprList_item *aOutEx = p->pEList->a;
-#endif
assert( addrBreak<0 );
if( pSort->labelBkOut ){
@@ -1210,21 +1245,21 @@ static void generateSortTail(
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
}
iTab = pSort->iECursor;
- if( eDest==SRT_Output || eDest==SRT_Coroutine ){
+ if( eDest==SRT_Output || eDest==SRT_Coroutine || eDest==SRT_Mem ){
regRowid = 0;
regRow = pDest->iSdst;
nSortData = nColumn;
}else{
regRowid = sqlite3GetTempReg(pParse);
- regRow = sqlite3GetTempReg(pParse);
- nSortData = 1;
+ regRow = sqlite3GetTempRange(pParse, nColumn);
+ nSortData = nColumn;
}
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->sortFlags & SORTFLAG_UseSorter ){
int regSortOut = ++pParse->nMem;
iSortTab = pParse->nTab++;
if( pSort->labelBkOut ){
- addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
+ addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
@@ -1239,11 +1274,18 @@ static void generateSortTail(
iSortTab = iTab;
bSeq = 1;
}
- for(i=0; i<nSortData; i++){
- sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
+ for(i=0, iCol=nKey+bSeq; i<nSortData; i++){
+ int iRead;
+ if( aOutEx[i].u.x.iOrderByCol ){
+ iRead = aOutEx[i].u.x.iOrderByCol-1;
+ }else{
+ iRead = iCol++;
+ }
+ sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
+ case SRT_Table:
case SRT_EphemTab: {
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid);
sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid);
@@ -1252,16 +1294,14 @@ static void generateSortTail(
}
#ifndef SQLITE_OMIT_SUBQUERY
case SRT_Set: {
- assert( nColumn==1 );
- sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid,
- &pDest->affSdst, 1);
- sqlite3ExprCacheAffinityChange(pParse, regRow, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid);
+ assert( nColumn==sqlite3Strlen30(pDest->zAffSdst) );
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, nColumn, regRowid,
+ pDest->zAffSdst, nColumn);
+ sqlite3ExprCacheAffinityChange(pParse, regRow, nColumn);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, regRowid, regRow, nColumn);
break;
}
case SRT_Mem: {
- assert( nColumn==1 );
- sqlite3ExprCodeMove(pParse, regRow, iParm, 1);
/* The LIMIT clause will terminate the loop for us */
break;
}
@@ -1280,7 +1320,11 @@ static void generateSortTail(
}
}
if( regRowid ){
- sqlite3ReleaseTempReg(pParse, regRow);
+ if( eDest==SRT_Set ){
+ sqlite3ReleaseTempRange(pParse, regRow, nColumn);
+ }else{
+ sqlite3ReleaseTempReg(pParse, regRow);
+ }
sqlite3ReleaseTempReg(pParse, regRowid);
}
/* The bottom of the loop
@@ -1420,20 +1464,20 @@ static const char *columnTypeImpl(
zType = "INTEGER";
zOrigCol = "rowid";
}else{
- zType = pTab->aCol[iCol].zType;
zOrigCol = pTab->aCol[iCol].zName;
+ zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
estWidth = pTab->aCol[iCol].szEst;
}
zOrigTab = pTab->zName;
if( pNC->pParse ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
- zOrigDb = pNC->pParse->db->aDb[iDb].zName;
+ zOrigDb = pNC->pParse->db->aDb[iDb].zDbSName;
}
#else
if( iCol<0 ){
zType = "INTEGER";
}else{
- zType = pTab->aCol[iCol].zType;
+ zType = sqlite3ColumnType(&pTab->aCol[iCol],0);
estWidth = pTab->aCol[iCol].szEst;
}
#endif
@@ -1668,7 +1712,7 @@ int sqlite3ColumnsFromExprList(
pCol->zName = zName;
sqlite3ColumnPropertiesFromName(0, pCol);
if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
- db->mallocFailed = 1;
+ sqlite3OomFault(db);
}
}
sqlite3HashClear(&ht);
@@ -1679,7 +1723,7 @@ int sqlite3ColumnsFromExprList(
sqlite3DbFree(db, aCol);
*paCol = 0;
*pnCol = 0;
- return SQLITE_NOMEM;
+ return SQLITE_NOMEM_BKPT;
}
return SQLITE_OK;
}
@@ -1695,7 +1739,7 @@ int sqlite3ColumnsFromExprList(
** This routine requires that all identifiers in the SELECT
** statement be resolved.
*/
-static void selectAddColumnTypeAndCollation(
+void sqlite3SelectAddColumnTypeAndCollation(
Parse *pParse, /* Parsing contexts */
Table *pTab, /* Add column type information to this table */
Select *pSelect /* SELECT used to determine types and collations */
@@ -1717,13 +1761,20 @@ static void selectAddColumnTypeAndCollation(
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
+ const char *zType;
+ int n, m;
p = a[i].pExpr;
- if( pCol->zType==0 ){
- pCol->zType = sqlite3DbStrDup(db,
- columnType(&sNC, p,0,0,0, &pCol->szEst));
- }
+ zType = columnType(&sNC, p, 0, 0, 0, &pCol->szEst);
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
+ if( zType && (m = sqlite3Strlen30(zType))>0 ){
+ n = sqlite3Strlen30(pCol->zName);
+ pCol->zName = sqlite3DbReallocOrFree(db, pCol->zName, n+m+2);
+ if( pCol->zName ){
+ memcpy(&pCol->zName[n+1], zType, m+1);
+ pCol->colFlags |= COLFLAG_HASTYPE;
+ }
+ }
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl && pCol->zColl==0 ){
@@ -1755,12 +1806,12 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
}
/* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside
** is disabled */
- assert( db->lookaside.bEnabled==0 );
- pTab->nRef = 1;
+ assert( db->lookaside.bDisable );
+ pTab->nTabRef = 1;
pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
- selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
@@ -1773,20 +1824,20 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
** Get a VDBE for the given parser context. Create a new one if necessary.
** If an error occurs, return NULL and leave a message in pParse.
*/
-Vdbe *sqlite3GetVdbe(Parse *pParse){
- Vdbe *v = pParse->pVdbe;
- if( v==0 ){
- v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
- if( v ) sqlite3VdbeAddOp0(v, OP_Init);
- if( pParse->pToplevel==0
- && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
- ){
- pParse->okConstFactor = 1;
- }
-
+static SQLITE_NOINLINE Vdbe *allocVdbe(Parse *pParse){
+ Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(pParse);
+ if( v ) sqlite3VdbeAddOp2(v, OP_Init, 0, 1);
+ if( pParse->pToplevel==0
+ && OptimizationEnabled(pParse->db,SQLITE_FactorOutConst)
+ ){
+ pParse->okConstFactor = 1;
}
return v;
}
+Vdbe *sqlite3GetVdbe(Parse *pParse){
+ Vdbe *v = pParse->pVdbe;
+ return v ? v : allocVdbe(pParse);
+}
/*
@@ -1836,8 +1887,9 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
VdbeComment((v, "LIMIT counter"));
if( n==0 ){
sqlite3VdbeGoto(v, iBreak);
- }else if( n>=0 && p->nSelectRow>(u64)n ){
- p->nSelectRow = n;
+ }else if( n>=0 && p->nSelectRow>sqlite3LogEst((u64)n) ){
+ p->nSelectRow = sqlite3LogEst((u64)n);
+ p->selFlags |= SF_FixedLimit;
}
}else{
sqlite3ExprCode(pParse, p->pLimit, iLimit);
@@ -1851,10 +1903,8 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
sqlite3ExprCode(pParse, p->pOffset, iOffset);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
VdbeComment((v, "OFFSET counter"));
- sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0);
- sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
+ sqlite3VdbeAddOp3(v, OP_OffsetLimit, iLimit, iOffset+1, iOffset);
VdbeComment((v, "LIMIT+OFFSET"));
- sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1);
}
}
}
@@ -1988,6 +2038,7 @@ static void generateWithRecursiveQuery(
/* Process the LIMIT and OFFSET clauses, if they exist */
addrBreak = sqlite3VdbeMakeLabel(v);
+ p->nSelectRow = 320; /* 4 billion rows */
computeLimitRegisters(pParse, p, addrBreak);
pLimit = p->pLimit;
pOffset = p->pOffset;
@@ -2217,7 +2268,6 @@ static int multiSelect(
if( dest.eDest==SRT_EphemTab ){
assert( p->pEList );
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iSDParm, p->pEList->nExpr);
- sqlite3VdbeChangeP5(v, BTREE_UNORDERED);
dest.eDest = SRT_Table;
}
@@ -2271,9 +2321,8 @@ static int multiSelect(
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
VdbeComment((v, "Jump ahead if LIMIT reached"));
if( p->iOffset ){
- sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0);
- sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1);
- sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1);
+ sqlite3VdbeAddOp3(v, OP_OffsetLimit,
+ p->iLimit, p->iOffset+1, p->iOffset);
}
}
explainSetInteger(iSub2, pParse->iNextSelectId);
@@ -2281,12 +2330,12 @@ static int multiSelect(
testcase( rc!=SQLITE_OK );
pDelete = p->pPrior;
p->pPrior = pPrior;
- p->nSelectRow += pPrior->nSelectRow;
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
if( pPrior->pLimit
&& sqlite3ExprIsInteger(pPrior->pLimit, &nLimit)
- && nLimit>0 && p->nSelectRow > (u64)nLimit
+ && nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
){
- p->nSelectRow = nLimit;
+ p->nSelectRow = sqlite3LogEst((u64)nLimit);
}
if( addr ){
sqlite3VdbeJumpHere(v, addr);
@@ -2358,7 +2407,9 @@ static int multiSelect(
pDelete = p->pPrior;
p->pPrior = pPrior;
p->pOrderBy = 0;
- if( p->op==TK_UNION ) p->nSelectRow += pPrior->nSelectRow;
+ if( p->op==TK_UNION ){
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
+ }
sqlite3ExprDelete(db, p->pLimit);
p->pLimit = pLimit;
p->pOffset = pOffset;
@@ -2457,7 +2508,7 @@ static int multiSelect(
computeLimitRegisters(pParse, p, iBreak);
sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); VdbeCoverage(v);
r1 = sqlite3GetTempReg(pParse);
- iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
+ iStart = sqlite3VdbeAddOp2(v, OP_RowData, tab1, r1);
sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r1);
selectInnerLoop(pParse, p, p->pEList, tab1,
@@ -2493,7 +2544,7 @@ static int multiSelect(
nCol = p->pEList->nExpr;
pKeyInfo = sqlite3KeyInfoAlloc(db, nCol, 1);
if( !pKeyInfo ){
- rc = SQLITE_NOMEM;
+ rc = SQLITE_NOMEM_BKPT;
goto multi_select_end;
}
for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){
@@ -2615,19 +2666,17 @@ static int generateOutputSubroutine(
}
#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.
+ /* If we are creating a set for an "expr IN (SELECT ...)".
*/
case SRT_Set: {
int r1;
- assert( pIn->nSdst==1 || pParse->nErr>0 );
- pDest->affSdst =
- sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
+ testcase( pIn->nSdst>1 );
r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, 1, r1, &pDest->affSdst,1);
- sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, 1);
- sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iSDParm, r1);
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst,
+ r1, pDest->zAffSdst, pIn->nSdst);
+ sqlite3ExprCacheAffinityChange(pParse, pIn->iSdst, pIn->nSdst);
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pDest->iSDParm, r1,
+ pIn->iSdst, pIn->nSdst);
sqlite3ReleaseTempReg(pParse, r1);
break;
}
@@ -2848,7 +2897,7 @@ static int multiSelectOrderBy(
}
if( j==nOrderBy ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
- if( pNew==0 ) return SQLITE_NOMEM;
+ if( pNew==0 ) return SQLITE_NOMEM_BKPT;
pNew->flags |= EP_IntValue;
pNew->u.iValue = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
@@ -2864,10 +2913,11 @@ static int multiSelectOrderBy(
** to the right and the left are evaluated, they use the correct
** collation.
*/
- aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
+ aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1));
if( aPermute ){
struct ExprList_item *pItem;
- for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
+ aPermute[0] = nOrderBy;
+ for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){
assert( pItem->u.x.iOrderByCol>0 );
assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
@@ -2945,7 +2995,7 @@ static int multiSelectOrderBy(
pPrior->iLimit = regLimitA;
explainSetInteger(iSub1, pParse->iNextSelectId);
sqlite3Select(pParse, pPrior, &destA);
- sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA);
+ sqlite3VdbeEndCoroutine(v, regAddrA);
sqlite3VdbeJumpHere(v, addr1);
/* Generate a coroutine to evaluate the SELECT statement on
@@ -2962,7 +3012,7 @@ static int multiSelectOrderBy(
sqlite3Select(pParse, p, &destB);
p->iLimit = savedLimit;
p->iOffset = savedOffset;
- sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrB);
+ sqlite3VdbeEndCoroutine(v, regAddrB);
/* Generate a subroutine that outputs the current row of the A
** select as the next output row of the compound select.
@@ -2994,7 +3044,7 @@ static int multiSelectOrderBy(
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd);
VdbeCoverage(v);
sqlite3VdbeGoto(v, addrEofA);
- p->nSelectRow += pPrior->nSelectRow;
+ p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
}
/* Generate a subroutine to run when the results from select B
@@ -3085,8 +3135,8 @@ static int multiSelectOrderBy(
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/* Forward Declarations */
-static void substExprList(sqlite3*, ExprList*, int, ExprList*);
-static void substSelect(sqlite3*, Select *, int, ExprList*, int);
+static void substExprList(Parse*, ExprList*, int, ExprList*);
+static void substSelect(Parse*, Select *, int, ExprList*, int);
/*
** Scan through the expression pExpr. Replace every reference to
@@ -3102,36 +3152,46 @@ static void substSelect(sqlite3*, Select *, int, ExprList*, int);
** of the subquery rather the result set of the subquery.
*/
static Expr *substExpr(
- sqlite3 *db, /* Report malloc errors to this connection */
+ Parse *pParse, /* Report errors here */
Expr *pExpr, /* Expr in which substitution occurs */
int iTable, /* Table to be substituted */
ExprList *pEList /* Substitute expressions */
){
+ sqlite3 *db = pParse->db;
if( pExpr==0 ) return 0;
if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
if( pExpr->iColumn<0 ){
pExpr->op = TK_NULL;
}else{
Expr *pNew;
+ Expr *pCopy = pEList->a[pExpr->iColumn].pExpr;
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0);
- sqlite3ExprDelete(db, pExpr);
- pExpr = pNew;
+ if( sqlite3ExprIsVector(pCopy) ){
+ sqlite3VectorErrorMsg(pParse, pCopy);
+ }else{
+ pNew = sqlite3ExprDup(db, pCopy, 0);
+ if( pNew && (pExpr->flags & EP_FromJoin) ){
+ pNew->iRightJoinTable = pExpr->iRightJoinTable;
+ pNew->flags |= EP_FromJoin;
+ }
+ sqlite3ExprDelete(db, pExpr);
+ pExpr = pNew;
+ }
}
}else{
- pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList);
- pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList);
+ pExpr->pLeft = substExpr(pParse, pExpr->pLeft, iTable, pEList);
+ pExpr->pRight = substExpr(pParse, pExpr->pRight, iTable, pEList);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
- substSelect(db, pExpr->x.pSelect, iTable, pEList, 1);
+ substSelect(pParse, pExpr->x.pSelect, iTable, pEList, 1);
}else{
- substExprList(db, pExpr->x.pList, iTable, pEList);
+ substExprList(pParse, pExpr->x.pList, iTable, pEList);
}
}
return pExpr;
}
static void substExprList(
- sqlite3 *db, /* Report malloc errors here */
+ Parse *pParse, /* Report errors here */
ExprList *pList, /* List to scan and in which to make substitutes */
int iTable, /* Table to be substituted */
ExprList *pEList /* Substitute values */
@@ -3139,11 +3199,11 @@ static void substExprList(
int i;
if( pList==0 ) return;
for(i=0; i<pList->nExpr; i++){
- pList->a[i].pExpr = substExpr(db, pList->a[i].pExpr, iTable, pEList);
+ pList->a[i].pExpr = substExpr(pParse, pList->a[i].pExpr, iTable, pEList);
}
}
static void substSelect(
- sqlite3 *db, /* Report malloc errors here */
+ Parse *pParse, /* Report errors here */
Select *p, /* SELECT statement in which to make substitutions */
int iTable, /* Table to be replaced */
ExprList *pEList, /* Substitute values */
@@ -3154,17 +3214,17 @@ static void substSelect(
int i;
if( !p ) return;
do{
- substExprList(db, p->pEList, iTable, pEList);
- substExprList(db, p->pGroupBy, iTable, pEList);
- substExprList(db, p->pOrderBy, iTable, pEList);
- p->pHaving = substExpr(db, p->pHaving, iTable, pEList);
- p->pWhere = substExpr(db, p->pWhere, iTable, pEList);
+ substExprList(pParse, p->pEList, iTable, pEList);
+ substExprList(pParse, p->pGroupBy, iTable, pEList);
+ substExprList(pParse, p->pOrderBy, iTable, pEList);
+ p->pHaving = substExpr(pParse, p->pHaving, iTable, pEList);
+ p->pWhere = substExpr(pParse, p->pWhere, iTable, pEList);
pSrc = p->pSrc;
assert( pSrc!=0 );
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
- substSelect(db, pItem->pSelect, iTable, pEList, 1);
+ substSelect(pParse, pItem->pSelect, iTable, pEList, 1);
if( pItem->fg.isTabFunc ){
- substExprList(db, pItem->u1.pFuncArg, iTable, pEList);
+ substExprList(pParse, pItem->u1.pFuncArg, iTable, pEList);
}
}
}while( doPrior && (p = p->pPrior)!=0 );
@@ -3561,12 +3621,12 @@ static int flattenSubquery(
*/
if( ALWAYS(pSubitem->pTab!=0) ){
Table *pTabToDel = pSubitem->pTab;
- if( pTabToDel->nRef==1 ){
+ if( pTabToDel->nTabRef==1 ){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
pTabToDel->pNextZombie = pToplevel->pZombieTab;
pToplevel->pZombieTab = pTabToDel;
}else{
- pTabToDel->nRef--;
+ pTabToDel->nTabRef--;
}
pSubitem->pTab = 0;
}
@@ -3681,14 +3741,15 @@ static int flattenSubquery(
assert( pParent->pHaving==0 );
pParent->pHaving = pParent->pWhere;
pParent->pWhere = pWhere;
- pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
- sqlite3ExprDup(db, pSub->pHaving, 0));
+ pParent->pHaving = sqlite3ExprAnd(db,
+ sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving
+ );
assert( pParent->pGroupBy==0 );
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
}else{
- pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
+ pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
}
- substSelect(db, pParent, iParent, pSub->pEList, 0);
+ substSelect(pParse, pParent, iParent, pSub->pEList, 0);
/* The flattened query is distinct if either the inner or the
** outer query is distinct.
@@ -3762,31 +3823,37 @@ static int flattenSubquery(
** terms are duplicated into the subquery.
*/
static int pushDownWhereTerms(
- sqlite3 *db, /* The database connection (for malloc()) */
+ Parse *pParse, /* Parse context (for malloc() and error reporting) */
Select *pSubq, /* The subquery whose WHERE clause is to be augmented */
Expr *pWhere, /* The WHERE clause of the outer query */
int iCursor /* Cursor number of the subquery */
){
Expr *pNew;
int nChng = 0;
+ Select *pX; /* For looping over compound SELECTs in pSubq */
if( pWhere==0 ) return 0;
- if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
- return 0; /* restrictions (1) and (2) */
+ for(pX=pSubq; pX; pX=pX->pPrior){
+ if( (pX->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){
+ testcase( pX->selFlags & SF_Aggregate );
+ testcase( pX->selFlags & SF_Recursive );
+ testcase( pX!=pSubq );
+ return 0; /* restrictions (1) and (2) */
+ }
}
if( pSubq->pLimit!=0 ){
- return 0; /* restriction (3) */
+ return 0; /* restriction (3) */
}
while( pWhere->op==TK_AND ){
- nChng += pushDownWhereTerms(db, pSubq, pWhere->pRight, iCursor);
+ nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
- pNew = sqlite3ExprDup(db, pWhere, 0);
- pNew = substExpr(db, pNew, iCursor, pSubq->pEList);
- pSubq->pWhere = sqlite3ExprAnd(db, pSubq->pWhere, pNew);
+ pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
+ pNew = substExpr(pParse, pNew, iCursor, pSubq->pEList);
+ pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
pSubq = pSubq->pPrior;
}
}
@@ -4078,13 +4145,13 @@ static int withExpand(
assert( pFrom->pTab==0 );
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
- pTab->nRef = 1;
+ pTab->nTabRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
- if( db->mallocFailed ) return SQLITE_NOMEM;
+ if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
assert( pFrom->pSelect );
/* Check if this is a recursive CTE. */
@@ -4101,25 +4168,33 @@ static int withExpand(
){
pItem->pTab = pTab;
pItem->fg.isRecursive = 1;
- pTab->nRef++;
+ pTab->nTabRef++;
pSel->selFlags |= SF_Recursive;
}
}
}
/* Only one recursive reference is permitted. */
- if( pTab->nRef>2 ){
+ if( pTab->nTabRef>2 ){
sqlite3ErrorMsg(
pParse, "multiple references to recursive table: %s", pCte->zName
);
return SQLITE_ERROR;
}
- assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 ));
+ assert( pTab->nTabRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nTabRef==2 ));
pCte->zCteErr = "circular reference: %s";
pSavedWith = pParse->pWith;
pParse->pWith = pWith;
- sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel);
+ if( bMayRecursive ){
+ Select *pPrior = pSel->pPrior;
+ assert( pPrior->pWith==0 );
+ pPrior->pWith = pSel->pWith;
+ sqlite3WalkSelect(pWalker, pPrior);
+ pPrior->pWith = 0;
+ }else{
+ sqlite3WalkSelect(pWalker, pSel);
+ }
pParse->pWith = pWith;
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
@@ -4163,10 +4238,12 @@ static int withExpand(
*/
static void selectPopWith(Walker *pWalker, Select *p){
Parse *pParse = pWalker->pParse;
- With *pWith = findRightmost(p)->pWith;
- if( pWith!=0 ){
- assert( pParse->pWith==pWith );
- pParse->pWith = pWith->pOuter;
+ if( pParse->pWith && p->pPrior==0 ){
+ With *pWith = findRightmost(p)->pWith;
+ if( pWith!=0 ){
+ assert( pParse->pWith==pWith );
+ pParse->pWith = pWith->pOuter;
+ }
}
}
#else
@@ -4216,8 +4293,8 @@ static int selectExpander(Walker *pWalker, Select *p){
}
pTabList = p->pSrc;
pEList = p->pEList;
- if( pWalker->xSelectCallback2==selectPopWith ){
- sqlite3WithPush(pParse, findRightmost(p)->pWith, 0);
+ if( p->pWith ){
+ sqlite3WithPush(pParse, p->pWith, 0);
}
/* Make sure cursor numbers have been assigned to all entries in
@@ -4247,7 +4324,7 @@ static int selectExpander(Walker *pWalker, Select *p){
if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
- pTab->nRef = 1;
+ pTab->nTabRef = 1;
pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; }
sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol);
@@ -4260,13 +4337,13 @@ static int selectExpander(Walker *pWalker, Select *p){
assert( pFrom->pTab==0 );
pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
if( pTab==0 ) return WRC_Abort;
- if( pTab->nRef==0xffff ){
+ if( pTab->nTabRef>=0xffff ){
sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
pTab->zName);
pFrom->pTab = 0;
return WRC_Abort;
}
- pTab->nRef++;
+ pTab->nTabRef++;
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
return WRC_Abort;
}
@@ -4370,7 +4447,7 @@ static int selectExpander(Walker *pWalker, Select *p){
continue;
}
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
- zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
+ zSchemaName = iDb>=0 ? db->aDb[iDb].zDbSName : "*";
}
for(j=0; j<pTab->nCol; j++){
char *zName = pTab->aCol[j].zName;
@@ -4416,10 +4493,10 @@ static int selectExpander(Walker *pWalker, Select *p){
if( longNames || pTabList->nSrc>1 ){
Expr *pLeft;
pLeft = sqlite3Expr(db, TK_ID, zTabName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
if( zSchemaName ){
pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
- pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
+ pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr);
}
if( longNames ){
zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
@@ -4429,8 +4506,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pExpr = pRight;
}
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
- sColname.z = zColname;
- sColname.n = sqlite3Strlen30(zColname);
+ sqlite3TokenInit(&sColname, zColname);
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
@@ -4505,9 +4581,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- if( (pSelect->selFlags & SF_MultiValue)==0 ){
- w.xSelectCallback2 = selectPopWith;
- }
+ w.xSelectCallback2 = selectPopWith;
sqlite3WalkSelect(&w, pSelect);
}
@@ -4545,7 +4619,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Select *pSel = pFrom->pSelect;
if( pSel ){
while( pSel->pPrior ) pSel = pSel->pPrior;
- selectAddColumnTypeAndCollation(pParse, pTab, pSel);
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
}
}
}
@@ -4657,8 +4731,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
- sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0,
- (void*)pF->pFunc, P4_FUNCDEF);
+ sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
+ sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
}
@@ -4709,8 +4783,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
if( regHit==0 && pAggInfo->nAccumulator ) regHit = ++pParse->nMem;
sqlite3VdbeAddOp4(v, OP_CollSeq, regHit, 0, 0, (char *)pColl, P4_COLLSEQ);
}
- sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem,
- (void*)pF->pFunc, P4_FUNCDEF);
+ sqlite3VdbeAddOp3(v, OP_AggStep0, 0, regAgg, pF->iMem);
+ sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
sqlite3VdbeChangeP5(v, (u8)nArg);
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg);
sqlite3ReleaseTempRange(pParse, regAgg, nArg);
@@ -4854,16 +4928,6 @@ int sqlite3Select(
}
#endif
-
- /* If writing to memory or generating a set
- ** only a single column may be output.
- */
-#ifndef SQLITE_OMIT_SUBQUERY
- if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){
- goto select_end;
- }
-#endif
-
/* Try to flatten subqueries in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -4954,7 +5018,7 @@ int sqlite3Select(
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( (pItem->fg.jointype & JT_OUTER)==0
- && pushDownWhereTerms(db, pSub, p->pWhere, pItem->iCursor)
+ && pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
@@ -4965,10 +5029,24 @@ int sqlite3Select(
}
/* Generate code to implement the subquery
+ **
+ ** The subquery is implemented as a co-routine if all of these are true:
+ ** (1) The subquery is guaranteed to be the outer loop (so that it
+ ** does not need to be computed more than once)
+ ** (2) The ALL keyword after SELECT is omitted. (Applications are
+ ** allowed to say "SELECT ALL" instead of just "SELECT" to disable
+ ** the use of co-routines.)
+ ** (3) Co-routines are not disabled using sqlite3_test_control()
+ ** with SQLITE_TESTCTRL_OPTIMIZATIONS.
+ **
+ ** TODO: Are there other reasons beside (1) to use a co-routine
+ ** implementation?
*/
- if( pTabList->nSrc==1
- && (p->selFlags & SF_All)==0
- && OptimizationEnabled(db, SQLITE_SubqCoroutine)
+ if( i==0
+ && (pTabList->nSrc==1
+ || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0) /* (1) */
+ && (p->selFlags & SF_All)==0 /* (2) */
+ && OptimizationEnabled(db, SQLITE_SubqCoroutine) /* (3) */
){
/* Implement a co-routine that will return a single row of the result
** set on each invocation.
@@ -4981,10 +5059,10 @@ int sqlite3Select(
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
+ pItem->pTab->nRowLogEst = pSub->nSelectRow;
pItem->fg.viaCoroutine = 1;
pItem->regResult = dest.iSdst;
- sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
+ sqlite3VdbeEndCoroutine(v, pItem->regReturn);
sqlite3VdbeJumpHere(v, addrTop-1);
sqlite3ClearTempRegCache(pParse);
}else{
@@ -5004,7 +5082,7 @@ int sqlite3Select(
/* If the subquery is not correlated and if we are not inside of
** a trigger, then we only need to compute the value of the subquery
** once. */
- onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
+ onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
}else{
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
@@ -5012,7 +5090,7 @@ int sqlite3Select(
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
- pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
+ pItem->pTab->nRowLogEst = pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
@@ -5063,6 +5141,13 @@ int sqlite3Select(
** the sDistinct.isTnct is still set. Hence, isTnct represents the
** original setting of the SF_Distinct flag, not the current setting */
assert( sDistinct.isTnct );
+
+#if SELECTTRACE_ENABLED
+ if( sqlite3SelectTrace & 0x400 ){
+ SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
}
/* If there is an ORDER BY clause, then create an ephemeral index to
@@ -5095,7 +5180,9 @@ int sqlite3Select(
/* Set the limiter.
*/
iEnd = sqlite3VdbeMakeLabel(v);
- p->nSelectRow = LARGEST_INT64;
+ if( (p->selFlags & SF_FixedLimit)==0 ){
+ p->nSelectRow = 320; /* 4 billion rows */
+ }
computeLimitRegisters(pParse, p, iEnd);
if( p->iLimit==0 && sSort.addrSortIndex>=0 ){
sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen);
@@ -5119,10 +5206,12 @@ int sqlite3Select(
if( !isAgg && pGroupBy==0 ){
/* No aggregate functions and no GROUP BY clause */
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0);
+ assert( WHERE_USE_LIMIT==SF_FixedLimit );
+ wctrlFlags |= p->selFlags & SF_FixedLimit;
/* Begin the database scan. */
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
- p->pEList, wctrlFlags, 0);
+ p->pEList, wctrlFlags, p->nSelectRow);
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
@@ -5132,6 +5221,7 @@ int sqlite3Select(
}
if( sSort.pOrderBy ){
sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
+ sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo);
if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
sSort.pOrderBy = 0;
}
@@ -5182,9 +5272,11 @@ int sqlite3Select(
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->u.x.iAlias = 0;
}
- if( p->nSelectRow>100 ) p->nSelectRow = 100;
+ assert( 66==sqlite3LogEst(100) );
+ if( p->nSelectRow>66 ) p->nSelectRow = 66;
}else{
- p->nSelectRow = 1;
+ assert( 0==sqlite3LogEst(1) );
+ p->nSelectRow = 0;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
@@ -5556,7 +5648,8 @@ int sqlite3Select(
if( flag ){
pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
pDel = pMinMax;
- if( pMinMax && !db->mallocFailed ){
+ assert( db->mallocFailed || pMinMax!=0 );
+ if( !db->mallocFailed ){
pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
pMinMax->a[0].pExpr->op = TK_COLUMN;
}
@@ -5567,7 +5660,7 @@ int sqlite3Select(
** of output.
*/
resetAccumulator(pParse, &sAggInfo);
- pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax,0,flag,0);
+ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDel);
goto select_end;
« no previous file with comments | « third_party/sqlite/src/src/rowset.c ('k') | third_party/sqlite/src/src/shell.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698