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 3b422f1100349609920c592ba6ab4e096d1ef2ff..85f8518cf1c38f0cc49dc159a726dfef1a204540 100644 |
--- a/third_party/sqlite/src/src/select.c |
+++ b/third_party/sqlite/src/src/select.c |
@@ -21,7 +21,8 @@ |
/***/ int sqlite3SelectTrace = 0; |
# define SELECTTRACE(K,P,S,X) \ |
if(sqlite3SelectTrace&(K)) \ |
- sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",(S)->zSelName,(S)),\ |
+ sqlite3DebugPrintf("%*s%s.%p: ",(P)->nSelectIndent*2-2,"",\ |
+ (S)->zSelName,(S)),\ |
sqlite3DebugPrintf X |
#else |
# define SELECTTRACE(K,P,S,X) |
@@ -53,25 +54,31 @@ struct SortCtx { |
int regReturn; /* Register holding block-output return address */ |
int labelBkOut; /* Start label for the block-output subroutine */ |
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 */ |
}; |
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ |
/* |
-** Delete all the content of a Select structure but do not deallocate |
-** the select structure itself. |
+** Delete all the content of a Select structure. Deallocate the structure |
+** itself only if bFree is true. |
*/ |
-static void clearSelect(sqlite3 *db, Select *p){ |
- sqlite3ExprListDelete(db, p->pEList); |
- sqlite3SrcListDelete(db, p->pSrc); |
- sqlite3ExprDelete(db, p->pWhere); |
- sqlite3ExprListDelete(db, p->pGroupBy); |
- sqlite3ExprDelete(db, p->pHaving); |
- sqlite3ExprListDelete(db, p->pOrderBy); |
- sqlite3SelectDelete(db, p->pPrior); |
- sqlite3ExprDelete(db, p->pLimit); |
- sqlite3ExprDelete(db, p->pOffset); |
- sqlite3WithDelete(db, p->pWith); |
+static void clearSelect(sqlite3 *db, Select *p, int bFree){ |
+ while( p ){ |
+ Select *pPrior = p->pPrior; |
+ sqlite3ExprListDelete(db, p->pEList); |
+ sqlite3SrcListDelete(db, p->pSrc); |
+ sqlite3ExprDelete(db, p->pWhere); |
+ sqlite3ExprListDelete(db, p->pGroupBy); |
+ sqlite3ExprDelete(db, p->pHaving); |
+ sqlite3ExprListDelete(db, p->pOrderBy); |
+ sqlite3ExprDelete(db, p->pLimit); |
+ sqlite3ExprDelete(db, p->pOffset); |
+ sqlite3WithDelete(db, p->pWith); |
+ if( bFree ) sqlite3DbFree(db, p); |
+ p = pPrior; |
+ bFree = 1; |
+ } |
} |
/* |
@@ -106,14 +113,13 @@ Select *sqlite3SelectNew( |
Select standin; |
sqlite3 *db = pParse->db; |
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) ); |
- assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */ |
if( pNew==0 ){ |
assert( db->mallocFailed ); |
pNew = &standin; |
memset(pNew, 0, sizeof(*pNew)); |
} |
if( pEList==0 ){ |
- pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0)); |
+ pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ASTERISK,0)); |
} |
pNew->pEList = pEList; |
if( pSrc==0 ) pSrc = sqlite3DbMallocZero(db, sizeof(*pSrc)); |
@@ -126,12 +132,11 @@ Select *sqlite3SelectNew( |
pNew->op = TK_SELECT; |
pNew->pLimit = pLimit; |
pNew->pOffset = pOffset; |
- assert( pOffset==0 || pLimit!=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); |
- if( pNew!=&standin ) sqlite3DbFree(db, pNew); |
+ clearSelect(db, pNew, pNew!=&standin); |
pNew = 0; |
}else{ |
assert( pNew->pSrc!=0 || pParse->nErr>0 ); |
@@ -156,10 +161,7 @@ void sqlite3SelectSetName(Select *p, const char *zName){ |
** Delete the given Select structure and all of its substructures. |
*/ |
void sqlite3SelectDelete(sqlite3 *db, Select *p){ |
- if( p ){ |
- clearSelect(db, p); |
- sqlite3DbFree(db, p); |
- } |
+ clearSelect(db, p, 1); |
} |
/* |
@@ -365,6 +367,12 @@ static void setJoinExpr(Expr *p, int iTable){ |
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); |
ExprSetVVAProperty(p, EP_NoReduce); |
p->iRightJoinTable = (i16)iTable; |
+ if( p->op==TK_FUNCTION && p->x.pList ){ |
+ int i; |
+ for(i=0; i<p->x.pList->nExpr; i++){ |
+ setJoinExpr(p->x.pList->a[i].pExpr, iTable); |
+ } |
+ } |
setJoinExpr(p->pLeft, iTable); |
p = p->pRight; |
} |
@@ -399,12 +407,12 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ |
int isOuter; |
if( NEVER(pLeftTab==0 || pRightTab==0) ) continue; |
- isOuter = (pRight->jointype & JT_OUTER)!=0; |
+ isOuter = (pRight->fg.jointype & JT_OUTER)!=0; |
/* When the NATURAL keyword is present, add WHERE clause terms for |
** every column that the two tables have in common. |
*/ |
- if( pRight->jointype & JT_NATURAL ){ |
+ if( pRight->fg.jointype & JT_NATURAL ){ |
if( pRight->pOn || pRight->pUsing ){ |
sqlite3ErrorMsg(pParse, "a NATURAL join may not have " |
"an ON or USING clause", 0); |
@@ -489,6 +497,7 @@ static void pushOntoSorter( |
SortCtx *pSort, /* Information about the ORDER BY clause */ |
Select *pSelect, /* The whole SELECT statement */ |
int regData, /* First register holding data to be sorted */ |
+ int regOrigData, /* First register holding data before packing */ |
int nData, /* Number of elements in the data array */ |
int nPrefixReg /* No. of reg prior to regData available for use */ |
){ |
@@ -500,8 +509,10 @@ static void pushOntoSorter( |
int regRecord = ++pParse->nMem; /* Assembled sorter record */ |
int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */ |
int op; /* Opcode to add sorter record to sorter */ |
+ int iLimit; /* LIMIT counter */ |
assert( bSeq==0 || bSeq==1 ); |
+ assert( nData==1 || regData==regOrigData ); |
if( nPrefixReg ){ |
assert( nPrefixReg==nExpr+bSeq ); |
regBase = regData - nExpr - bSeq; |
@@ -509,14 +520,17 @@ static void pushOntoSorter( |
regBase = pParse->nMem + 1; |
pParse->nMem += nBase; |
} |
- sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP); |
+ assert( pSelect->iOffset==0 || pSelect->iLimit!=0 ); |
+ iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit; |
+ pSort->labelDone = sqlite3VdbeMakeLabel(v); |
+ sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData, |
+ SQLITE_ECEL_DUP|SQLITE_ECEL_REF); |
if( bSeq ){ |
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr); |
} |
if( nPrefixReg==0 ){ |
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData); |
} |
- |
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord); |
if( nOBSat>0 ){ |
int regPrevKey; /* The first nOBSat columns of the previous row */ |
@@ -542,13 +556,19 @@ static void pushOntoSorter( |
pKI = pOp->p4.pKeyInfo; |
memset(pKI->aSortOrder, 0, pKI->nField); /* Makes OP_Jump below testable */ |
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO); |
- pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, 1); |
+ testcase( pKI->nXField>2 ); |
+ pOp->p4.pKeyInfo = keyInfoFromExprList(pParse, pSort->pOrderBy, nOBSat, |
+ pKI->nXField-1); |
addrJmp = sqlite3VdbeCurrentAddr(v); |
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v); |
pSort->labelBkOut = sqlite3VdbeMakeLabel(v); |
pSort->regReturn = ++pParse->nMem; |
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor); |
+ if( iLimit ){ |
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone); |
+ VdbeCoverage(v); |
+ } |
sqlite3VdbeJumpHere(v, addrFirst); |
sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat); |
sqlite3VdbeJumpHere(v, addrJmp); |
@@ -559,21 +579,12 @@ static void pushOntoSorter( |
op = OP_IdxInsert; |
} |
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord); |
- if( pSelect->iLimit ){ |
- int addr1, addr2; |
- int iLimit; |
- if( pSelect->iOffset ){ |
- iLimit = pSelect->iOffset+1; |
- }else{ |
- iLimit = pSelect->iLimit; |
- } |
- addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); |
- addr2 = sqlite3VdbeAddOp0(v, OP_Goto); |
- sqlite3VdbeJumpHere(v, addr1); |
+ if( iLimit ){ |
+ int addr; |
+ addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v); |
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor); |
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor); |
- sqlite3VdbeJumpHere(v, addr2); |
+ sqlite3VdbeJumpHere(v, addr); |
} |
} |
@@ -586,11 +597,8 @@ static void codeOffset( |
int iContinue /* Jump here to skip the current record */ |
){ |
if( iOffset>0 ){ |
- int addr; |
- addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); |
- VdbeComment((v, "skip OFFSET records")); |
- sqlite3VdbeJumpHere(v, addr); |
+ sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v); |
+ VdbeComment((v, "OFFSET")); |
} |
} |
@@ -714,8 +722,13 @@ static void selectInnerLoop( |
/* If the destination is an EXISTS(...) expression, the actual |
** values returned by the SELECT are not required. |
*/ |
- sqlite3ExprCodeExprList(pParse, pEList, regResult, |
- (eDest==SRT_Output||eDest==SRT_Coroutine)?SQLITE_ECEL_DUP:0); |
+ u8 ecelFlags; |
+ if( eDest==SRT_Mem || eDest==SRT_Output || eDest==SRT_Coroutine ){ |
+ ecelFlags = SQLITE_ECEL_DUP; |
+ }else{ |
+ ecelFlags = 0; |
+ } |
+ sqlite3ExprCodeExprList(pParse, pEList, regResult, 0, ecelFlags); |
} |
/* If the DISTINCT keyword was present on the SELECT statement |
@@ -770,7 +783,8 @@ static void selectInnerLoop( |
default: { |
assert( pDistinct->eTnctType==WHERE_DISTINCT_UNORDERED ); |
- codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, regResult); |
+ codeDistinct(pParse, pDistinct->tabTnct, iContinue, nResultCol, |
+ regResult); |
break; |
} |
} |
@@ -812,6 +826,8 @@ static void selectInnerLoop( |
int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1); |
testcase( eDest==SRT_Table ); |
testcase( eDest==SRT_EphemTab ); |
+ testcase( eDest==SRT_Fifo ); |
+ testcase( eDest==SRT_DistFifo ); |
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); |
#ifndef SQLITE_OMIT_CTE |
if( eDest==SRT_DistFifo ){ |
@@ -821,13 +837,14 @@ static void selectInnerLoop( |
** current row to the index and proceed with writing it to the |
** output table as well. */ |
int addr = sqlite3VdbeCurrentAddr(v) + 4; |
- sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); VdbeCoverage(v); |
+ sqlite3VdbeAddOp4Int(v, OP_Found, iParm+1, addr, r1, 0); |
+ VdbeCoverage(v); |
sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm+1, r1); |
assert( pSort==0 ); |
} |
#endif |
if( pSort ){ |
- pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, 1, nPrefixReg); |
+ pushOntoSorter(pParse, pSort, p, r1+nPrefixReg,regResult,1,nPrefixReg); |
}else{ |
int r2 = sqlite3GetTempReg(pParse); |
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); |
@@ -853,7 +870,7 @@ static void selectInnerLoop( |
** 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, 1, nPrefixReg); |
+ pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); |
}else{ |
int r1 = sqlite3GetTempReg(pParse); |
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1); |
@@ -879,7 +896,7 @@ static void selectInnerLoop( |
case SRT_Mem: { |
assert( nResultCol==1 ); |
if( pSort ){ |
- pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg); |
+ pushOntoSorter(pParse, pSort, p, regResult, regResult, 1, nPrefixReg); |
}else{ |
assert( regResult==iParm ); |
/* The LIMIT clause will jump out of the loop for us */ |
@@ -893,7 +910,8 @@ static void selectInnerLoop( |
testcase( eDest==SRT_Coroutine ); |
testcase( eDest==SRT_Output ); |
if( pSort ){ |
- pushOntoSorter(pParse, pSort, p, regResult, nResultCol, nPrefixReg); |
+ pushOntoSorter(pParse, pSort, p, regResult, regResult, nResultCol, |
+ nPrefixReg); |
}else if( eDest==SRT_Coroutine ){ |
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); |
}else{ |
@@ -970,7 +988,7 @@ static void selectInnerLoop( |
** the output for us. |
*/ |
if( pSort==0 && p->iLimit ){ |
- sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); |
} |
} |
@@ -1053,7 +1071,7 @@ static KeyInfo *keyInfoFromExprList( |
int i; |
nExpr = pList->nExpr; |
- pInfo = sqlite3KeyInfoAlloc(db, nExpr+nExtra-iStart, 1); |
+ pInfo = sqlite3KeyInfoAlloc(db, nExpr-iStart, nExtra+1); |
if( pInfo ){ |
assert( sqlite3KeyInfoIsWriteable(pInfo) ); |
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){ |
@@ -1067,7 +1085,6 @@ static KeyInfo *keyInfoFromExprList( |
return pInfo; |
} |
-#ifndef SQLITE_OMIT_COMPOUND_SELECT |
/* |
** Name of the connection operator, used for error messages. |
*/ |
@@ -1081,7 +1098,6 @@ static const char *selectOpName(int id){ |
} |
return z; |
} |
-#endif /* SQLITE_OMIT_COMPOUND_SELECT */ |
#ifndef SQLITE_OMIT_EXPLAIN |
/* |
@@ -1168,7 +1184,7 @@ static void generateSortTail( |
SelectDest *pDest /* Write the sorted results here */ |
){ |
Vdbe *v = pParse->pVdbe; /* The prepared statement */ |
- int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */ |
+ int addrBreak = pSort->labelDone; /* Jump here to exit loop */ |
int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ |
int addr; |
int addrOnce = 0; |
@@ -1187,9 +1203,10 @@ static void generateSortTail( |
struct ExprList_item *aOutEx = p->pEList->a; |
#endif |
+ assert( addrBreak<0 ); |
if( pSort->labelBkOut ){ |
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak); |
+ sqlite3VdbeGoto(v, addrBreak); |
sqlite3VdbeResolveLabel(v, pSort->labelBkOut); |
} |
iTab = pSort->iECursor; |
@@ -1227,10 +1244,7 @@ static void generateSortTail( |
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); |
} |
switch( eDest ){ |
- case SRT_Table: |
case SRT_EphemTab: { |
- testcase( eDest==SRT_Table ); |
- testcase( eDest==SRT_EphemTab ); |
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); |
sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); |
sqlite3VdbeChangeP5(v, OPFLAG_APPEND); |
@@ -1307,30 +1321,30 @@ static void generateSortTail( |
*/ |
#ifdef SQLITE_ENABLE_COLUMN_METADATA |
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F) |
+#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ |
+# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) |
+#endif |
static const char *columnTypeImpl( |
NameContext *pNC, |
Expr *pExpr, |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
const char **pzOrigDb, |
const char **pzOrigTab, |
const char **pzOrigCol, |
+#endif |
u8 *pEstWidth |
){ |
- char const *zOrigDb = 0; |
- char const *zOrigTab = 0; |
- char const *zOrigCol = 0; |
-#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */ |
-# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F) |
-static const char *columnTypeImpl( |
- NameContext *pNC, |
- Expr *pExpr, |
- u8 *pEstWidth |
-){ |
-#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */ |
char const *zType = 0; |
int j; |
u8 estWidth = 1; |
+#ifdef SQLITE_ENABLE_COLUMN_METADATA |
+ char const *zOrigDb = 0; |
+ char const *zOrigTab = 0; |
+ char const *zOrigCol = 0; |
+#endif |
- if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0; |
+ assert( pExpr!=0 ); |
+ assert( pNC->pSrcList!=0 ); |
switch( pExpr->op ){ |
case TK_AGG_COLUMN: |
case TK_COLUMN: { |
@@ -1385,6 +1399,9 @@ static const char *columnTypeImpl( |
/* If iCol is less than zero, then the expression requests the |
** rowid of the sub-select or view. This expression is legal (see |
** test case misc2.2.2) - it always evaluates to NULL. |
+ ** |
+ ** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been |
+ ** caught already by name resolution. |
*/ |
NameContext sNC; |
Expr *p = pS->pEList->a[iCol].pExpr; |
@@ -1515,7 +1532,9 @@ static void generateColumnNames( |
} |
#endif |
- if( pParse->colNamesSet || NEVER(v==0) || db->mallocFailed ) return; |
+ if( pParse->colNamesSet || db->mallocFailed ) return; |
+ assert( v!=0 ); |
+ assert( pTabList!=0 ); |
pParse->colNamesSet = 1; |
fullNames = (db->flags & SQLITE_FullColNames)!=0; |
shortNames = (db->flags & SQLITE_ShortColNames)!=0; |
@@ -1527,7 +1546,7 @@ static void generateColumnNames( |
if( pEList->a[i].zName ){ |
char *zName = pEList->a[i].zName; |
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT); |
- }else if( (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN) && pTabList ){ |
+ }else if( p->op==TK_COLUMN || p->op==TK_AGG_COLUMN ){ |
Table *pTab; |
char *zCol; |
int iCol = p->iColumn; |
@@ -1575,7 +1594,7 @@ static void generateColumnNames( |
** Return SQLITE_OK on success. If a memory allocation error occurs, |
** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM. |
*/ |
-static int selectColumnsFromExprList( |
+int sqlite3ColumnsFromExprList( |
Parse *pParse, /* Parsing context */ |
ExprList *pEList, /* Expr list from which to derive column names */ |
i16 *pnCol, /* Write the number of columns here */ |
@@ -1583,13 +1602,15 @@ static int selectColumnsFromExprList( |
){ |
sqlite3 *db = pParse->db; /* Database connection */ |
int i, j; /* Loop counters */ |
- int cnt; /* Index added to make the name unique */ |
+ u32 cnt; /* Index added to make the name unique */ |
Column *aCol, *pCol; /* For looping over result columns */ |
int nCol; /* Number of columns in the result set */ |
Expr *p; /* Expression for a single result column */ |
char *zName; /* Column name */ |
int nName; /* Size of name in zName[] */ |
+ Hash ht; /* Hash table of column names */ |
+ sqlite3HashInit(&ht); |
if( pEList ){ |
nCol = pEList->nExpr; |
aCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); |
@@ -1598,16 +1619,16 @@ static int selectColumnsFromExprList( |
nCol = 0; |
aCol = 0; |
} |
+ assert( nCol==(i16)nCol ); |
*pnCol = nCol; |
*paCol = aCol; |
- for(i=0, pCol=aCol; i<nCol; i++, pCol++){ |
+ for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){ |
/* Get an appropriate name for the column |
*/ |
p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); |
if( (zName = pEList->a[i].zName)!=0 ){ |
/* If the column contains an "AS <name>" phrase, use <name> as the name */ |
- zName = sqlite3DbStrDup(db, zName); |
}else{ |
Expr *pColExpr = p; /* The expression that is the result column name */ |
Table *pTab; /* Table associated with this expression */ |
@@ -1620,41 +1641,37 @@ static int selectColumnsFromExprList( |
int iCol = pColExpr->iColumn; |
pTab = pColExpr->pTab; |
if( iCol<0 ) iCol = pTab->iPKey; |
- zName = sqlite3MPrintf(db, "%s", |
- iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); |
+ zName = iCol>=0 ? pTab->aCol[iCol].zName : "rowid"; |
}else if( pColExpr->op==TK_ID ){ |
assert( !ExprHasProperty(pColExpr, EP_IntValue) ); |
- zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken); |
+ zName = pColExpr->u.zToken; |
}else{ |
/* Use the original text of the column expression as its name */ |
- zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); |
+ zName = pEList->a[i].zSpan; |
} |
} |
- if( db->mallocFailed ){ |
- sqlite3DbFree(db, zName); |
- break; |
- } |
+ zName = sqlite3MPrintf(db, "%s", zName); |
/* Make sure the column name is unique. If the name is not unique, |
** append an integer to the name so that it becomes unique. |
*/ |
- nName = sqlite3Strlen30(zName); |
- for(j=cnt=0; j<i; j++){ |
- if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){ |
- char *zNewName; |
- int k; |
- for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){} |
- if( k>=0 && zName[k]==':' ) nName = k; |
- zName[nName] = 0; |
- zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt); |
- sqlite3DbFree(db, zName); |
- zName = zNewName; |
- j = -1; |
- if( zName==0 ) break; |
+ cnt = 0; |
+ while( zName && sqlite3HashFind(&ht, zName)!=0 ){ |
+ nName = sqlite3Strlen30(zName); |
+ if( nName>0 ){ |
+ for(j=nName-1; j>0 && sqlite3Isdigit(zName[j]); j--){} |
+ if( zName[j]==':' ) nName = j; |
} |
+ zName = sqlite3MPrintf(db, "%.*z:%u", nName, zName, ++cnt); |
+ if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt); |
} |
pCol->zName = zName; |
+ sqlite3ColumnPropertiesFromName(0, pCol); |
+ if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){ |
+ db->mallocFailed = 1; |
+ } |
} |
+ sqlite3HashClear(&ht); |
if( db->mallocFailed ){ |
for(j=0; j<i; j++){ |
sqlite3DbFree(db, aCol[j].zName); |
@@ -1701,12 +1718,15 @@ static void selectAddColumnTypeAndCollation( |
a = pSelect->pEList->a; |
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ |
p = a[i].pExpr; |
- pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst)); |
+ if( pCol->zType==0 ){ |
+ pCol->zType = sqlite3DbStrDup(db, |
+ columnType(&sNC, p,0,0,0, &pCol->szEst)); |
+ } |
szAll += pCol->szEst; |
pCol->affinity = sqlite3ExprAffinity(p); |
- if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE; |
+ if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB; |
pColl = sqlite3ExprCollSeq(pParse, p); |
- if( pColl ){ |
+ if( pColl && pCol->zColl==0 ){ |
pCol->zColl = sqlite3DbStrDup(db, pColl->zName); |
} |
} |
@@ -1739,7 +1759,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){ |
pTab->nRef = 1; |
pTab->zName = 0; |
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
- selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
+ sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); |
selectAddColumnTypeAndCollation(pParse, pTab, pSelect); |
pTab->iPKey = -1; |
if( db->mallocFailed ){ |
@@ -1796,7 +1816,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ |
Vdbe *v = 0; |
int iLimit = 0; |
int iOffset; |
- int addr1, n; |
+ int n; |
if( p->iLimit ) return; |
/* |
@@ -1815,7 +1835,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ |
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); |
VdbeComment((v, "LIMIT counter")); |
if( n==0 ){ |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); |
+ sqlite3VdbeGoto(v, iBreak); |
}else if( n>=0 && p->nSelectRow>(u64)n ){ |
p->nSelectRow = n; |
} |
@@ -1823,7 +1843,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){ |
sqlite3ExprCode(pParse, p->pLimit, iLimit); |
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v); |
VdbeComment((v, "LIMIT counter")); |
- sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v); |
} |
if( p->pOffset ){ |
p->iOffset = iOffset = ++pParse->nMem; |
@@ -1831,14 +1851,10 @@ 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")); |
- addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); |
- sqlite3VdbeJumpHere(v, addr1); |
+ sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0); |
sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1); |
VdbeComment((v, "LIMIT+OFFSET")); |
- addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1); |
- sqlite3VdbeJumpHere(v, addr1); |
+ sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1); |
} |
} |
} |
@@ -1860,7 +1876,10 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ |
pRet = 0; |
} |
assert( iCol>=0 ); |
- if( pRet==0 && iCol<p->pEList->nExpr ){ |
+ /* iCol must be less than p->pEList->nExpr. Otherwise an error would |
+ ** have been thrown during name resolution and we would not have gotten |
+ ** this far */ |
+ if( pRet==0 && ALWAYS(iCol<p->pEList->nExpr) ){ |
pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr); |
} |
return pRet; |
@@ -1915,7 +1934,7 @@ static KeyInfo *multiSelectOrderByKeyInfo(Parse *pParse, Select *p, int nExtra){ |
** |
** |
** There is exactly one reference to the recursive-table in the FROM clause |
-** of recursive-query, marked with the SrcList->a[].isRecursive flag. |
+** of recursive-query, marked with the SrcList->a[].fg.isRecursive flag. |
** |
** The setup-query runs once to generate an initial set of rows that go |
** into a Queue table. Rows are extracted from the Queue table one by |
@@ -1980,7 +1999,7 @@ static void generateWithRecursiveQuery( |
/* Locate the cursor number of the Current table */ |
for(i=0; ALWAYS(i<pSrc->nSrc); i++){ |
- if( pSrc->a[i].isRecursive ){ |
+ if( pSrc->a[i].fg.isRecursive ){ |
iCurrent = pSrc->a[i].iCursor; |
break; |
} |
@@ -2042,7 +2061,7 @@ static void generateWithRecursiveQuery( |
selectInnerLoop(pParse, p, p->pEList, iCurrent, |
0, 0, pDest, addrCont, addrBreak); |
if( regLimit ){ |
- sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1); |
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak); |
VdbeCoverage(v); |
} |
sqlite3VdbeResolveLabel(v, addrCont); |
@@ -2050,13 +2069,17 @@ static void generateWithRecursiveQuery( |
/* Execute the recursive SELECT taking the single row in Current as |
** the value for the recursive-table. Store the results in the Queue. |
*/ |
- p->pPrior = 0; |
- sqlite3Select(pParse, p, &destQueue); |
- assert( p->pPrior==0 ); |
- p->pPrior = pSetup; |
+ if( p->selFlags & SF_Aggregate ){ |
+ sqlite3ErrorMsg(pParse, "recursive aggregate queries not supported"); |
+ }else{ |
+ p->pPrior = 0; |
+ sqlite3Select(pParse, p, &destQueue); |
+ assert( p->pPrior==0 ); |
+ p->pPrior = pSetup; |
+ } |
/* Keep running the loop until the Queue is empty */ |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrTop); |
+ sqlite3VdbeGoto(v, addrTop); |
sqlite3VdbeResolveLabel(v, addrBreak); |
end_of_recursive_query: |
@@ -2075,6 +2098,48 @@ static int multiSelectOrderBy( |
SelectDest *pDest /* What to do with query results */ |
); |
+/* |
+** Handle the special case of a compound-select that originates from a |
+** VALUES clause. By handling this as a special case, we avoid deep |
+** recursion, and thus do not need to enforce the SQLITE_LIMIT_COMPOUND_SELECT |
+** on a VALUES clause. |
+** |
+** Because the Select object originates from a VALUES clause: |
+** (1) It has no LIMIT or OFFSET |
+** (2) All terms are UNION ALL |
+** (3) There is no ORDER BY clause |
+*/ |
+static int multiSelectValues( |
+ Parse *pParse, /* Parsing context */ |
+ Select *p, /* The right-most of SELECTs to be coded */ |
+ SelectDest *pDest /* What to do with query results */ |
+){ |
+ Select *pPrior; |
+ int nRow = 1; |
+ int rc = 0; |
+ assert( p->selFlags & SF_MultiValue ); |
+ do{ |
+ assert( p->selFlags & SF_Values ); |
+ assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) ); |
+ assert( p->pLimit==0 ); |
+ assert( p->pOffset==0 ); |
+ assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr ); |
+ if( p->pPrior==0 ) break; |
+ assert( p->pPrior->pNext==p ); |
+ p = p->pPrior; |
+ nRow++; |
+ }while(1); |
+ while( p ){ |
+ pPrior = p->pPrior; |
+ p->pPrior = 0; |
+ rc = sqlite3Select(pParse, p, pDest); |
+ p->pPrior = pPrior; |
+ if( rc ) break; |
+ p->nSelectRow = nRow; |
+ p = p->pNext; |
+ } |
+ return rc; |
+} |
/* |
** This routine is called to process a compound query form from |
@@ -2156,20 +2221,18 @@ static int multiSelect( |
dest.eDest = SRT_Table; |
} |
+ /* Special handling for a compound-select that originates as a VALUES clause. |
+ */ |
+ if( p->selFlags & SF_MultiValue ){ |
+ rc = multiSelectValues(pParse, p, &dest); |
+ goto multi_select_end; |
+ } |
+ |
/* Make sure all SELECTs in the statement have the same number of elements |
** in their result sets. |
*/ |
assert( p->pEList && pPrior->pEList ); |
- if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ |
- if( p->selFlags & SF_Values ){ |
- sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); |
- }else{ |
- sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" |
- " do not have the same number of result columns", selectOpName(p->op)); |
- } |
- rc = 1; |
- goto multi_select_end; |
- } |
+ assert( p->pEList->nExpr==pPrior->pEList->nExpr ); |
#ifndef SQLITE_OMIT_CTE |
if( p->selFlags & SF_Recursive ){ |
@@ -2205,8 +2268,13 @@ static int multiSelect( |
p->iLimit = pPrior->iLimit; |
p->iOffset = pPrior->iOffset; |
if( p->iLimit ){ |
- addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v); |
+ 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); |
+ } |
} |
explainSetInteger(iSub2, pParse->iNextSelectId); |
rc = sqlite3Select(pParse, p, &dest); |
@@ -2307,7 +2375,7 @@ static int multiSelect( |
if( dest.eDest==SRT_Output ){ |
Select *pFirst = p; |
while( pFirst->pPrior ) pFirst = pFirst->pPrior; |
- generateColumnNames(pParse, 0, pFirst->pEList); |
+ generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); |
} |
iBreak = sqlite3VdbeMakeLabel(v); |
iCont = sqlite3VdbeMakeLabel(v); |
@@ -2382,7 +2450,7 @@ static int multiSelect( |
if( dest.eDest==SRT_Output ){ |
Select *pFirst = p; |
while( pFirst->pPrior ) pFirst = pFirst->pPrior; |
- generateColumnNames(pParse, 0, pFirst->pEList); |
+ generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); |
} |
iBreak = sqlite3VdbeMakeLabel(v); |
iCont = sqlite3VdbeMakeLabel(v); |
@@ -2462,6 +2530,19 @@ multi_select_end: |
#endif /* SQLITE_OMIT_COMPOUND_SELECT */ |
/* |
+** Error message for when two or more terms of a compound select have different |
+** size result sets. |
+*/ |
+void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p){ |
+ if( p->selFlags & SF_Values ){ |
+ sqlite3ErrorMsg(pParse, "all VALUES must have the same number of terms"); |
+ }else{ |
+ sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s" |
+ " do not have the same number of result columns", selectOpName(p->op)); |
+ } |
+} |
+ |
+/* |
** Code an output subroutine for a coroutine implementation of a |
** SELECT statment. |
** |
@@ -2501,12 +2582,12 @@ static int generateOutputSubroutine( |
/* Suppress duplicates for UNION, EXCEPT, and INTERSECT |
*/ |
if( regPrev ){ |
- int j1, j2; |
- j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); |
- j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, |
+ int addr1, addr2; |
+ addr1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); VdbeCoverage(v); |
+ addr2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iSdst, regPrev+1, pIn->nSdst, |
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); |
- sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2); VdbeCoverage(v); |
- sqlite3VdbeJumpHere(v, j1); |
+ sqlite3VdbeAddOp3(v, OP_Jump, addr2+2, iContinue, addr2+2); VdbeCoverage(v); |
+ sqlite3VdbeJumpHere(v, addr1); |
sqlite3VdbeAddOp3(v, OP_Copy, pIn->iSdst, regPrev+1, pIn->nSdst-1); |
sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); |
} |
@@ -2516,15 +2597,14 @@ static int generateOutputSubroutine( |
*/ |
codeOffset(v, p->iOffset, iContinue); |
+ assert( pDest->eDest!=SRT_Exists ); |
+ assert( pDest->eDest!=SRT_Table ); |
switch( pDest->eDest ){ |
/* Store the result as data using a unique key. |
*/ |
- case SRT_Table: |
case SRT_EphemTab: { |
int r1 = sqlite3GetTempReg(pParse); |
int r2 = sqlite3GetTempReg(pParse); |
- testcase( pDest->eDest==SRT_Table ); |
- testcase( pDest->eDest==SRT_EphemTab ); |
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1); |
sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iSDParm, r2); |
sqlite3VdbeAddOp3(v, OP_Insert, pDest->iSDParm, r1, r2); |
@@ -2541,7 +2621,7 @@ static int generateOutputSubroutine( |
*/ |
case SRT_Set: { |
int r1; |
- assert( pIn->nSdst==1 ); |
+ assert( pIn->nSdst==1 || pParse->nErr>0 ); |
pDest->affSdst = |
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst); |
r1 = sqlite3GetTempReg(pParse); |
@@ -2552,22 +2632,12 @@ static int generateOutputSubroutine( |
break; |
} |
-#if 0 /* Never occurs on an ORDER BY query */ |
- /* If any row exist in the result set, record that fact and abort. |
- */ |
- case SRT_Exists: { |
- sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm); |
- /* The LIMIT clause will terminate the loop for us */ |
- break; |
- } |
-#endif |
- |
/* If this is a scalar select that is part of an expression, then |
** store the results in the appropriate memory cell and break out |
** of the scan loop. |
*/ |
case SRT_Mem: { |
- assert( pIn->nSdst==1 ); |
+ assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 ); |
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1); |
/* The LIMIT clause will jump out of the loop for us */ |
break; |
@@ -2582,7 +2652,7 @@ static int generateOutputSubroutine( |
pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst); |
pDest->nSdst = pIn->nSdst; |
} |
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst); |
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst); |
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm); |
break; |
} |
@@ -2606,7 +2676,7 @@ static int generateOutputSubroutine( |
/* Jump to the end of the loop if the LIMIT is reached. |
*/ |
if( p->iLimit ){ |
- sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v); |
} |
/* Generate the subroutine return |
@@ -2734,7 +2804,7 @@ static int multiSelectOrderBy( |
int savedOffset; /* Saved value of p->iOffset */ |
int labelCmpr; /* Label for the start of the merge algorithm */ |
int labelEnd; /* Label for the end of the overall SELECT stmt */ |
- int j1; /* Jump instructions that get retargetted */ |
+ int addr1; /* Jump instructions that get retargetted */ |
int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ |
KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */ |
KeyInfo *pKeyMerge; /* Comparison information for merging rows */ |
@@ -2798,8 +2868,8 @@ static int multiSelectOrderBy( |
if( aPermute ){ |
struct ExprList_item *pItem; |
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){ |
- assert( pItem->u.x.iOrderByCol>0 |
- && pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
+ assert( pItem->u.x.iOrderByCol>0 ); |
+ assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); |
aPermute[i] = pItem->u.x.iOrderByCol - 1; |
} |
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1); |
@@ -2870,19 +2940,19 @@ static int multiSelectOrderBy( |
** left of the compound operator - the "A" select. |
*/ |
addrSelectA = sqlite3VdbeCurrentAddr(v) + 1; |
- j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
+ addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA); |
VdbeComment((v, "left SELECT")); |
pPrior->iLimit = regLimitA; |
explainSetInteger(iSub1, pParse->iNextSelectId); |
sqlite3Select(pParse, pPrior, &destA); |
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regAddrA); |
- sqlite3VdbeJumpHere(v, j1); |
+ sqlite3VdbeJumpHere(v, addr1); |
/* Generate a coroutine to evaluate the SELECT statement on |
** the right - the "B" select |
*/ |
addrSelectB = sqlite3VdbeCurrentAddr(v) + 1; |
- j1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); |
+ addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB); |
VdbeComment((v, "right SELECT")); |
savedLimit = p->iLimit; |
savedOffset = p->iOffset; |
@@ -2923,7 +2993,7 @@ static int multiSelectOrderBy( |
addrEofA = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); |
addrEofA_noB = sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, labelEnd); |
VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); |
+ sqlite3VdbeGoto(v, addrEofA); |
p->nSelectRow += pPrior->nSelectRow; |
} |
@@ -2937,7 +3007,7 @@ static int multiSelectOrderBy( |
VdbeNoopComment((v, "eof-B subroutine")); |
addrEofB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); |
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, labelEnd); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); |
+ sqlite3VdbeGoto(v, addrEofB); |
} |
/* Generate code to handle the case of A<B |
@@ -2945,7 +3015,7 @@ static int multiSelectOrderBy( |
VdbeNoopComment((v, "A-lt-B subroutine")); |
addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); |
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); |
+ sqlite3VdbeGoto(v, labelCmpr); |
/* Generate code to handle the case of A==B |
*/ |
@@ -2958,7 +3028,7 @@ static int multiSelectOrderBy( |
VdbeNoopComment((v, "A-eq-B subroutine")); |
addrAeqB = |
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); |
+ sqlite3VdbeGoto(v, labelCmpr); |
} |
/* Generate code to handle the case of A>B |
@@ -2969,11 +3039,11 @@ static int multiSelectOrderBy( |
sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); |
} |
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); |
+ sqlite3VdbeGoto(v, labelCmpr); |
/* This code runs once to initialize everything. |
*/ |
- sqlite3VdbeJumpHere(v, j1); |
+ sqlite3VdbeJumpHere(v, addr1); |
sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); |
sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); |
@@ -2995,7 +3065,7 @@ static int multiSelectOrderBy( |
if( pDest->eDest==SRT_Output ){ |
Select *pFirst = pPrior; |
while( pFirst->pPrior ) pFirst = pFirst->pPrior; |
- generateColumnNames(pParse, 0, pFirst->pEList); |
+ generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList); |
} |
/* Reassembly the compound query so that it will be freed correctly |
@@ -3009,14 +3079,14 @@ static int multiSelectOrderBy( |
/*** TBD: Insert subroutine calls to close cursors on incomplete |
**** subqueries ****/ |
explainComposite(pParse, p->op, iSub1, iSub2, 0); |
- return SQLITE_OK; |
+ return pParse->nErr!=0; |
} |
#endif |
#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 *); |
+static void substSelect(sqlite3*, Select *, int, ExprList*, int); |
/* |
** Scan through the expression pExpr. Replace every reference to |
@@ -3053,7 +3123,7 @@ static Expr *substExpr( |
pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); |
pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); |
if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
- substSelect(db, pExpr->x.pSelect, iTable, pEList); |
+ substSelect(db, pExpr->x.pSelect, iTable, pEList, 1); |
}else{ |
substExprList(db, pExpr->x.pList, iTable, pEList); |
} |
@@ -3076,25 +3146,28 @@ static void substSelect( |
sqlite3 *db, /* Report malloc errors here */ |
Select *p, /* SELECT statement in which to make substitutions */ |
int iTable, /* Table to be replaced */ |
- ExprList *pEList /* Substitute values */ |
+ ExprList *pEList, /* Substitute values */ |
+ int doPrior /* Do substitutes on p->pPrior too */ |
){ |
SrcList *pSrc; |
struct SrcList_item *pItem; |
int i; |
if( !p ) return; |
- 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); |
- substSelect(db, p->pPrior, iTable, pEList); |
- pSrc = p->pSrc; |
- assert( pSrc ); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ |
- if( ALWAYS(pSrc) ){ |
+ 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); |
+ pSrc = p->pSrc; |
+ assert( pSrc!=0 ); |
for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){ |
- substSelect(db, pItem->pSelect, iTable, pEList); |
+ substSelect(db, pItem->pSelect, iTable, pEList, 1); |
+ if( pItem->fg.isTabFunc ){ |
+ substExprList(db, pItem->u1.pFuncArg, iTable, pEList); |
+ } |
} |
- } |
+ }while( doPrior && (p = p->pPrior)!=0 ); |
} |
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
@@ -3129,7 +3202,10 @@ static void substSelect( |
** |
** (1) The subquery and the outer query do not both use aggregates. |
** |
-** (2) The subquery is not an aggregate or the outer query is not a join. |
+** (2) The subquery is not an aggregate or (2a) the outer query is not a join |
+** and (2b) the outer query does not use subqueries other than the one |
+** FROM-clause subquery that is a candidate for flattening. (2b is |
+** due to ticket [2f7170d73bf9abf80] from 2015-02-09.) |
** |
** (3) The subquery is not the right operand of a left outer join |
** (Originally ticket #306. Strengthened by ticket #3300) |
@@ -3155,8 +3231,8 @@ static void substSelect( |
** |
** (**) Restriction (10) was removed from the code on 2005-02-05 but we |
** accidently carried the comment forward until 2014-09-15. Original |
-** text: "The subquery does not use aggregates or the outer query does not |
-** use LIMIT." |
+** text: "The subquery does not use aggregates or the outer query |
+** does not use LIMIT." |
** |
** (11) The subquery and the outer query do not both have ORDER BY clauses. |
** |
@@ -3243,7 +3319,7 @@ static int flattenSubquery( |
int subqueryIsAgg /* True if the subquery uses aggregate functions */ |
){ |
const char *zSavedAuthContext = pParse->zAuthContext; |
- Select *pParent; |
+ Select *pParent; /* Current UNION ALL term of the other query */ |
Select *pSub; /* The inner query or "subquery" */ |
Select *pSub1; /* Pointer to the rightmost select in sub-query */ |
SrcList *pSrc; /* The FROM clause of the outer query */ |
@@ -3266,8 +3342,17 @@ static int flattenSubquery( |
iParent = pSubitem->iCursor; |
pSub = pSubitem->pSelect; |
assert( pSub!=0 ); |
- if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */ |
- if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */ |
+ if( subqueryIsAgg ){ |
+ if( isAgg ) return 0; /* Restriction (1) */ |
+ if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */ |
+ if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery)) |
+ || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0 |
+ || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0 |
+ ){ |
+ return 0; /* Restriction (2b) */ |
+ } |
+ } |
+ |
pSubSrc = pSub->pSrc; |
assert( pSubSrc ); |
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, |
@@ -3337,7 +3422,7 @@ static int flattenSubquery( |
** is fraught with danger. Best to avoid the whole thing. If the |
** subquery is the right term of a LEFT JOIN, then do not flatten. |
*/ |
- if( (pSubitem->jointype & JT_OUTER)!=0 ){ |
+ if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){ |
return 0; |
} |
@@ -3357,10 +3442,10 @@ static int flattenSubquery( |
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct ); |
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate ); |
assert( pSub->pSrc!=0 ); |
+ assert( pSub->pEList->nExpr==pSub1->pEList->nExpr ); |
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 |
|| (pSub1->pPrior && pSub1->op!=TK_ALL) |
|| pSub1->pSrc->nSrc<1 |
- || pSub->pEList->nExpr!=pSub1->pEList->nExpr |
){ |
return 0; |
} |
@@ -3508,7 +3593,7 @@ static int flattenSubquery( |
if( pSrc ){ |
assert( pParent==p ); /* First time through the loop */ |
- jointype = pSubitem->jointype; |
+ jointype = pSubitem->fg.jointype; |
}else{ |
assert( pParent!=p ); /* 2nd and subsequent times through the loop */ |
pSrc = pParent->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); |
@@ -3529,9 +3614,9 @@ static int flattenSubquery( |
** |
** The outer query has 3 slots in its FROM clause. One slot of the |
** outer query (the middle slot) is used by the subquery. The next |
- ** block of code will expand the out query to 4 slots. The middle |
- ** slot is expanded to two slots in order to make space for the |
- ** two elements in the FROM clause of the subquery. |
+ ** block of code will expand the outer query FROM clause to 4 slots. |
+ ** The middle slot is expanded to two slots in order to make space |
+ ** for the two elements in the FROM clause of the subquery. |
*/ |
if( nSubSrc>1 ){ |
pParent->pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc-1,iFrom+1); |
@@ -3545,10 +3630,11 @@ static int flattenSubquery( |
*/ |
for(i=0; i<nSubSrc; i++){ |
sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing); |
+ assert( pSrc->a[i+iFrom].fg.isTabFunc==0 ); |
pSrc->a[i+iFrom] = pSubSrc->a[i]; |
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); |
} |
- pSrc->a[iFrom].jointype = jointype; |
+ pSrc->a[iFrom].fg.jointype = jointype; |
/* Now begin substituting subquery result set expressions for |
** references to the iParent in the outer query. |
@@ -3570,11 +3656,6 @@ static int flattenSubquery( |
pList->a[i].zName = zName; |
} |
} |
- substExprList(db, pParent->pEList, iParent, pSub->pEList); |
- if( isAgg ){ |
- substExprList(db, pParent->pGroupBy, iParent, pSub->pEList); |
- pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); |
- } |
if( pSub->pOrderBy ){ |
/* At this point, any non-zero iOrderByCol values indicate that the |
** ORDER BY column expression is identical to the iOrderByCol'th |
@@ -3594,27 +3675,20 @@ static int flattenSubquery( |
assert( pSub->pPrior==0 ); |
pParent->pOrderBy = pOrderBy; |
pSub->pOrderBy = 0; |
- }else if( pParent->pOrderBy ){ |
- substExprList(db, pParent->pOrderBy, iParent, pSub->pEList); |
- } |
- if( pSub->pWhere ){ |
- pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
- }else{ |
- pWhere = 0; |
} |
+ pWhere = sqlite3ExprDup(db, pSub->pWhere, 0); |
if( subqueryIsAgg ){ |
assert( pParent->pHaving==0 ); |
pParent->pHaving = pParent->pWhere; |
pParent->pWhere = pWhere; |
- pParent->pHaving = substExpr(db, pParent->pHaving, iParent, pSub->pEList); |
pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving, |
sqlite3ExprDup(db, pSub->pHaving, 0)); |
assert( pParent->pGroupBy==0 ); |
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0); |
}else{ |
- pParent->pWhere = substExpr(db, pParent->pWhere, iParent, pSub->pEList); |
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere); |
} |
+ substSelect(db, pParent, iParent, pSub->pEList, 0); |
/* The flattened query is distinct if either the inner or the |
** outer query is distinct. |
@@ -3640,7 +3714,7 @@ static int flattenSubquery( |
#if SELECTTRACE_ENABLED |
if( sqlite3SelectTrace & 0x100 ){ |
- sqlite3DebugPrintf("After flattening:\n"); |
+ SELECTTRACE(0x100,pParse,p,("After flattening:\n")); |
sqlite3TreeViewSelect(0, p, 0); |
} |
#endif |
@@ -3649,6 +3723,77 @@ static int flattenSubquery( |
} |
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
+ |
+ |
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
+/* |
+** Make copies of relevant WHERE clause terms of the outer query into |
+** the WHERE clause of subquery. Example: |
+** |
+** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1) WHERE x=5 AND y=10; |
+** |
+** Transformed into: |
+** |
+** SELECT * FROM (SELECT a AS x, c-d AS y FROM t1 WHERE a=5 AND c-d=10) |
+** WHERE x=5 AND y=10; |
+** |
+** The hope is that the terms added to the inner query will make it more |
+** efficient. |
+** |
+** Do not attempt this optimization if: |
+** |
+** (1) The inner query is an aggregate. (In that case, we'd really want |
+** to copy the outer WHERE-clause terms onto the HAVING clause of the |
+** inner query. But they probably won't help there so do not bother.) |
+** |
+** (2) The inner query is the recursive part of a common table expression. |
+** |
+** (3) The inner query has a LIMIT clause (since the changes to the WHERE |
+** close would change the meaning of the LIMIT). |
+** |
+** (4) The inner query is the right operand of a LEFT JOIN. (The caller |
+** enforces this restriction since this routine does not have enough |
+** information to know.) |
+** |
+** (5) The WHERE clause expression originates in the ON or USING clause |
+** of a LEFT JOIN. |
+** |
+** Return 0 if no changes are made and non-zero if one or more WHERE clause |
+** terms are duplicated into the subquery. |
+*/ |
+static int pushDownWhereTerms( |
+ sqlite3 *db, /* The database connection (for malloc()) */ |
+ 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; |
+ if( pWhere==0 ) return 0; |
+ if( (pSubq->selFlags & (SF_Aggregate|SF_Recursive))!=0 ){ |
+ return 0; /* restrictions (1) and (2) */ |
+ } |
+ if( pSubq->pLimit!=0 ){ |
+ return 0; /* restriction (3) */ |
+ } |
+ while( pWhere->op==TK_AND ){ |
+ nChng += pushDownWhereTerms(db, 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); |
+ pSubq = pSubq->pPrior; |
+ } |
+ } |
+ return nChng; |
+} |
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ |
+ |
/* |
** Based on the contents of the AggInfo structure indicated by the first |
** argument, this function checks if the following are true: |
@@ -3732,20 +3877,20 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ |
** pFrom->pIndex and return SQLITE_OK. |
*/ |
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){ |
- if( pFrom->pTab && pFrom->zIndex ){ |
+ if( pFrom->pTab && pFrom->fg.isIndexedBy ){ |
Table *pTab = pFrom->pTab; |
- char *zIndex = pFrom->zIndex; |
+ char *zIndexedBy = pFrom->u1.zIndexedBy; |
Index *pIdx; |
for(pIdx=pTab->pIndex; |
- pIdx && sqlite3StrICmp(pIdx->zName, zIndex); |
+ pIdx && sqlite3StrICmp(pIdx->zName, zIndexedBy); |
pIdx=pIdx->pNext |
); |
if( !pIdx ){ |
- sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0); |
+ sqlite3ErrorMsg(pParse, "no such index: %s", zIndexedBy, 0); |
pParse->checkSchema = 1; |
return SQLITE_ERROR; |
} |
- pFrom->pIndex = pIdx; |
+ pFrom->pIBIndex = pIdx; |
} |
return SQLITE_OK; |
} |
@@ -3801,7 +3946,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ |
if( pNewSrc==0 ) return WRC_Abort; |
*pNew = *p; |
p->pSrc = pNewSrc; |
- p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ALL, 0)); |
+ p->pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db, TK_ASTERISK, 0)); |
p->op = TK_SELECT; |
p->pWhere = 0; |
pNew->pGroupBy = 0; |
@@ -3809,7 +3954,10 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ |
pNew->pOrderBy = 0; |
p->pPrior = 0; |
p->pNext = 0; |
+ p->pWith = 0; |
p->selFlags &= ~SF_Compound; |
+ assert( (p->selFlags & SF_Converted)==0 ); |
+ p->selFlags |= SF_Converted; |
assert( pNew->pPrior!=0 ); |
pNew->pPrior->pNext = pNew; |
pNew->pLimit = 0; |
@@ -3817,6 +3965,19 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ |
return WRC_Continue; |
} |
+/* |
+** Check to see if the FROM clause term pFrom has table-valued function |
+** arguments. If it does, leave an error message in pParse and return |
+** non-zero, since pFrom is not allowed to be a table-valued function. |
+*/ |
+static int cannotBeFunction(Parse *pParse, struct SrcList_item *pFrom){ |
+ if( pFrom->fg.isTabFunc ){ |
+ sqlite3ErrorMsg(pParse, "'%s' is not a function", pFrom->zName); |
+ return 1; |
+ } |
+ return 0; |
+} |
+ |
#ifndef SQLITE_OMIT_CTE |
/* |
** Argument pWith (which may be NULL) points to a linked list of nested |
@@ -3829,7 +3990,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){ |
** object that the returned CTE belongs to. |
*/ |
static struct Cte *searchWith( |
- With *pWith, /* Current outermost WITH clause */ |
+ With *pWith, /* Current innermost WITH clause */ |
struct SrcList_item *pItem, /* FROM clause element to resolve */ |
With **ppContext /* OUT: WITH clause return value belongs to */ |
){ |
@@ -3860,11 +4021,12 @@ static struct Cte *searchWith( |
** statement with which it is associated. |
*/ |
void sqlite3WithPush(Parse *pParse, With *pWith, u8 bFree){ |
- assert( bFree==0 || pParse->pWith==0 ); |
+ assert( bFree==0 || (pParse->pWith==0 && pParse->pWithToFree==0) ); |
if( pWith ){ |
+ assert( pParse->pWith!=pWith ); |
pWith->pOuter = pParse->pWith; |
pParse->pWith = pWith; |
- pParse->bFreeWith = bFree; |
+ if( bFree ) pParse->pWithToFree = pWith; |
} |
} |
@@ -3903,14 +4065,15 @@ static int withExpand( |
int bMayRecursive; /* True if compound joined by UNION [ALL] */ |
With *pSavedWith; /* Initial value of pParse->pWith */ |
- /* If pCte->zErr is non-NULL at this point, then this is an illegal |
+ /* If pCte->zCteErr is non-NULL at this point, then this is an illegal |
** recursive reference to CTE pCte. Leave an error in pParse and return |
- ** early. If pCte->zErr is NULL, then this is not a recursive reference. |
+ ** early. If pCte->zCteErr is NULL, then this is not a recursive reference. |
** In this case, proceed. */ |
- if( pCte->zErr ){ |
- sqlite3ErrorMsg(pParse, pCte->zErr, pCte->zName); |
+ if( pCte->zCteErr ){ |
+ sqlite3ErrorMsg(pParse, pCte->zCteErr, pCte->zName); |
return SQLITE_ERROR; |
} |
+ if( cannotBeFunction(pParse, pFrom) ) return SQLITE_ERROR; |
assert( pFrom->pTab==0 ); |
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
@@ -3919,7 +4082,7 @@ static int withExpand( |
pTab->zName = sqlite3DbStrDup(db, pCte->zName); |
pTab->iPKey = -1; |
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
- pTab->tabFlags |= TF_Ephemeral; |
+ pTab->tabFlags |= TF_Ephemeral | TF_NoVisibleRowid; |
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0); |
if( db->mallocFailed ) return SQLITE_NOMEM; |
assert( pFrom->pSelect ); |
@@ -3937,7 +4100,7 @@ static int withExpand( |
&& 0==sqlite3StrICmp(pItem->zName, pCte->zName) |
){ |
pItem->pTab = pTab; |
- pItem->isRecursive = 1; |
+ pItem->fg.isRecursive = 1; |
pTab->nRef++; |
pSel->selFlags |= SF_Recursive; |
} |
@@ -3953,15 +4116,16 @@ static int withExpand( |
} |
assert( pTab->nRef==1 || ((pSel->selFlags&SF_Recursive) && pTab->nRef==2 )); |
- pCte->zErr = "circular reference: %s"; |
+ pCte->zCteErr = "circular reference: %s"; |
pSavedWith = pParse->pWith; |
pParse->pWith = pWith; |
sqlite3WalkSelect(pWalker, bMayRecursive ? pSel->pPrior : pSel); |
+ pParse->pWith = pWith; |
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior); |
pEList = pLeft->pEList; |
if( pCte->pCols ){ |
- if( pEList->nExpr!=pCte->pCols->nExpr ){ |
+ if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){ |
sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns", |
pCte->zName, pEList->nExpr, pCte->pCols->nExpr |
); |
@@ -3971,16 +4135,16 @@ static int withExpand( |
pEList = pCte->pCols; |
} |
- selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); |
+ sqlite3ColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol); |
if( bMayRecursive ){ |
if( pSel->selFlags & SF_Recursive ){ |
- pCte->zErr = "multiple recursive references: %s"; |
+ pCte->zCteErr = "multiple recursive references: %s"; |
}else{ |
- pCte->zErr = "recursive reference in a subquery: %s"; |
+ pCte->zCteErr = "recursive reference in a subquery: %s"; |
} |
sqlite3WalkSelect(pWalker, pSel); |
} |
- pCte->zErr = 0; |
+ pCte->zCteErr = 0; |
pParse->pWith = pSavedWith; |
} |
@@ -4052,7 +4216,9 @@ static int selectExpander(Walker *pWalker, Select *p){ |
} |
pTabList = p->pSrc; |
pEList = p->pEList; |
- sqlite3WithPush(pParse, findRightmost(p)->pWith, 0); |
+ if( pWalker->xSelectCallback2==selectPopWith ){ |
+ sqlite3WithPush(pParse, findRightmost(p)->pWith, 0); |
+ } |
/* Make sure cursor numbers have been assigned to all entries in |
** the FROM clause of the SELECT statement. |
@@ -4065,17 +4231,9 @@ static int selectExpander(Walker *pWalker, Select *p){ |
*/ |
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
Table *pTab; |
- assert( pFrom->isRecursive==0 || pFrom->pTab ); |
- if( pFrom->isRecursive ) continue; |
- if( pFrom->pTab!=0 ){ |
- /* This statement has already been prepared. There is no need |
- ** to go further. */ |
- assert( i==0 ); |
-#ifndef SQLITE_OMIT_CTE |
- selectPopWith(pWalker, p); |
-#endif |
- return WRC_Prune; |
- } |
+ assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 ); |
+ if( pFrom->fg.isRecursive ) continue; |
+ assert( pFrom->pTab==0 ); |
#ifndef SQLITE_OMIT_CTE |
if( withExpand(pWalker, pFrom) ) return WRC_Abort; |
if( pFrom->pTab ) {} else |
@@ -4086,13 +4244,13 @@ static int selectExpander(Walker *pWalker, Select *p){ |
/* A sub-query in the FROM clause of a SELECT */ |
assert( pSel!=0 ); |
assert( pFrom->pTab==0 ); |
- sqlite3WalkSelect(pWalker, pSel); |
+ if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort; |
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
if( pTab==0 ) return WRC_Abort; |
pTab->nRef = 1; |
pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab); |
while( pSel->pPrior ){ pSel = pSel->pPrior; } |
- selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol); |
+ sqlite3ColumnsFromExprList(pParse, pSel->pEList,&pTab->nCol,&pTab->aCol); |
pTab->iPKey = -1; |
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); |
pTab->tabFlags |= TF_Ephemeral; |
@@ -4109,14 +4267,20 @@ static int selectExpander(Walker *pWalker, Select *p){ |
return WRC_Abort; |
} |
pTab->nRef++; |
+ if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){ |
+ return WRC_Abort; |
+ } |
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE) |
- if( pTab->pSelect || IsVirtual(pTab) ){ |
- /* We reach here if the named table is a really a view */ |
+ if( IsVirtual(pTab) || pTab->pSelect ){ |
+ i16 nCol; |
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort; |
assert( pFrom->pSelect==0 ); |
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0); |
sqlite3SelectSetName(pFrom->pSelect, pTab->zName); |
+ nCol = pTab->nCol; |
+ pTab->nCol = -1; |
sqlite3WalkSelect(pWalker, pFrom->pSelect); |
+ pTab->nCol = nCol; |
} |
#endif |
} |
@@ -4136,19 +4300,20 @@ static int selectExpander(Walker *pWalker, Select *p){ |
/* For every "*" that occurs in the column list, insert the names of |
** all columns in all tables. And for every TABLE.* insert the names |
** of all columns in TABLE. The parser inserted a special expression |
- ** with the TK_ALL operator for each "*" that it found in the column list. |
- ** The following code just has to locate the TK_ALL expressions and expand |
- ** each one to the list of all columns in all tables. |
+ ** with the TK_ASTERISK operator for each "*" that it found in the column |
+ ** list. The following code just has to locate the TK_ASTERISK |
+ ** expressions and expand each one to the list of all columns in |
+ ** all tables. |
** |
** The first loop just checks to see if there are any "*" operators |
** that need expanding. |
*/ |
for(k=0; k<pEList->nExpr; k++){ |
pE = pEList->a[k].pExpr; |
- if( pE->op==TK_ALL ) break; |
+ if( pE->op==TK_ASTERISK ) break; |
assert( pE->op!=TK_DOT || pE->pRight!=0 ); |
assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) ); |
- if( pE->op==TK_DOT && pE->pRight->op==TK_ALL ) break; |
+ if( pE->op==TK_DOT && pE->pRight->op==TK_ASTERISK ) break; |
} |
if( k<pEList->nExpr ){ |
/* |
@@ -4162,18 +4327,13 @@ static int selectExpander(Walker *pWalker, Select *p){ |
int longNames = (flags & SQLITE_FullColNames)!=0 |
&& (flags & SQLITE_ShortColNames)==0; |
- /* When processing FROM-clause subqueries, it is always the case |
- ** that full_column_names=OFF and short_column_names=ON. The |
- ** sqlite3ResultSetOfSelect() routine makes it so. */ |
- assert( (p->selFlags & SF_NestedFrom)==0 |
- || ((flags & SQLITE_FullColNames)==0 && |
- (flags & SQLITE_ShortColNames)!=0) ); |
- |
for(k=0; k<pEList->nExpr; k++){ |
pE = a[k].pExpr; |
pRight = pE->pRight; |
assert( pE->op!=TK_DOT || pRight!=0 ); |
- if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){ |
+ if( pE->op!=TK_ASTERISK |
+ && (pE->op!=TK_DOT || pRight->op!=TK_ASTERISK) |
+ ){ |
/* This particular expression does not need to be expanded. |
*/ |
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); |
@@ -4225,18 +4385,19 @@ static int selectExpander(Walker *pWalker, Select *p){ |
continue; |
} |
- /* If a column is marked as 'hidden' (currently only possible |
- ** for virtual tables), do not include it in the expanded |
- ** result-set list. |
+ /* If a column is marked as 'hidden', omit it from the expanded |
+ ** result-set list unless the SELECT has the SF_IncludeHidden |
+ ** bit set. |
*/ |
- if( IsHiddenColumn(&pTab->aCol[j]) ){ |
- assert(IsVirtual(pTab)); |
+ if( (p->selFlags & SF_IncludeHidden)==0 |
+ && IsHiddenColumn(&pTab->aCol[j]) |
+ ){ |
continue; |
} |
tableSeen = 1; |
if( i>0 && zTName==0 ){ |
- if( (pFrom->jointype & JT_NATURAL)!=0 |
+ if( (pFrom->fg.jointype & JT_NATURAL)!=0 |
&& tableAndColumnIndex(pTabList, i, zName, 0, 0) |
){ |
/* In a NATURAL join, omit the join columns from the |
@@ -4301,6 +4462,7 @@ static int selectExpander(Walker *pWalker, Select *p){ |
#if SQLITE_MAX_COLUMN |
if( p->pEList && p->pEList->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){ |
sqlite3ErrorMsg(pParse, "too many columns in result set"); |
+ return WRC_Abort; |
} |
#endif |
return WRC_Continue; |
@@ -4315,7 +4477,7 @@ static int selectExpander(Walker *pWalker, Select *p){ |
** Walker.xSelectCallback is set to do something useful for every |
** subquery in the parser tree. |
*/ |
-static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ |
+int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ |
UNUSED_PARAMETER2(NotUsed, NotUsed2); |
return WRC_Continue; |
} |
@@ -4336,14 +4498,16 @@ static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ |
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ |
Walker w; |
memset(&w, 0, sizeof(w)); |
- w.xExprCallback = exprWalkNoop; |
+ w.xExprCallback = sqlite3ExprWalkNoop; |
w.pParse = pParse; |
if( pParse->hasCompound ){ |
w.xSelectCallback = convertCompoundSelectToSubquery; |
sqlite3WalkSelect(&w, pSelect); |
} |
w.xSelectCallback = selectExpander; |
- w.xSelectCallback2 = selectPopWith; |
+ if( (pSelect->selFlags & SF_MultiValue)==0 ){ |
+ w.xSelectCallback2 = selectPopWith; |
+ } |
sqlite3WalkSelect(&w, pSelect); |
} |
@@ -4369,19 +4533,19 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ |
struct SrcList_item *pFrom; |
assert( p->selFlags & SF_Resolved ); |
- if( (p->selFlags & SF_HasTypeInfo)==0 ){ |
- p->selFlags |= SF_HasTypeInfo; |
- pParse = pWalker->pParse; |
- pTabList = p->pSrc; |
- for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
- Table *pTab = pFrom->pTab; |
- if( ALWAYS(pTab!=0) && (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
- /* A sub-query in the FROM clause of a SELECT */ |
- Select *pSel = pFrom->pSelect; |
- if( pSel ){ |
- while( pSel->pPrior ) pSel = pSel->pPrior; |
- selectAddColumnTypeAndCollation(pParse, pTab, pSel); |
- } |
+ assert( (p->selFlags & SF_HasTypeInfo)==0 ); |
+ p->selFlags |= SF_HasTypeInfo; |
+ pParse = pWalker->pParse; |
+ pTabList = p->pSrc; |
+ for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){ |
+ Table *pTab = pFrom->pTab; |
+ assert( pTab!=0 ); |
+ if( (pTab->tabFlags & TF_Ephemeral)!=0 ){ |
+ /* A sub-query in the FROM clause of a SELECT */ |
+ Select *pSel = pFrom->pSelect; |
+ if( pSel ){ |
+ while( pSel->pPrior ) pSel = pSel->pPrior; |
+ selectAddColumnTypeAndCollation(pParse, pTab, pSel); |
} |
} |
} |
@@ -4401,7 +4565,7 @@ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ |
Walker w; |
memset(&w, 0, sizeof(w)); |
w.xSelectCallback2 = selectAddSubqueryTypeInfo; |
- w.xExprCallback = exprWalkNoop; |
+ w.xExprCallback = sqlite3ExprWalkNoop; |
w.pParse = pParse; |
sqlite3WalkSelect(&w, pSelect); |
#endif |
@@ -4520,14 +4684,15 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ |
if( pList ){ |
nArg = pList->nExpr; |
regAgg = sqlite3GetTempRange(pParse, nArg); |
- sqlite3ExprCodeExprList(pParse, pList, regAgg, SQLITE_ECEL_DUP); |
+ sqlite3ExprCodeExprList(pParse, pList, regAgg, 0, SQLITE_ECEL_DUP); |
}else{ |
nArg = 0; |
regAgg = 0; |
} |
if( pF->iDistinct>=0 ){ |
addrNext = sqlite3VdbeMakeLabel(v); |
- assert( nArg==1 ); |
+ testcase( nArg==0 ); /* Error condition */ |
+ testcase( nArg>1 ); /* Also an error */ |
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg); |
} |
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){ |
@@ -4544,7 +4709,7 @@ 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_AggStep, 0, regAgg, pF->iMem, |
+ sqlite3VdbeAddOp4(v, OP_AggStep0, 0, regAgg, pF->iMem, |
(void*)pF->pFunc, P4_FUNCDEF); |
sqlite3VdbeChangeP5(v, (u8)nArg); |
sqlite3ExprCacheAffinityChange(pParse, regAgg, nArg); |
@@ -4627,7 +4792,7 @@ int sqlite3Select( |
WhereInfo *pWInfo; /* Return from sqlite3WhereBegin() */ |
Vdbe *v; /* The virtual machine under construction */ |
int isAgg; /* True for select lists like "count(*)" */ |
- ExprList *pEList; /* List of columns to extract. */ |
+ ExprList *pEList = 0; /* List of columns to extract. */ |
SrcList *pTabList; /* List of tables to select from */ |
Expr *pWhere; /* The WHERE clause. May be NULL */ |
ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ |
@@ -4677,36 +4842,90 @@ int sqlite3Select( |
memset(&sSort, 0, sizeof(sSort)); |
sSort.pOrderBy = p->pOrderBy; |
pTabList = p->pSrc; |
- pEList = p->pEList; |
if( pParse->nErr || db->mallocFailed ){ |
goto select_end; |
} |
+ assert( p->pEList!=0 ); |
isAgg = (p->selFlags & SF_Aggregate)!=0; |
- assert( pEList!=0 ); |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x100 ){ |
+ SELECTTRACE(0x100,pParse,p, ("after name resolution:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
+ } |
+#endif |
- /* Begin generating code. |
- */ |
- v = sqlite3GetVdbe(pParse); |
- if( v==0 ) goto select_end; |
/* If writing to memory or generating a set |
** only a single column may be output. |
*/ |
#ifndef SQLITE_OMIT_SUBQUERY |
- if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){ |
+ if( checkForMultiColumnSelectError(pParse, pDest, p->pEList->nExpr) ){ |
goto select_end; |
} |
#endif |
- /* Generate code for all sub-queries in the FROM clause |
+ /* Try to flatten subqueries in the FROM clause up into the main query |
*/ |
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ |
struct SrcList_item *pItem = &pTabList->a[i]; |
- SelectDest dest; |
Select *pSub = pItem->pSelect; |
int isAggSub; |
+ Table *pTab = pItem->pTab; |
+ if( pSub==0 ) continue; |
+ |
+ /* Catch mismatch in the declared columns of a view and the number of |
+ ** columns in the SELECT on the RHS */ |
+ if( pTab->nCol!=pSub->pEList->nExpr ){ |
+ sqlite3ErrorMsg(pParse, "expected %d columns for '%s' but got %d", |
+ pTab->nCol, pTab->zName, pSub->pEList->nExpr); |
+ goto select_end; |
+ } |
+ |
+ isAggSub = (pSub->selFlags & SF_Aggregate)!=0; |
+ if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ |
+ /* This subquery can be absorbed into its parent. */ |
+ if( isAggSub ){ |
+ isAgg = 1; |
+ p->selFlags |= SF_Aggregate; |
+ } |
+ i = -1; |
+ } |
+ pTabList = p->pSrc; |
+ if( db->mallocFailed ) goto select_end; |
+ if( !IgnorableOrderby(pDest) ){ |
+ sSort.pOrderBy = p->pOrderBy; |
+ } |
+ } |
+#endif |
+ /* Get a pointer the VDBE under construction, allocating a new VDBE if one |
+ ** does not already exist */ |
+ v = sqlite3GetVdbe(pParse); |
+ if( v==0 ) goto select_end; |
+ |
+#ifndef SQLITE_OMIT_COMPOUND_SELECT |
+ /* Handle compound SELECT statements using the separate multiSelect() |
+ ** procedure. |
+ */ |
+ if( p->pPrior ){ |
+ rc = multiSelect(pParse, p, pDest); |
+ explainSetInteger(pParse->iSelectId, iRestoreSelectId); |
+#if SELECTTRACE_ENABLED |
+ SELECTTRACE(1,pParse,p,("end compound-select processing\n")); |
+ pParse->nSelectIndent--; |
+#endif |
+ return rc; |
+ } |
+#endif |
+ |
+ /* Generate code for all sub-queries in the FROM clause |
+ */ |
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) |
+ for(i=0; i<pTabList->nSrc; i++){ |
+ struct SrcList_item *pItem = &pTabList->a[i]; |
+ SelectDest dest; |
+ Select *pSub = pItem->pSelect; |
if( pSub==0 ) continue; |
/* Sometimes the code for a subquery will be generated more than |
@@ -4716,7 +4935,7 @@ int sqlite3Select( |
** is sufficient, though the subroutine to manifest the view does need |
** to be invoked again. */ |
if( pItem->addrFillSub ){ |
- if( pItem->viaCoroutine==0 ){ |
+ if( pItem->fg.viaCoroutine==0 ){ |
sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); |
} |
continue; |
@@ -4731,16 +4950,25 @@ int sqlite3Select( |
*/ |
pParse->nHeight += sqlite3SelectExprHeight(p); |
- isAggSub = (pSub->selFlags & SF_Aggregate)!=0; |
- if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ |
- /* This subquery can be absorbed into its parent. */ |
- if( isAggSub ){ |
- isAgg = 1; |
- p->selFlags |= SF_Aggregate; |
+ /* Make copies of constant WHERE-clause terms in the outer query down |
+ ** 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) |
+ ){ |
+#if SELECTTRACE_ENABLED |
+ if( sqlite3SelectTrace & 0x100 ){ |
+ SELECTTRACE(0x100,pParse,p,("After WHERE-clause push-down:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
} |
- i = -1; |
- }else if( pTabList->nSrc==1 |
- && OptimizationEnabled(db, SQLITE_SubqCoroutine) |
+#endif |
+ } |
+ |
+ /* Generate code to implement the subquery |
+ */ |
+ if( pTabList->nSrc==1 |
+ && (p->selFlags & SF_All)==0 |
+ && OptimizationEnabled(db, SQLITE_SubqCoroutine) |
){ |
/* Implement a co-routine that will return a single row of the result |
** set on each invocation. |
@@ -4754,7 +4982,7 @@ int sqlite3Select( |
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); |
sqlite3Select(pParse, pSub, &dest); |
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow); |
- pItem->viaCoroutine = 1; |
+ pItem->fg.viaCoroutine = 1; |
pItem->regResult = dest.iSdst; |
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn); |
sqlite3VdbeJumpHere(v, addrTop-1); |
@@ -4772,7 +5000,7 @@ int sqlite3Select( |
pItem->regReturn = ++pParse->nMem; |
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn); |
pItem->addrFillSub = topAddr+1; |
- if( pItem->isCorrelated==0 ){ |
+ if( pItem->fg.isCorrelated==0 ){ |
/* 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. */ |
@@ -4791,33 +5019,23 @@ int sqlite3Select( |
sqlite3VdbeChangeP1(v, topAddr, retAddr); |
sqlite3ClearTempRegCache(pParse); |
} |
- if( /*pParse->nErr ||*/ db->mallocFailed ){ |
- goto select_end; |
- } |
+ if( db->mallocFailed ) goto select_end; |
pParse->nHeight -= sqlite3SelectExprHeight(p); |
- pTabList = p->pSrc; |
- if( !IgnorableOrderby(pDest) ){ |
- sSort.pOrderBy = p->pOrderBy; |
- } |
} |
- pEList = p->pEList; |
#endif |
+ |
+ /* Various elements of the SELECT copied into local variables for |
+ ** convenience */ |
+ pEList = p->pEList; |
pWhere = p->pWhere; |
pGroupBy = p->pGroupBy; |
pHaving = p->pHaving; |
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0; |
-#ifndef SQLITE_OMIT_COMPOUND_SELECT |
- /* If there is are a sequence of queries, do the earlier ones first. |
- */ |
- if( p->pPrior ){ |
- rc = multiSelect(pParse, p, pDest); |
- explainSetInteger(pParse->iSelectId, iRestoreSelectId); |
#if SELECTTRACE_ENABLED |
- SELECTTRACE(1,pParse,p,("end compound-select processing\n")); |
- pParse->nSelectIndent--; |
-#endif |
- return rc; |
+ if( sqlite3SelectTrace & 0x400 ){ |
+ SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n")); |
+ sqlite3TreeViewSelect(0, p, 0); |
} |
#endif |
@@ -4829,7 +5047,7 @@ int sqlite3Select( |
** |
** is transformed to: |
** |
- ** SELECT xyz FROM ... GROUP BY xyz |
+ ** SELECT xyz FROM ... GROUP BY xyz ORDER BY xyz |
** |
** The second form is preferred as a single index (or temp-table) may be |
** used for both the ORDER BY and DISTINCT processing. As originally |
@@ -4837,28 +5055,27 @@ int sqlite3Select( |
** BY and DISTINCT, and an index or separate temp-table for the other. |
*/ |
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct |
- && sqlite3ExprListCompare(sSort.pOrderBy, p->pEList, -1)==0 |
+ && sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0 |
){ |
p->selFlags &= ~SF_Distinct; |
- p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0); |
- pGroupBy = p->pGroupBy; |
- sSort.pOrderBy = 0; |
+ pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0); |
/* Notice that even thought SF_Distinct has been cleared from p->selFlags, |
** 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 there is an ORDER BY clause, then this sorting |
- ** index might end up being unused if the data can be |
- ** extracted in pre-sorted order. If that is the case, then the |
- ** OP_OpenEphemeral instruction will be changed to an OP_Noop once |
- ** we figure out that the sorting index is not needed. The addrSortIndex |
- ** variable is used to facilitate that change. |
+ /* If there is an ORDER BY clause, then create an ephemeral index to |
+ ** do the sorting. But this sorting ephemeral index might end up |
+ ** being unused if the data can be extracted in pre-sorted order. |
+ ** If that is the case, then the OP_OpenEphemeral instruction will be |
+ ** changed to an OP_Noop once we figure out that the sorting index is |
+ ** not needed. The sSort.addrSortIndex variable is used to facilitate |
+ ** that change. |
*/ |
if( sSort.pOrderBy ){ |
KeyInfo *pKeyInfo; |
- pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, 0); |
+ pKeyInfo = keyInfoFromExprList(pParse, sSort.pOrderBy, 0, pEList->nExpr); |
sSort.iECursor = pParse->nTab++; |
sSort.addrSortIndex = |
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
@@ -4881,18 +5098,18 @@ int sqlite3Select( |
p->nSelectRow = LARGEST_INT64; |
computeLimitRegisters(pParse, p, iEnd); |
if( p->iLimit==0 && sSort.addrSortIndex>=0 ){ |
- sqlite3VdbeGetOp(v, sSort.addrSortIndex)->opcode = OP_SorterOpen; |
+ sqlite3VdbeChangeOpcode(v, sSort.addrSortIndex, OP_SorterOpen); |
sSort.sortFlags |= SORTFLAG_UseSorter; |
} |
- /* Open a virtual index to use for the distinct set. |
+ /* Open an ephemeral index to use for the distinct set. |
*/ |
if( p->selFlags & SF_Distinct ){ |
sDistinct.tabTnct = pParse->nTab++; |
sDistinct.addrTnct = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, |
- sDistinct.tabTnct, 0, 0, |
- (char*)keyInfoFromExprList(pParse, p->pEList,0,0), |
- P4_KEYINFO); |
+ sDistinct.tabTnct, 0, 0, |
+ (char*)keyInfoFromExprList(pParse, p->pEList,0,0), |
+ P4_KEYINFO); |
sqlite3VdbeChangeP5(v, BTREE_UNORDERED); |
sDistinct.eTnctType = WHERE_DISTINCT_UNORDERED; |
}else{ |
@@ -4970,11 +5187,10 @@ int sqlite3Select( |
p->nSelectRow = 1; |
} |
- |
/* If there is both a GROUP BY and an ORDER BY clause and they are |
** identical, then it may be possible to disable the ORDER BY clause |
** on the grounds that the GROUP BY will cause elements to come out |
- ** in the correct order. It also may not - the GROUP BY may use a |
+ ** in the correct order. It also may not - the GROUP BY might use a |
** database index that causes rows to be grouped together as required |
** but not actually sorted. Either way, record the fact that the |
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp |
@@ -5017,7 +5233,7 @@ int sqlite3Select( |
*/ |
if( pGroupBy ){ |
KeyInfo *pKeyInfo; /* Keying information for the group by clause */ |
- int j1; /* A-vs-B comparision jump */ |
+ int addr1; /* A-vs-B comparision jump */ |
int addrOutputRow; /* Start of subroutine that outputs a result row */ |
int regOutputRow; /* Return address register for output subroutine */ |
int addrSetAbort; /* Set the abort flag and return */ |
@@ -5032,7 +5248,7 @@ int sqlite3Select( |
** will be converted into a Noop. |
*/ |
sAggInfo.sortingIdx = pParse->nTab++; |
- pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, 0); |
+ pKeyInfo = keyInfoFromExprList(pParse, pGroupBy, 0, sAggInfo.nColumn); |
addrSortingIdx = sqlite3VdbeAddOp4(v, OP_SorterOpen, |
sAggInfo.sortingIdx, sAggInfo.nSortingColumn, |
0, (char*)pKeyInfo, P4_KEYINFO); |
@@ -5098,19 +5314,14 @@ int sqlite3Select( |
} |
regBase = sqlite3GetTempRange(pParse, nCol); |
sqlite3ExprCacheClear(pParse); |
- sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0); |
+ sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0, 0); |
j = nGroupBy; |
for(i=0; i<sAggInfo.nColumn; i++){ |
struct AggInfo_col *pCol = &sAggInfo.aCol[i]; |
if( pCol->iSorterColumn>=j ){ |
int r1 = j + regBase; |
- int r2; |
- |
- r2 = sqlite3ExprCodeGetColumn(pParse, |
- pCol->pTab, pCol->iColumn, pCol->iTable, r1, 0); |
- if( r1!=r2 ){ |
- sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); |
- } |
+ sqlite3ExprCodeGetColumnToReg(pParse, |
+ pCol->pTab, pCol->iColumn, pCol->iTable, r1); |
j++; |
} |
} |
@@ -5152,7 +5363,8 @@ int sqlite3Select( |
addrTopOfLoop = sqlite3VdbeCurrentAddr(v); |
sqlite3ExprCacheClear(pParse); |
if( groupBySort ){ |
- sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, sortOut,sortPTab); |
+ sqlite3VdbeAddOp3(v, OP_SorterData, sAggInfo.sortingIdx, |
+ sortOut, sortPTab); |
} |
for(j=0; j<pGroupBy->nExpr; j++){ |
if( groupBySort ){ |
@@ -5164,8 +5376,8 @@ int sqlite3Select( |
} |
sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy->nExpr, |
(char*)sqlite3KeyInfoRef(pKeyInfo), P4_KEYINFO); |
- j1 = sqlite3VdbeCurrentAddr(v); |
- sqlite3VdbeAddOp3(v, OP_Jump, j1+1, 0, j1+1); VdbeCoverage(v); |
+ addr1 = sqlite3VdbeCurrentAddr(v); |
+ sqlite3VdbeAddOp3(v, OP_Jump, addr1+1, 0, addr1+1); VdbeCoverage(v); |
/* Generate code that runs whenever the GROUP BY changes. |
** Changes in the GROUP BY are detected by the previous code |
@@ -5187,7 +5399,7 @@ int sqlite3Select( |
/* Update the aggregate accumulators based on the content of |
** the current row |
*/ |
- sqlite3VdbeJumpHere(v, j1); |
+ sqlite3VdbeJumpHere(v, addr1); |
updateAccumulator(pParse, &sAggInfo); |
sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); |
VdbeComment((v, "indicate data in accumulator")); |
@@ -5209,7 +5421,7 @@ int sqlite3Select( |
/* Jump over the subroutines |
*/ |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd); |
+ sqlite3VdbeGoto(v, addrEnd); |
/* Generate a subroutine that outputs a single row of the result |
** set. This subroutine first looks at the iUseFlag. If iUseFlag |
@@ -5224,7 +5436,8 @@ int sqlite3Select( |
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); |
sqlite3VdbeResolveLabel(v, addrOutputRow); |
addrOutputRow = sqlite3VdbeCurrentAddr(v); |
- sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); VdbeCoverage(v); |
+ sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow+2); |
+ VdbeCoverage(v); |
VdbeComment((v, "Groupby result generator entry point")); |
sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); |
finalizeAggFunctions(pParse, &sAggInfo); |
@@ -5362,7 +5575,7 @@ int sqlite3Select( |
updateAccumulator(pParse, &sAggInfo); |
assert( pMinMax==0 || pMinMax->nExpr==1 ); |
if( sqlite3WhereIsOrdered(pWInfo)>0 ){ |
- sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3WhereBreakLabel(pWInfo)); |
+ sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo)); |
VdbeComment((v, "%s() by index", |
(flag==WHERE_ORDERBY_MIN?"min":"max"))); |
} |
@@ -5388,7 +5601,8 @@ int sqlite3Select( |
** and send them to the callback one by one. |
*/ |
if( sSort.pOrderBy ){ |
- explainTempTable(pParse, sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); |
+ explainTempTable(pParse, |
+ sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); |
generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); |
} |
@@ -5396,10 +5610,9 @@ int sqlite3Select( |
*/ |
sqlite3VdbeResolveLabel(v, iEnd); |
- /* The SELECT was successfully coded. Set the return code to 0 |
- ** to indicate no errors. |
- */ |
- rc = 0; |
+ /* The SELECT has been coded. If there is an error in the Parse structure, |
+ ** set the return code to 1. Otherwise 0. */ |
+ rc = (pParse->nErr>0); |
/* Control jumps to here if an error is encountered above, or upon |
** successful coding of the SELECT. |
@@ -5421,97 +5634,3 @@ select_end: |
#endif |
return rc; |
} |
- |
-#ifdef SQLITE_DEBUG |
-/* |
-** Generate a human-readable description of a the Select object. |
-*/ |
-void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){ |
- int n = 0; |
- pView = sqlite3TreeViewPush(pView, moreToFollow); |
- sqlite3TreeViewLine(pView, "SELECT%s%s", |
- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""), |
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : "") |
- ); |
- if( p->pSrc && p->pSrc->nSrc ) n++; |
- if( p->pWhere ) n++; |
- if( p->pGroupBy ) n++; |
- if( p->pHaving ) n++; |
- if( p->pOrderBy ) n++; |
- if( p->pLimit ) n++; |
- if( p->pOffset ) n++; |
- if( p->pPrior ) n++; |
- sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set"); |
- if( p->pSrc && p->pSrc->nSrc ){ |
- int i; |
- pView = sqlite3TreeViewPush(pView, (n--)>0); |
- sqlite3TreeViewLine(pView, "FROM"); |
- for(i=0; i<p->pSrc->nSrc; i++){ |
- struct SrcList_item *pItem = &p->pSrc->a[i]; |
- StrAccum x; |
- char zLine[100]; |
- sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0); |
- sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor); |
- if( pItem->zDatabase ){ |
- sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName); |
- }else if( pItem->zName ){ |
- sqlite3XPrintf(&x, 0, " %s", pItem->zName); |
- } |
- if( pItem->pTab ){ |
- sqlite3XPrintf(&x, 0, " tabname=%Q", pItem->pTab->zName); |
- } |
- if( pItem->zAlias ){ |
- sqlite3XPrintf(&x, 0, " (AS %s)", pItem->zAlias); |
- } |
- if( pItem->jointype & JT_LEFT ){ |
- sqlite3XPrintf(&x, 0, " LEFT-JOIN"); |
- } |
- sqlite3StrAccumFinish(&x); |
- sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1); |
- if( pItem->pSelect ){ |
- sqlite3TreeViewSelect(pView, pItem->pSelect, 0); |
- } |
- sqlite3TreeViewPop(pView); |
- } |
- sqlite3TreeViewPop(pView); |
- } |
- if( p->pWhere ){ |
- sqlite3TreeViewItem(pView, "WHERE", (n--)>0); |
- sqlite3TreeViewExpr(pView, p->pWhere, 0); |
- sqlite3TreeViewPop(pView); |
- } |
- if( p->pGroupBy ){ |
- sqlite3TreeViewExprList(pView, p->pGroupBy, (n--)>0, "GROUPBY"); |
- } |
- if( p->pHaving ){ |
- sqlite3TreeViewItem(pView, "HAVING", (n--)>0); |
- sqlite3TreeViewExpr(pView, p->pHaving, 0); |
- sqlite3TreeViewPop(pView); |
- } |
- if( p->pOrderBy ){ |
- sqlite3TreeViewExprList(pView, p->pOrderBy, (n--)>0, "ORDERBY"); |
- } |
- if( p->pLimit ){ |
- sqlite3TreeViewItem(pView, "LIMIT", (n--)>0); |
- sqlite3TreeViewExpr(pView, p->pLimit, 0); |
- sqlite3TreeViewPop(pView); |
- } |
- if( p->pOffset ){ |
- sqlite3TreeViewItem(pView, "OFFSET", (n--)>0); |
- sqlite3TreeViewExpr(pView, p->pOffset, 0); |
- sqlite3TreeViewPop(pView); |
- } |
- if( p->pPrior ){ |
- const char *zOp = "UNION"; |
- switch( p->op ){ |
- case TK_ALL: zOp = "UNION ALL"; break; |
- case TK_INTERSECT: zOp = "INTERSECT"; break; |
- case TK_EXCEPT: zOp = "EXCEPT"; break; |
- } |
- sqlite3TreeViewItem(pView, zOp, (n--)>0); |
- sqlite3TreeViewSelect(pView, p->pPrior, 0); |
- sqlite3TreeViewPop(pView); |
- } |
- sqlite3TreeViewPop(pView); |
-} |
-#endif /* SQLITE_DEBUG */ |