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; |