/* ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() ** interface. ** ** For each FROM-clause subquery, add Column.zType and Column.zColl ** information to the Table ure that represents the result set ** of that subquery. ** ** The Table ure that represents the result set was coned ** by selectExpander() but the type and collation information was omitted ** at that point because identifiers had not yet been resolved. This ** routine is called after identifier resolution. */ static int selectAddSubqueryTypeInfo(Walker pWalker, Select p) { Parse pParse; int i; SrcList pTabList; SrcList_item pFrom; Debug.Assert((p.selFlags & SF_Resolved) != 0); if ((p.selFlags & SF_HasTypeInfo) == 0) { p.selFlags |= SF_HasTypeInfo; pParse = pWalker.pParse; pTabList = p.pSrc; for (i = 0; i < pTabList.nSrc; i++)//, pFrom++ ) { pFrom = pTabList.a[i]; Table pTab = pFrom.pTab; if (ALWAYS(pTab != null) && (pTab.tabFlags & TF_Ephemeral) != 0) { /* A sub-query in the FROM clause of a SELECT */ Select pSel = pFrom.pSelect; Debug.Assert(pSel != null); while (pSel.pPrior != null) pSel = pSel.pPrior; selectAddColumnTypeAndCollation(pParse, pTab.nCol, pTab.aCol, pSel); } } } return WRC_Continue; }
/* ** This routine is a Walker callback for "expanding" a SELECT statement. ** "Expanding" means to do the following: ** ** (1) Make sure VDBE cursor numbers have been assigned to every ** element of the FROM clause. ** ** (2) Fill in the pTabList.a[].pTab fields in the SrcList that ** defines FROM clause. When views appear in the FROM clause, ** fill pTabList.a[].x.pSelect with a copy of the SELECT statement ** that implements the view. A copy is made of the view's SELECT ** statement so that we can freely modify or delete that statement ** without worrying about messing up the presistent representation ** of the view. ** ** (3) Add terms to the WHERE clause to accomodate the NATURAL keyword ** on joins and the ON and USING clause of joins. ** ** (4) Scan the list of columns in the result set (pEList) looking ** for instances of the "*" operator or the TABLE.* operator. ** If found, expand each "*" to be every column in every table ** and TABLE.* to be every column in TABLE. ** */ static int selectExpander(Walker pWalker, Select p) { Parse pParse = pWalker.pParse; int i, j, k; SrcList pTabList; ExprList pEList; SrcList_item pFrom; sqlite3 db = pParse.db; //if ( db.mallocFailed != 0 ) //{ // return WRC_Abort; //} if (NEVER(p.pSrc == null) || (p.selFlags & SF_Expanded) != 0) { return WRC_Prune; } p.selFlags |= SF_Expanded; pTabList = p.pSrc; pEList = p.pEList; /* Make sure cursor numbers have been assigned to all entries in ** the FROM clause of the SELECT statement. */ sqlite3SrcListAssignCursors(pParse, pTabList); /* Look up every table named in the FROM clause of the select. If ** an entry of the FROM clause is a subquery instead of a table or view, ** then create a transient table ure to describe the subquery. */ for (i = 0; i < pTabList.nSrc; i++)// pFrom++ ) { pFrom = pTabList.a[i]; Table pTab; if (pFrom.pTab != null) { /* This statement has already been prepared. There is no need ** to go further. */ Debug.Assert(i == 0); return WRC_Prune; } if (pFrom.zName == null) { #if !SQLITE_OMIT_SUBQUERY Select pSel = pFrom.pSelect; /* A sub-query in the FROM clause of a SELECT */ Debug.Assert(pSel != null); Debug.Assert(pFrom.pTab == null); sqlite3WalkSelect(pWalker, pSel); pFrom.pTab = pTab = new Table();// sqlite3DbMallocZero( db, sizeof( Table ) ); if (pTab == null) return WRC_Abort; pTab.nRef = 1; pTab.zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", pTab); while (pSel.pPrior != null) { pSel = pSel.pPrior; } selectColumnsFromExprList(pParse, pSel.pEList, ref pTab.nCol, ref pTab.aCol); pTab.iPKey = -1; pTab.nRowEst = 1000000; pTab.tabFlags |= TF_Ephemeral; #endif } else { /* An ordinary table or view name in the FROM clause */ Debug.Assert(pFrom.pTab == null); pFrom.pTab = pTab = sqlite3LocateTable(pParse, 0, pFrom.zName, pFrom.zDatabase); if (pTab == null) return WRC_Abort; pTab.nRef++; #if !(SQLITE_OMIT_VIEW) || !(SQLITE_OMIT_VIRTUALTABLE) if (pTab.pSelect != null || IsVirtual(pTab)) { /* We reach here if the named table is a really a view */ if (sqlite3ViewGetColumnNames(pParse, pTab) != 0) return WRC_Abort; pFrom.pSelect = sqlite3SelectDup(db, pTab.pSelect, 0); sqlite3WalkSelect(pWalker, pFrom.pSelect); } #endif } /* Locate the index named by the INDEXED BY clause, if any. */ if (sqlite3IndexedByLookup(pParse, pFrom) != 0) { return WRC_Abort; } } /* Process NATURAL keywords, and ON and USING clauses of joins. */ if ( /* db.mallocFailed != 0 || */ sqliteProcessJoin(pParse, p) != 0) { return WRC_Abort; } /* 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. ** ** The first loop just checks to see if there are any "*" operators ** that need expanding. */ for (k = 0; k < pEList.nExpr; k++) { Expr pE = pEList.a[k].pExpr; if (pE.op == TK_ALL) break; Debug.Assert(pE.op != TK_DOT || pE.pRight != null); Debug.Assert(pE.op != TK_DOT || (pE.pLeft != null && pE.pLeft.op == TK_ID)); if (pE.op == TK_DOT && pE.pRight.op == TK_ALL) break; } if (k < pEList.nExpr) { /* ** If we get here it means the result set contains one or more "*" ** operators that need to be expanded. Loop through each expression ** in the result set and expand them one by one. */ ExprList_item[] a = pEList.a; ExprList pNew = null; int flags = pParse.db.flags; bool longNames = (flags & SQLITE_FullColNames) != 0 && (flags & SQLITE_ShortColNames) == 0; for (k = 0; k < pEList.nExpr; k++) { Expr pE = a[k].pExpr; Debug.Assert(pE.op != TK_DOT || pE.pRight != null); if (pE.op != TK_ALL && (pE.op != TK_DOT || pE.pRight.op != TK_ALL)) { /* This particular expression does not need to be expanded. */ pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr); if (pNew != null) { pNew.a[pNew.nExpr - 1].zName = a[k].zName; pNew.a[pNew.nExpr - 1].zSpan = a[k].zSpan; a[k].zName = null; a[k].zSpan = null; } a[k].pExpr = null; } else { /* This expression is a "*" or a "TABLE.*" and needs to be ** expanded. */ int tableSeen = 0; /* Set to 1 when TABLE matches */ string zTName; /* text of name of TABLE */ if (pE.op == TK_DOT) { Debug.Assert(pE.pLeft != null); Debug.Assert(!ExprHasProperty(pE.pLeft, EP_IntValue)); zTName = pE.pLeft.u.zToken; } else { zTName = null; } for (i = 0; i < pTabList.nSrc; i++)//, pFrom++ ) { pFrom = pTabList.a[i]; Table pTab = pFrom.pTab; string zTabName = pFrom.zAlias; if (zTabName == null) { zTabName = pTab.zName; } ///if ( db.mallocFailed != 0 ) break; if (zTName != null && !zTName.Equals(zTabName, StringComparison.InvariantCultureIgnoreCase)) { continue; } tableSeen = 1; for (j = 0; j < pTab.nCol; j++) { Expr pExpr, pRight; string zName = pTab.aCol[j].zName; string zColname; /* The computed column name */ string zToFree; /* Malloced string that needs to be freed */ Token sColname = new Token(); /* Computed column name as a token */ /* If a column is marked as 'hidden' (currently only possible ** for virtual tables), do not include it in the expanded ** result-set list. */ if (IsHiddenColumn(pTab.aCol[j])) { Debug.Assert(IsVirtual(pTab)); continue; } if (i > 0 && (zTName == null || zTName.Length == 0)) { int iDummy = 0; if ((pFrom.jointype & JT_NATURAL) != 0 && tableAndColumnIndex(pTabList, i, zName, ref iDummy, ref iDummy) != 0 ) { /* In a NATURAL join, omit the join columns from the ** table to the right of the join */ continue; } if (sqlite3IdListIndex(pFrom.pUsing, zName) >= 0) { /* In a join with a USING clause, omit columns in the ** using clause from the table on the right. */ continue; } } pRight = sqlite3Expr(db, TK_ID, zName); zColname = zName; zToFree = ""; if (longNames || pTabList.nSrc > 1) { Expr pLeft; pLeft = sqlite3Expr(db, TK_ID, zTabName); pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0); if (longNames) { zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName); zToFree = zColname; } } else { pExpr = pRight; } pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); sColname.z = zColname; sColname.n = sqlite3Strlen30(zColname); sqlite3ExprListSetName(pParse, pNew, sColname, 0); sqlite3DbFree(db, ref zToFree); } } if (tableSeen == 0) { if (zTName != null) { sqlite3ErrorMsg(pParse, "no such table: %s", zTName); } else { sqlite3ErrorMsg(pParse, "no tables specified"); } } } } sqlite3ExprListDelete(db, ref pEList); p.pEList = pNew; } //#if SQLITE_MAX_COLUMN if (p.pEList != null && p.pEList.nExpr > db.aLimit[SQLITE_LIMIT_COLUMN]) { sqlite3ErrorMsg(pParse, "too many columns in result set"); } //#endif return WRC_Continue; }
/* ** This routine "expands" a SELECT statement and all of its subqueries. ** For additional information on what it means to "expand" a SELECT ** statement, see the comment on the selectExpand worker callback above. ** ** Expanding a SELECT statement is the first step in processing a ** SELECT statement. The SELECT statement must be expanded before ** name resolution is performed. ** ** If anything goes wrong, an error message is written into pParse. ** The calling function can detect the problem by looking at pParse.nErr ** and/or pParse.db.mallocFailed. */ static void sqlite3SelectExpand(Parse pParse, Select pSelect) { Walker w = new Walker(); w.xSelectCallback = selectExpander; w.xExprCallback = exprWalkNoop; w.pParse = pParse; sqlite3WalkSelect(w, pSelect); }
/* ** Analyze the SELECT statement passed as an argument to see if it ** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if ** it is, or 0 otherwise. At present, a query is considered to be ** a min()/max() query if: ** ** 1. There is a single object in the FROM clause. ** ** 2. There is a single expression in the result set, and it is ** either min(x) or max(x), where x is a column reference. */ static u8 minMaxQuery(Select p) { Expr pExpr; ExprList pEList = p.pEList; if (pEList.nExpr != 1) return WHERE_ORDERBY_NORMAL; pExpr = pEList.a[0].pExpr; if (pExpr.op != TK_AGG_FUNCTION) return 0; if (NEVER(ExprHasProperty(pExpr, EP_xIsSelect))) return 0; pEList = pExpr.x.pList; if (pEList == null || pEList.nExpr != 1) return 0; if (pEList.a[0].pExpr.op != TK_AGG_COLUMN) return WHERE_ORDERBY_NORMAL; Debug.Assert(!ExprHasProperty(pExpr, EP_IntValue)); if (pExpr.u.zToken.Equals("min", StringComparison.InvariantCultureIgnoreCase)) { return WHERE_ORDERBY_MIN; } else if (pExpr.u.zToken.Equals("max", StringComparison.InvariantCultureIgnoreCase)) { return WHERE_ORDERBY_MAX; } return WHERE_ORDERBY_NORMAL; }
/* ** The select statement passed as the first argument is an aggregate query. ** The second argment is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** ** SELECT count() FROM <tbl> ** ** where table is a database table, not a sub-select or view. If the query ** does match this pattern, then a pointer to the Table object representing ** <tbl> is returned. Otherwise, 0 is returned. */ static Table isSimpleCount(Select p, AggInfo pAggInfo) { Table pTab; Expr pExpr; Debug.Assert(null == p.pGroupBy); if (p.pWhere != null || p.pEList.nExpr != 1 || p.pSrc.nSrc != 1 || p.pSrc.a[0].pSelect != null ) { return null; } pTab = p.pSrc.a[0].pTab; pExpr = p.pEList.a[0].pExpr; Debug.Assert(pTab != null && null == pTab.pSelect && pExpr != null); if (IsVirtual(pTab)) return null; if (pExpr.op != TK_AGG_FUNCTION) return null; if ((pAggInfo.aFunc[0].pFunc.flags & SQLITE_FUNC_COUNT) == 0) return null; if ((pExpr.flags & EP_Distinct) != 0) return null; return pTab; }
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 */ ) { SrcList pSrc; SrcList_item pItem; int i; if (p == null) 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; Debug.Assert(pSrc != null); /* Even for (SELECT 1) we have: pSrc!=0 but pSrc->nSrc==0 */ if (ALWAYS(pSrc)) { for (i = pSrc.nSrc; i > 0; i--)//, pItem++ ) { pItem = pSrc.a[pSrc.nSrc - i]; substSelect(db, pItem.pSelect, iTable, pEList); } } }
/// <summary> /// This routine attempts to flatten subqueries in order to speed /// execution. It returns 1 if it makes changes and 0 if no flattening /// occurs. /// /// To understand the concept of flattening, consider the following /// query: /// /// SELECT a FROM (SELECT x+y AS a FROM t1 WHERE z<100) WHERE a>5 /// /// The default way of implementing this query is to execute the /// subquery first and store the results in a temporary table, then /// run the outer query on that temporary table. This requires two /// passes over the data. Furthermore, because the temporary table /// has no indices, the WHERE clause on the outer query cannot be /// optimized. /// /// This routine attempts to rewrite queries such as the above into /// a single flat select, like this: /// /// SELECT x+y AS a FROM t1 WHERE z<100 AND a>5 /// /// The code generated for this simpification gives the same result /// but only has to scan the data once. And because indices might /// exist on the table t1, a complete scan of the data might be /// avoided. /// /// Flattening is only attempted if all of the following are true: /// /// (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. /// /// (3) The subquery is not the right operand of a left outer join /// (Originally ticket #306. Strengthened by ticket #3300) /// /// (4) The subquery is not DISTINCT. /// /// (*) At one point restrictions (4) and (5) defined a subset of DISTINCT /// sub-queries that were excluded from this optimization. Restriction /// (4) has since been expanded to exclude all DISTINCT subqueries. /// /// (6) The subquery does not use aggregates or the outer query is not /// DISTINCT. /// /// (7) The subquery has a FROM clause. /// /// (8) The subquery does not use LIMIT or the outer query is not a join. /// /// (9) The subquery does not use LIMIT or the outer query does not use /// aggregates. /// /// (10) 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. /// /// (*) Not implemented. Subsumed into restriction (3). Was previously /// a separate restriction deriving from ticket #350. /// /// (13) The subquery and outer query do not both use LIMIT. /// /// (14) The subquery does not use OFFSET. /// /// (15) The outer query is not part of a compound select or the /// subquery does not have a LIMIT clause. /// (See ticket #2339 and ticket [02a8e81d44]). /// /// (16) The outer query is not an aggregate or the subquery does /// not contain ORDER BY. (Ticket #2942) This used to not matter /// until we introduced the group_concat() function. /// /// (17) The sub-query is not a compound select, or it is a UNION ALL /// compound clause made up entirely of non-aggregate queries, and /// the parent query: /// /// * is not itself part of a compound select, /// * is not an aggregate or DISTINCT query, and /// * has no other tables or sub-selects in the FROM clause. /// /// The parent and sub-query may contain WHERE clauses. Subject to /// rules (11), (13) and (14), they may also contain ORDER BY, /// LIMIT and OFFSET clauses. /// /// (18) If the sub-query is a compound select, then all terms of the /// ORDER by clause of the parent must be simple references to /// columns of the sub-query. /// /// (19) The subquery does not use LIMIT or the outer query does not /// have a WHERE clause. /// /// (20) If the sub-query is a compound select, then it must not use /// an ORDER BY clause. Ticket #3773. We could relax this constraint /// somewhat by saying that the terms of the ORDER BY clause must /// appear as unmodified result columns in the outer query. But /// have other optimizations in mind to deal with that case. /// /// (21) The subquery does not use LIMIT or the outer query is not /// DISTINCT. (See ticket [752e1646fc]). /// /// In this routine, the "p" parameter is a pointer to the outer query. /// The subquery is p.pSrc.a[iFrom]. isAgg is true if the outer query /// uses aggregates and subqueryIsAgg is true if the subquery uses aggregates. /// /// If flattening is not attempted, this routine is a no-op and returns 0. /// If flattening is attempted this routine returns 1. /// /// All of the expression analysis must occur on both the outer query and /// the subquery before this routine runs. /// </summary> static int flattenSubquery( Parse pParse, /* Parsing context */ Select p, /* The parent or outer SELECT statement */ int iFrom, /* Index in p.pSrc.a[] of the inner subquery */ bool isAgg, /* True if outer SELECT uses aggregate functions */ bool subqueryIsAgg /* True if the subquery uses aggregate functions */ ) { string zSavedAuthContext = pParse.zAuthContext; Select pParent; 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 */ SrcList pSubSrc; /* The FROM clause of the subquery */ ExprList pList; /* The result set of the outer query */ int iParent; /* VDBE cursor number of the pSub result set temp table */ int i; /* Loop counter */ Expr pWhere; /* The WHERE clause */ SrcList_item pSubitem;/* The subquery */ sqlite3 db = pParse.db; /* Check to see if flattening is permitted. Return 0 if not. */ Debug.Assert(p != null); Debug.Assert(p.pPrior == null); /* Unable to flatten compound queries */ if ((db.flags & SQLITE_QueryFlattener) != 0) return 0; pSrc = p.pSrc; Debug.Assert(pSrc != null && iFrom >= 0 && iFrom < pSrc.nSrc); pSubitem = pSrc.a[iFrom]; iParent = pSubitem.iCursor; pSub = pSubitem.pSelect; Debug.Assert(pSub != null); if (isAgg && subqueryIsAgg) return 0; /* Restriction (1) */ if (subqueryIsAgg && pSrc.nSrc > 1) return 0; /* Restriction (2) */ pSubSrc = pSub.pSrc; Debug.Assert(pSubSrc != null); /* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants, ** not arbitrary expresssions, we allowed some combining of LIMIT and OFFSET ** because they could be computed at compile-time. But when LIMIT and OFFSET ** became arbitrary expressions, we were forced to add restrictions (13) ** and (14). */ if (pSub.pLimit != null && p.pLimit != null) return 0; /* Restriction (13) */ if (pSub.pOffset != null) return 0; /* Restriction (14) */ if (p.pRightmost != null && pSub.pLimit != null) { return 0; /* Restriction (15) */ } if (pSubSrc.nSrc == 0) return 0; /* Restriction (7) */ if ((pSub.selFlags & SF_Distinct) != 0) return 0; /* Restriction (5) */ if (pSub.pLimit != null && (pSrc.nSrc > 1 || isAgg)) { return 0; /* Restrictions (8)(9) */ } if ((p.selFlags & SF_Distinct) != 0 && subqueryIsAgg) { return 0; /* Restriction (6) */ } if (p.pOrderBy != null && pSub.pOrderBy != null) { return 0; /* Restriction (11) */ } if (isAgg && pSub.pOrderBy != null) return 0; /* Restriction (16) */ if (pSub.pLimit != null && p.pWhere != null) return 0; /* Restriction (19) */ if (pSub.pLimit != null && (p.selFlags & SF_Distinct) != 0) { return 0; /* Restriction (21) */ } /* OBSOLETE COMMENT 1: ** Restriction 3: If the subquery is a join, make sure the subquery is ** not used as the right operand of an outer join. Examples of why this ** is not allowed: ** ** t1 LEFT OUTER JOIN (t2 JOIN t3) ** ** If we flatten the above, we would get ** ** (t1 LEFT OUTER JOIN t2) JOIN t3 ** ** which is not at all the same thing. ** ** OBSOLETE COMMENT 2: ** Restriction 12: If the subquery is the right operand of a left outer /* Restriction 12: If the subquery is the right operand of a left outer ** join, make sure the subquery has no WHERE clause. ** An examples of why this is not allowed: ** ** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0) ** ** If we flatten the above, we would get ** ** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0 ** ** But the t2.x>0 test will always fail on a NULL row of t2, which ** effectively converts the OUTER JOIN into an INNER JOIN. ** ** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE: ** Ticket #3300 shows that flattening the right term of a LEFT JOIN ** 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) { return 0; } /* Restriction 17: If the sub-query is a compound SELECT, then it must ** use only the UNION ALL operator. And none of the simple select queries ** that make up the compound SELECT are allowed to be aggregate or distinct ** queries. */ if (pSub.pPrior != null) { if (pSub.pOrderBy != null) { return 0; /* Restriction 20 */ } if (isAgg || (p.selFlags & SF_Distinct) != 0 || pSrc.nSrc != 1) { return 0; } for (pSub1 = pSub; pSub1 != null; pSub1 = pSub1.pPrior) { testcase((pSub1.selFlags & (SF_Distinct | SF_Aggregate)) == SF_Distinct); testcase((pSub1.selFlags & (SF_Distinct | SF_Aggregate)) == SF_Aggregate); if ((pSub1.selFlags & (SF_Distinct | SF_Aggregate)) != 0 || (pSub1.pPrior != null && pSub1.op != TK_ALL) || NEVER(pSub1.pSrc == null) || pSub1.pSrc.nSrc != 1 ) { return 0; } } /* Restriction 18. */ if (p.pOrderBy != null) { int ii; for (ii = 0; ii < p.pOrderBy.nExpr; ii++) { if (p.pOrderBy.a[ii].iCol == 0) return 0; } } } /***** If we reach this point, flattening is permitted. *****/ /* Authorize the subquery */ pParse.zAuthContext = pSubitem.zName; sqlite3AuthCheck(pParse, SQLITE_SELECT, null, null, null); pParse.zAuthContext = zSavedAuthContext; /* If the sub-query is a compound SELECT statement, then (by restrictions ** 17 and 18 above) it must be a UNION ALL and the parent query must ** be of the form: ** ** SELECT <expr-list> FROM (<sub-query>) <where-clause> ** ** followed by any ORDER BY, LIMIT and/or OFFSET clauses. This block ** creates N-1 copies of the parent query without any ORDER BY, LIMIT or ** OFFSET clauses and joins them to the left-hand-side of the original ** using UNION ALL operators. In this case N is the number of simple ** select statements in the compound sub-query. ** ** Example: ** ** SELECT a+1 FROM ( ** SELECT x FROM tab ** UNION ALL ** SELECT y FROM tab ** UNION ALL ** SELECT abs(z*2) FROM tab2 ** ) WHERE a!=5 ORDER BY 1 ** ** Transformed into: ** ** SELECT x+1 FROM tab WHERE x+1!=5 ** UNION ALL ** SELECT y+1 FROM tab WHERE y+1!=5 ** UNION ALL ** SELECT abs(z*2)+1 FROM tab2 WHERE abs(z*2)+1!=5 ** ORDER BY 1 ** ** We call this the "compound-subquery flattening". */ for (pSub = pSub.pPrior; pSub != null; pSub = pSub.pPrior) { Select pNew; ExprList pOrderBy = p.pOrderBy; Expr pLimit = p.pLimit; Select pPrior = p.pPrior; p.pOrderBy = null; p.pSrc = null; p.pPrior = null; p.pLimit = null; pNew = sqlite3SelectDup(db, p, 0); p.pLimit = pLimit; p.pOrderBy = pOrderBy; p.pSrc = pSrc; p.op = TK_ALL; p.pRightmost = null; if (pNew == null) { pNew = pPrior; } else { pNew.pPrior = pPrior; pNew.pRightmost = null; } p.pPrior = pNew; // if ( db.mallocFailed != 0 ) return 1; } /* Begin flattening the iFrom-th entry of the FROM clause ** in the outer query. */ pSub = pSub1 = pSubitem.pSelect; /* Delete the transient table structure associated with the ** subquery */ sqlite3DbFree(db, ref pSubitem.zDatabase); sqlite3DbFree(db, ref pSubitem.zName); sqlite3DbFree(db, ref pSubitem.zAlias); pSubitem.zDatabase = null; pSubitem.zName = null; pSubitem.zAlias = null; pSubitem.pSelect = null; /* Defer deleting the Table object associated with the ** subquery until code generation is ** complete, since there may still exist Expr.pTab entries that ** refer to the subquery even after flattening. Ticket #3346. ** ** pSubitem->pTab is always non-NULL by test restrictions and tests above. */ if (ALWAYS(pSubitem.pTab != null)) { Table pTabToDel = pSubitem.pTab; if (pTabToDel.nRef == 1) { Parse pToplevel = sqlite3ParseToplevel(pParse); pTabToDel.pNextZombie = pToplevel.pZombieTab; pToplevel.pZombieTab = pTabToDel; } else { pTabToDel.nRef--; } pSubitem.pTab = null; } /* The following loop runs once for each term in a compound-subquery ** flattening (as described above). If we are doing a different kind ** of flattening - a flattening other than a compound-subquery flattening - ** then this loop only runs once. ** ** This loop moves all of the FROM elements of the subquery into the ** the FROM clause of the outer query. Before doing this, remember ** the cursor number for the original outer query FROM element in ** iParent. The iParent cursor will never be used. Subsequent code ** will scan expressions looking for iParent references and replace ** those references with expressions that resolve to the subquery FROM ** elements we are now copying in. */ for (pParent = p; pParent != null; pParent = pParent.pPrior, pSub = pSub.pPrior) { int nSubSrc; u8 jointype = 0; pSubSrc = pSub.pSrc; /* FROM clause of subquery */ nSubSrc = pSubSrc.nSrc; /* Number of terms in subquery FROM clause */ pSrc = pParent.pSrc; /* FROM clause of the outer query */ if (pSrc != null) { Debug.Assert(pParent == p); /* First time through the loop */ jointype = pSubitem.jointype; } else { Debug.Assert(pParent != p); /* 2nd and subsequent times through the loop */ pSrc = pParent.pSrc = sqlite3SrcListAppend(db, null, null, null); //if ( pSrc == null ) //{ // //Debug.Assert( db.mallocFailed != 0 ); // break; //} } /* The subquery uses a single slot of the FROM clause of the outer ** query. If the subquery has more than one element in its FROM clause, ** then expand the outer query to make space for it to hold all elements ** of the subquery. ** ** Example: ** ** SELECT * FROM tabA, (SELECT * FROM sub1, sub2), tabB; ** ** 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. */ if (nSubSrc > 1) { pParent.pSrc = pSrc = sqlite3SrcListEnlarge(db, pSrc, nSubSrc - 1, iFrom + 1); //if ( db.mallocFailed != 0 ) //{ // break; //} } /* Transfer the FROM clause terms from the subquery into the ** outer query. */ for (i = 0; i < nSubSrc; i++) { sqlite3IdListDelete(db, ref pSrc.a[i + iFrom].pUsing); pSrc.a[i + iFrom] = pSubSrc.a[i]; pSubSrc.a[i] = new SrcList_item();//memset(pSubSrc.a[i], 0, sizeof(pSubSrc.a[i])); } pSubitem = pSrc.a[iFrom]; // Reset for C# pSrc.a[iFrom].jointype = jointype; /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. ** ** Example: ** ** SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; ** \ \_____________ subquery __________/ / ** \_____________________ outer query ______________________________/ ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ pList = pParent.pEList; for (i = 0; i < pList.nExpr; i++) { if (pList.a[i].zName == null) { string zSpan = pList.a[i].zSpan; if (ALWAYS(zSpan)) { pList.a[i].zName = zSpan;// sqlite3DbStrDup( db, zSpan ); } } } 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 != null) { Debug.Assert(pParent.pOrderBy == null); pParent.pOrderBy = pSub.pOrderBy; pSub.pOrderBy = null; } else if (pParent.pOrderBy != null) { substExprList(db, pParent.pOrderBy, iParent, pSub.pEList); } if (pSub.pWhere != null) { pWhere = sqlite3ExprDup(db, pSub.pWhere, 0); } else { pWhere = null; } if (subqueryIsAgg) { Debug.Assert(pParent.pHaving == null); 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)); Debug.Assert(pParent.pGroupBy == null); pParent.pGroupBy = sqlite3ExprListDup(db, pSub.pGroupBy, 0); } else { pParent.pWhere = substExpr(db, pParent.pWhere, iParent, pSub.pEList); pParent.pWhere = sqlite3ExprAnd(db, pParent.pWhere, pWhere); } /* The flattened query is distinct if either the inner or the ** outer query is distinct. */ pParent.selFlags = (u16)(pParent.selFlags | pSub.selFlags & SF_Distinct); /* ** SELECT ... FROM (SELECT ... LIMIT a OFFSET b) LIMIT x OFFSET y; ** ** One is tempted to try to add a and b to combine the limits. But this ** does not work if either limit is negative. */ if (pSub.pLimit != null) { pParent.pLimit = pSub.pLimit; pSub.pLimit = null; } } /* Finially, delete what is left of the subquery and return ** success. */ sqlite3SelectDelete(db, ref pSub); sqlite3SelectDelete(db, ref pSub1); return 1; }
/* ** Code an output subroutine for a coroutine implementation of a ** SELECT statment. ** ** The data to be output is contained in pIn.iMem. There are ** pIn.nMem columns to be output. pDest is where the output should ** be sent. ** ** regReturn is the number of the register holding the subroutine ** return address. ** ** If regPrev>0 then it is the first register in a vector that ** records the previous output. mem[regPrev] is a flag that is false ** if there has been no previous output. If regPrev>0 then code is ** generated to suppress duplicates. pKeyInfo is used for comparing ** keys. ** ** If the LIMIT found in p.iLimit is reached, jump immediately to ** iBreak. */ static int generateOutputSubroutine( Parse pParse, /* Parsing context */ Select p, /* The SELECT statement */ SelectDest pIn, /* Coroutine supplying data */ SelectDest pDest, /* Where to send the data */ int regReturn, /* The return address register */ int regPrev, /* Previous result register. No uniqueness if 0 */ KeyInfo pKeyInfo, /* For comparing with previous entry */ int p4type, /* The p4 type for pKeyInfo */ int iBreak /* Jump here if we hit the LIMIT */ ) { Vdbe v = pParse.pVdbe; int iContinue; int addr; addr = sqlite3VdbeCurrentAddr(v); iContinue = sqlite3VdbeMakeLabel(v); /* Suppress duplicates for UNION, EXCEPT, and INTERSECT */ if (regPrev != 0) { int j1, j2; j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev); j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn.iMem, regPrev + 1, pIn.nMem, pKeyInfo, p4type); sqlite3VdbeAddOp3(v, OP_Jump, j2 + 2, iContinue, j2 + 2); sqlite3VdbeJumpHere(v, j1); sqlite3ExprCodeCopy(pParse, pIn.iMem, regPrev + 1, pIn.nMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev); } //if ( pParse.db.mallocFailed != 0 ) return 0; /* Suppress the the first OFFSET entries if there is an OFFSET clause */ codeOffset(v, p, iContinue); switch (pDest.eDest) { /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); int r2 = sqlite3GetTempReg(pParse); testcase(pDest.eDest == SRT_Table); testcase(pDest.eDest == SRT_EphemTab); sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn.iMem, pIn.nMem, r1); sqlite3VdbeAddOp2(v, OP_NewRowid, pDest.iParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, pDest.iParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); sqlite3ReleaseTempReg(pParse, r1); break; } #if !SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { int r1; Debug.Assert(pIn.nMem == 1); p.affinity = sqlite3CompareAffinity(p.pEList.a[0].pExpr, pDest.affinity); r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn.iMem, 1, r1, p.affinity, 1); sqlite3ExprCacheAffinityChange(pParse, pIn.iMem, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest.iParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } #if FALSE //* 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.iParm); /* 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: { Debug.Assert(pIn.nMem == 1); sqlite3ExprCodeMove(pParse, pIn.iMem, pDest.iParm, 1); /* The LIMIT clause will jump out of the loop for us */ break; } #endif //* #if !SQLITE_OMIT_SUBQUERY */ /* The results are stored in a sequence of registers ** starting at pDest.iMem. Then the co-routine yields. */ case SRT_Coroutine: { if (pDest.iMem == 0) { pDest.iMem = sqlite3GetTempRange(pParse, pIn.nMem); pDest.nMem = pIn.nMem; } sqlite3ExprCodeMove(pParse, pIn.iMem, pDest.iMem, pDest.nMem); sqlite3VdbeAddOp1(v, OP_Yield, pDest.iParm); break; } /* If none of the above, then the result destination must be ** SRT_Output. This routine is never called with any other ** destination other than the ones handled above or SRT_Output. ** ** For SRT_Output, results are stored in a sequence of registers. ** Then the OP_ResultRow opcode is used to cause sqlite3_step() to ** return the next row of result. */ default: { Debug.Assert(pDest.eDest == SRT_Output); sqlite3VdbeAddOp2(v, OP_ResultRow, pIn.iMem, pIn.nMem); sqlite3ExprCacheAffinityChange(pParse, pIn.iMem, pIn.nMem); break; } } /* Jump to the end of the loop if the LIMIT is reached. */ if (p.iLimit != 0) { sqlite3VdbeAddOp3(v, OP_IfZero, p.iLimit, iBreak, -1); } /* Generate the subroutine return */ sqlite3VdbeResolveLabel(v, iContinue); sqlite3VdbeAddOp1(v, OP_Return, regReturn); return addr; }
/* ** Alternative compound select code generator for cases when there ** is an ORDER BY clause. ** ** We assume a query of the following form: ** ** <selectA> <operator> <selectB> ORDER BY <orderbylist> ** ** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT. The idea ** is to code both <selectA> and <selectB> with the ORDER BY clause as ** co-routines. Then run the co-routines in parallel and merge the results ** into the output. In addition to the two coroutines (called selectA and ** selectB) there are 7 subroutines: ** ** outA: Move the output of the selectA coroutine into the output ** of the compound query. ** ** outB: Move the output of the selectB coroutine into the output ** of the compound query. (Only generated for UNION and ** UNION ALL. EXCEPT and INSERTSECT never output a row that ** appears only in B.) ** ** AltB: Called when there is data from both coroutines and A<B. ** ** AeqB: Called when there is data from both coroutines and A==B. ** ** AgtB: Called when there is data from both coroutines and A>B. ** ** EofA: Called when data is exhausted from selectA. ** ** EofB: Called when data is exhausted from selectB. ** ** The implementation of the latter five subroutines depend on which ** <operator> is used: ** ** ** UNION ALL UNION EXCEPT INTERSECT ** ------------- ----------------- -------------- ----------------- ** AltB: outA, nextA outA, nextA outA, nextA nextA ** ** AeqB: outA, nextA nextA nextA outA, nextA ** ** AgtB: outB, nextB outB, nextB nextB nextB ** ** EofA: outB, nextB outB, nextB halt halt ** ** EofB: outA, nextA outA, nextA outA, nextA halt ** ** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA ** causes an immediate jump to EofA and an EOF on B following nextB causes ** an immediate jump to EofB. Within EofA and EofB, and EOF on entry or ** following nextX causes a jump to the end of the select processing. ** ** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled ** within the output subroutine. The regPrev register set holds the previously ** output value. A comparison is made against this value and the output ** is skipped if the next results would be the same as the previous. ** ** The implementation plan is to implement the two coroutines and seven ** subroutines first, then put the control logic at the bottom. Like this: ** ** goto Init ** coA: coroutine for left query (A) ** coB: coroutine for right query (B) ** outA: output one row of A ** outB: output one row of B (UNION and UNION ALL only) ** EofA: ... ** EofB: ... ** AltB: ... ** AeqB: ... ** AgtB: ... ** Init: initialize coroutine registers ** yield coA ** if eof(A) goto EofA ** yield coB ** if eof(B) goto EofB ** Cmpr: Compare A, B ** Jump AltB, AeqB, AgtB ** End: ... ** ** We call AltB, AeqB, AgtB, EofA, and EofB "subroutines" but they are not ** actually called using Gosub and they do not Return. EofA and EofB loop ** until all data is exhausted then jump to the "end" labe. AltB, AeqB, ** and AgtB jump to either L2 or to one of EofA or EofB. */ #if !SQLITE_OMIT_COMPOUND_SELECT static int multiSelectOrderBy( Parse pParse, /* Parsing context */ Select p, /* The right-most of SELECTs to be coded */ SelectDest pDest /* What to do with query results */ ) { int i, j; /* Loop counters */ Select pPrior; /* Another SELECT immediately to our left */ Vdbe v; /* Generate code to this VDBE */ SelectDest destA = new SelectDest(); /* Destination for coroutine A */ SelectDest destB = new SelectDest(); /* Destination for coroutine B */ int regAddrA; /* Address register for select-A coroutine */ int regEofA; /* Flag to indicate when select-A is complete */ int regAddrB; /* Address register for select-B coroutine */ int regEofB; /* Flag to indicate when select-B is complete */ int addrSelectA; /* Address of the select-A coroutine */ int addrSelectB; /* Address of the select-B coroutine */ int regOutA; /* Address register for the output-A subroutine */ int regOutB; /* Address register for the output-B subroutine */ int addrOutA; /* Address of the output-A subroutine */ int addrOutB = 0; /* Address of the output-B subroutine */ int addrEofA; /* Address of the select-A-exhausted subroutine */ int addrEofB; /* Address of the select-B-exhausted subroutine */ int addrAltB; /* Address of the A<B subroutine */ int addrAeqB; /* Address of the A==B subroutine */ int addrAgtB; /* Address of the A>B subroutine */ int regLimitA; /* Limit register for select-A */ int regLimitB; /* Limit register for select-A */ int regPrev; /* A range of registers to hold previous output */ int savedLimit; /* Saved value of p.iLimit */ int savedOffset; /* Saved value of p.iOffset */ int labelCmpr; /* Label for the start of the merge algorithm */ int labelEnd; /* Label for the end of the overall SELECT stmt */ int j1; /* Jump instructions that get retargetted */ int op; /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */ KeyInfo pKeyDup = null; /* Comparison information for duplicate removal */ KeyInfo pKeyMerge; /* Comparison information for merging rows */ sqlite3 db; /* Database connection */ ExprList pOrderBy; /* The ORDER BY clause */ int nOrderBy; /* Number of terms in the ORDER BY clause */ int[] aPermute; /* Mapping from ORDER BY terms to result set columns */ #if !SQLITE_OMIT_EXPLAIN int iSub1 = 0; /* EQP id of left-hand query */ int iSub2 = 0; /* EQP id of right-hand query */ #endif Debug.Assert(p.pOrderBy != null); Debug.Assert(pKeyDup == null); /* "Managed" code needs this. Ticket #3382. */ db = pParse.db; v = pParse.pVdbe; Debug.Assert(v != null); /* Already thrown the error if VDBE alloc failed */ labelEnd = sqlite3VdbeMakeLabel(v); labelCmpr = sqlite3VdbeMakeLabel(v); /* Patch up the ORDER BY clause */ op = p.op; pPrior = p.pPrior; Debug.Assert(pPrior.pOrderBy == null); pOrderBy = p.pOrderBy; Debug.Assert(pOrderBy != null); nOrderBy = pOrderBy.nExpr; /* For operators other than UNION ALL we have to make sure that ** the ORDER BY clause covers every term of the result set. Add ** terms to the ORDER BY clause as necessary. */ if (op != TK_ALL) { for (i = 1; /* db.mallocFailed == 0 && */ i <= p.pEList.nExpr; i++) { ExprList_item pItem; for (j = 0; j < nOrderBy; j++)//, pItem++) { pItem = pOrderBy.a[j]; Debug.Assert(pItem.iCol > 0); if (pItem.iCol == i) break; } if (j == nOrderBy) { Expr pNew = sqlite3Expr(db, TK_INTEGER, null); //if ( pNew == null ) // return SQLITE_NOMEM; pNew.flags |= EP_IntValue; pNew.u.iValue = i; pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); pOrderBy.a[nOrderBy++].iCol = (u16)i; } } } /* Compute the comparison permutation and keyinfo that is used with ** the permutation used to determine if the next ** row of results comes from selectA or selectB. Also add explicit ** collations to the ORDER BY clause terms so that when the subqueries ** to the right and the left are evaluated, they use the correct ** collation. */ aPermute = new int[nOrderBy];// sqlite3DbMallocRaw( db, sizeof( int ) * nOrderBy ); if (aPermute != null) { ExprList_item pItem; for (i = 0; i < nOrderBy; i++)//, pItem++) { pItem = pOrderBy.a[i]; Debug.Assert(pItem.iCol > 0 && pItem.iCol <= p.pEList.nExpr); aPermute[i] = pItem.iCol - 1; } pKeyMerge = new KeyInfo();// sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq)+1)); if (pKeyMerge != null) { pKeyMerge.aColl = new CollSeq[nOrderBy]; pKeyMerge.aSortOrder = new byte[nOrderBy];//(u8)&pKeyMerge.aColl[nOrderBy]; pKeyMerge.nField = (u16)nOrderBy; pKeyMerge.enc = ENC(db); for (i = 0; i < nOrderBy; i++) { CollSeq pColl; Expr pTerm = pOrderBy.a[i].pExpr; if ((pTerm.flags & EP_ExpCollate) != 0) { pColl = pTerm.pColl; } else { pColl = multiSelectCollSeq(pParse, p, aPermute[i]); pTerm.flags |= EP_ExpCollate; pTerm.pColl = pColl; } pKeyMerge.aColl[i] = pColl; pKeyMerge.aSortOrder[i] = (byte)pOrderBy.a[i].sortOrder; } } } else { pKeyMerge = null; } /* Reattach the ORDER BY clause to the query. */ p.pOrderBy = pOrderBy; pPrior.pOrderBy = sqlite3ExprListDup(pParse.db, pOrderBy, 0); /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL). */ if (op == TK_ALL) { regPrev = 0; } else { int nExpr = p.pEList.nExpr; Debug.Assert(nOrderBy >= nExpr /*|| db.mallocFailed != 0 */ ); regPrev = sqlite3GetTempRange(pParse, nExpr + 1); sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev); pKeyDup = new KeyInfo();//sqlite3DbMallocZero(db, //sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq)+1) ); if (pKeyDup != null) { pKeyDup.aColl = new CollSeq[nExpr]; pKeyDup.aSortOrder = new byte[nExpr];//(u8)&pKeyDup.aColl[nExpr]; pKeyDup.nField = (u16)nExpr; pKeyDup.enc = ENC(db); for (i = 0; i < nExpr; i++) { pKeyDup.aColl[i] = multiSelectCollSeq(pParse, p, i); pKeyDup.aSortOrder[i] = 0; } } } /* Separate the left and the right query from one another */ p.pPrior = null; sqlite3ResolveOrderGroupBy(pParse, p, p.pOrderBy, "ORDER"); if (pPrior.pPrior == null) { sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior.pOrderBy, "ORDER"); } /* Compute the limit registers */ computeLimitRegisters(pParse, p, labelEnd); if (p.iLimit != 0 && op == TK_ALL) { regLimitA = ++pParse.nMem; regLimitB = ++pParse.nMem; sqlite3VdbeAddOp2(v, OP_Copy, (p.iOffset != 0) ? p.iOffset + 1 : p.iLimit, regLimitA); sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB); } else { regLimitA = regLimitB = 0; } sqlite3ExprDelete(db, ref p.pLimit); p.pLimit = null; sqlite3ExprDelete(db, ref p.pOffset); p.pOffset = null; regAddrA = ++pParse.nMem; regEofA = ++pParse.nMem; regAddrB = ++pParse.nMem; regEofB = ++pParse.nMem; regOutA = ++pParse.nMem; regOutB = ++pParse.nMem; sqlite3SelectDestInit(destA, SRT_Coroutine, regAddrA); sqlite3SelectDestInit(destB, SRT_Coroutine, regAddrB); /* Jump past the various subroutines and coroutines to the main ** merge loop */ j1 = sqlite3VdbeAddOp0(v, OP_Goto); addrSelectA = sqlite3VdbeCurrentAddr(v); /* Generate a coroutine to evaluate the SELECT statement to the ** left of the compound operator - the "A" select. */ VdbeNoopComment(v, "Begin coroutine for left SELECT"); pPrior.iLimit = regLimitA; explainSetInteger(ref iSub1, pParse.iNextSelectId); sqlite3Select(pParse, pPrior, ref destA); sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA); sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); VdbeNoopComment(v, "End coroutine for left SELECT"); /* Generate a coroutine to evaluate the SELECT statement on ** the right - the "B" select */ addrSelectB = sqlite3VdbeCurrentAddr(v); VdbeNoopComment(v, "Begin coroutine for right SELECT"); savedLimit = p.iLimit; savedOffset = p.iOffset; p.iLimit = regLimitB; p.iOffset = 0; explainSetInteger(ref iSub2, pParse.iNextSelectId); sqlite3Select(pParse, p, ref destB); p.iLimit = savedLimit; p.iOffset = savedOffset; sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB); sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); VdbeNoopComment(v, "End coroutine for right SELECT"); /* Generate a subroutine that outputs the current row of the A ** select as the next output row of the compound select. */ VdbeNoopComment(v, "Output routine for A"); addrOutA = generateOutputSubroutine(pParse, p, destA, pDest, regOutA, regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd); /* Generate a subroutine that outputs the current row of the B ** select as the next output row of the compound select. */ if (op == TK_ALL || op == TK_UNION) { VdbeNoopComment(v, "Output routine for B"); addrOutB = generateOutputSubroutine(pParse, p, destB, pDest, regOutB, regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd); } /* Generate a subroutine to run when the results from select A ** are exhausted and only data in select B remains. */ VdbeNoopComment(v, "eof-A subroutine"); if (op == TK_EXCEPT || op == TK_INTERSECT) { addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd); } else { addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd); sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA); p.nSelectRow += pPrior.nSelectRow; } /* Generate a subroutine to run when the results from select B ** are exhausted and only data in select A remains. */ if (op == TK_INTERSECT) { addrEofB = addrEofA; if (p.nSelectRow > pPrior.nSelectRow) p.nSelectRow = pPrior.nSelectRow; } else { VdbeNoopComment(v, "eof-B subroutine"); addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd); sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB); } /* Generate code to handle the case of A<B */ VdbeNoopComment(v, "A-lt-B subroutine"); addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA); sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* Generate code to handle the case of A==B */ if (op == TK_ALL) { addrAeqB = addrAltB; } else if (op == TK_INTERSECT) { addrAeqB = addrAltB; addrAltB++; } else { VdbeNoopComment(v, "A-eq-B subroutine"); addrAeqB = sqlite3VdbeAddOp1(v, OP_Yield, regAddrA); sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); } /* Generate code to handle the case of A>B */ VdbeNoopComment(v, "A-gt-B subroutine"); addrAgtB = sqlite3VdbeCurrentAddr(v); if (op == TK_ALL || op == TK_UNION) { sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); } sqlite3VdbeAddOp1(v, OP_Yield, regAddrB); sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, j1); sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA); sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB); sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA); sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB); sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA); sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB); /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy, pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Release temporary registers */ if (regPrev != 0) { sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy + 1); } /* Jump to the this point in order to terminate the query. */ sqlite3VdbeResolveLabel(v, labelEnd); /* Set the number of output columns */ if (pDest.eDest == SRT_Output) { Select pFirst = pPrior; while (pFirst.pPrior != null) pFirst = pFirst.pPrior; generateColumnNames(pParse, null, pFirst.pEList); } /* Reassembly the compound query so that it will be freed correctly ** by the calling function */ if (p.pPrior != null) { sqlite3SelectDelete(db, ref p.pPrior); } p.pPrior = pPrior; /*** TBD: Insert subroutine calls to close cursors on incomplete **** subqueries ****/ explainComposite(pParse, p.op, iSub1, iSub2, false); return SQLITE_OK; }
/* Forward reference */ //static int multiSelectOrderBy( // Parse* pParse, /* Parsing context */ // Select* p, /* The right-most of SELECTs to be coded */ // SelectDest* pDest /* What to do with query results */ //); #if !SQLITE_OMIT_COMPOUND_SELECT /* ** This routine is called to process a compound query form from ** two or more separate queries using UNION, UNION ALL, EXCEPT, or ** INTERSECT ** ** "p" points to the right-most of the two queries. the query on the ** left is p.pPrior. The left query could also be a compound query ** in which case this routine will be called recursively. ** ** The results of the total query are to be written into a destination ** of type eDest with parameter iParm. ** ** Example 1: Consider a three-way compound SQL statement. ** ** SELECT a FROM t1 UNION SELECT b FROM t2 UNION SELECT c FROM t3 ** ** This statement is parsed up as follows: ** ** SELECT c FROM t3 ** | ** `----. SELECT b FROM t2 ** | ** `-----. SELECT a FROM t1 ** ** The arrows in the diagram above represent the Select.pPrior pointer. ** So if this routine is called with p equal to the t3 query, then ** pPrior will be the t2 query. p.op will be TK_UNION in this case. ** ** Notice that because of the way SQLite parses compound SELECTs, the ** individual selects always group from left to right. */ static int multiSelect( Parse pParse, /* Parsing context */ Select p, /* The right-most of SELECTs to be coded */ SelectDest pDest /* What to do with query results */ ) { int rc = SQLITE_OK; /* Success code from a subroutine */ Select pPrior; /* Another SELECT immediately to our left */ Vdbe v; /* Generate code to this VDBE */ SelectDest dest = new SelectDest(); /* Alternative data destination */ Select pDelete = null; /* Chain of simple selects to delete */ sqlite3 db; /* Database connection */ #if !SQLITE_OMIT_EXPLAIN int iSub1 = 0; /* EQP id of left-hand query */ int iSub2 = 0; /* EQP id of right-hand query */ #endif /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs. Only ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. */ Debug.Assert(p != null && p.pPrior != null); /* Calling function guarantees this much */ db = pParse.db; pPrior = p.pPrior; Debug.Assert(pPrior.pRightmost != pPrior); Debug.Assert(pPrior.pRightmost == p.pRightmost); dest = pDest; if (pPrior.pOrderBy != null) { sqlite3ErrorMsg(pParse, "ORDER BY clause should come after %s not before", selectOpName(p.op)); rc = 1; goto multi_select_end; } if (pPrior.pLimit != null) { sqlite3ErrorMsg(pParse, "LIMIT clause should come after %s not before", selectOpName(p.op)); rc = 1; goto multi_select_end; } v = sqlite3GetVdbe(pParse); Debug.Assert(v != null); /* The VDBE already created by calling function */ /* Create the destination temporary table if necessary */ if (dest.eDest == SRT_EphemTab) { Debug.Assert(p.pEList != null); sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p.pEList.nExpr); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); dest.eDest = SRT_Table; } /* Make sure all SELECTs in the statement have the same number of elements ** in their result sets. */ Debug.Assert(p.pEList != null && pPrior.pEList != null); if (p.pEList.nExpr != pPrior.pEList.nExpr) { 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; } /* Compound SELECTs that have an ORDER BY clause are handled separately. */ if (p.pOrderBy != null) { return multiSelectOrderBy(pParse, p, pDest); } /* Generate code for the left and right SELECT statements. */ switch (p.op) { case TK_ALL: { int addr = 0; int nLimit = 0; Debug.Assert(pPrior.pLimit == null); pPrior.pLimit = p.pLimit; pPrior.pOffset = p.pOffset; explainSetInteger(ref iSub1, pParse.iNextSelectId); rc = sqlite3Select(pParse, pPrior, ref dest); p.pLimit = null; p.pOffset = null; if (rc != 0) { goto multi_select_end; } p.pPrior = null; p.iLimit = pPrior.iLimit; p.iOffset = pPrior.iOffset; if (p.iLimit != 0) { addr = sqlite3VdbeAddOp1(v, OP_IfZero, p.iLimit); #if SQLITE_DEBUG VdbeComment( v, "Jump ahead if LIMIT reached" ); #endif } explainSetInteger(ref iSub2, pParse.iNextSelectId); rc = sqlite3Select(pParse, p, ref dest); testcase(rc != SQLITE_OK); pDelete = p.pPrior; p.pPrior = pPrior; p.nSelectRow += pPrior.nSelectRow; if (pPrior.pLimit != null && sqlite3ExprIsInteger(pPrior.pLimit, ref nLimit) != 0 && p.nSelectRow > (double)nLimit ) { p.nSelectRow = (double)nLimit; } if (addr != 0) { sqlite3VdbeJumpHere(v, addr); } break; } case TK_EXCEPT: case TK_UNION: { int unionTab; /* VdbeCursor number of the temporary table holding result */ u8 op = 0; /* One of the SRT_ operations to apply to self */ int priorOp; /* The SRT_ operation to apply to prior selects */ Expr pLimit, pOffset; /* Saved values of p.nLimit and p.nOffset */ int addr; SelectDest uniondest = new SelectDest(); testcase(p.op == TK_EXCEPT); testcase(p.op == TK_UNION); priorOp = SRT_Union; if (dest.eDest == priorOp && ALWAYS(null == p.pLimit && null == p.pOffset)) { /* We can reuse a temporary table generated by a SELECT to our ** right. */ Debug.Assert(p.pRightmost != p); /* Can only happen for leftward elements ** of a 3-way or more compound */ Debug.Assert(p.pLimit == null); /* Not allowed on leftward elements */ Debug.Assert(p.pOffset == null); /* Not allowed on leftward elements */ unionTab = dest.iParm; } else { /* We will need to create our own temporary table to hold the ** intermediate results. */ unionTab = pParse.nTab++; Debug.Assert(p.pOrderBy == null); addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0); Debug.Assert(p.addrOpenEphm[0] == -1); p.addrOpenEphm[0] = addr; p.pRightmost.selFlags |= SF_UsesEphemeral; Debug.Assert(p.pEList != null); } /* Code the SELECT statements to our left */ Debug.Assert(pPrior.pOrderBy == null); sqlite3SelectDestInit(uniondest, priorOp, unionTab); explainSetInteger(ref iSub1, pParse.iNextSelectId); rc = sqlite3Select(pParse, pPrior, ref uniondest); if (rc != 0) { goto multi_select_end; } /* Code the current SELECT statement */ if (p.op == TK_EXCEPT) { op = SRT_Except; } else { Debug.Assert(p.op == TK_UNION); op = SRT_Union; } p.pPrior = null; pLimit = p.pLimit; p.pLimit = null; pOffset = p.pOffset; p.pOffset = null; uniondest.eDest = op; explainSetInteger(ref iSub2, pParse.iNextSelectId); rc = sqlite3Select(pParse, p, ref uniondest); testcase(rc != SQLITE_OK); /* Query flattening in sqlite3Select() might refill p.pOrderBy. ** Be sure to delete p.pOrderBy, therefore, to avoid a memory leak. */ sqlite3ExprListDelete(db, ref p.pOrderBy); pDelete = p.pPrior; p.pPrior = pPrior; p.pOrderBy = null; if (p.op == TK_UNION) p.nSelectRow += pPrior.nSelectRow; sqlite3ExprDelete(db, ref p.pLimit); p.pLimit = pLimit; p.pOffset = pOffset; p.iLimit = 0; p.iOffset = 0; /* Convert the data in the temporary table into whatever form ** it is that we currently need. */ Debug.Assert(unionTab == dest.iParm || dest.eDest != priorOp); if (dest.eDest != priorOp) { int iCont, iBreak, iStart; Debug.Assert(p.pEList != null); if (dest.eDest == SRT_Output) { Select pFirst = p; while (pFirst.pPrior != null) pFirst = pFirst.pPrior; generateColumnNames(pParse, null, pFirst.pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak); iStart = sqlite3VdbeCurrentAddr(v); selectInnerLoop(pParse, p, p.pEList, unionTab, p.pEList.nExpr, null, -1, dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0); } break; } default: Debug.Assert(p.op == TK_INTERSECT); { int tab1, tab2; int iCont, iBreak, iStart; Expr pLimit, pOffset; int addr; SelectDest intersectdest = new SelectDest(); int r1; /* INTERSECT is different from the others since it requires ** two temporary tables. Hence it has its own case. Begin ** by allocating the tables we will need. */ tab1 = pParse.nTab++; tab2 = pParse.nTab++; Debug.Assert(p.pOrderBy == null); addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0); Debug.Assert(p.addrOpenEphm[0] == -1); p.addrOpenEphm[0] = addr; p.pRightmost.selFlags |= SF_UsesEphemeral; Debug.Assert(p.pEList != null); /* Code the SELECTs to our left into temporary table "tab1". */ sqlite3SelectDestInit(intersectdest, SRT_Union, tab1); explainSetInteger(ref iSub1, pParse.iNextSelectId); rc = sqlite3Select(pParse, pPrior, ref intersectdest); if (rc != 0) { goto multi_select_end; } /* Code the current SELECT into temporary table "tab2" */ addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0); Debug.Assert(p.addrOpenEphm[1] == -1); p.addrOpenEphm[1] = addr; p.pPrior = null; pLimit = p.pLimit; p.pLimit = null; pOffset = p.pOffset; p.pOffset = null; intersectdest.iParm = tab2; explainSetInteger(ref iSub2, pParse.iNextSelectId); rc = sqlite3Select(pParse, p, ref intersectdest); testcase(rc != SQLITE_OK); p.pPrior = pPrior; if (p.nSelectRow > pPrior.nSelectRow) p.nSelectRow = pPrior.nSelectRow; sqlite3ExprDelete(db, ref p.pLimit); p.pLimit = pLimit; p.pOffset = pOffset; /* Generate code to take the intersection of the two temporary ** tables. */ Debug.Assert(p.pEList != null); if (dest.eDest == SRT_Output) { Select pFirst = p; while (pFirst.pPrior != null) pFirst = pFirst.pPrior; generateColumnNames(pParse, null, pFirst.pEList); } iBreak = sqlite3VdbeMakeLabel(v); iCont = sqlite3VdbeMakeLabel(v); computeLimitRegisters(pParse, p, iBreak); sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak); r1 = sqlite3GetTempReg(pParse); iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1); sqlite3VdbeAddOp4Int(v, OP_NotFound, tab2, iCont, r1, 0); sqlite3ReleaseTempReg(pParse, r1); selectInnerLoop(pParse, p, p.pEList, tab1, p.pEList.nExpr, null, -1, dest, iCont, iBreak); sqlite3VdbeResolveLabel(v, iCont); sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart); sqlite3VdbeResolveLabel(v, iBreak); sqlite3VdbeAddOp2(v, OP_Close, tab2, 0); sqlite3VdbeAddOp2(v, OP_Close, tab1, 0); break; } } explainComposite(pParse, p.op, iSub1, iSub2, p.op != TK_ALL); /* Compute collating sequences used by ** temporary tables needed to implement the compound select. ** Attach the KeyInfo structure to all temporary tables. ** ** This section is run by the right-most SELECT statement only. ** SELECT statements to the left always skip this part. The right-most ** SELECT might also skip this part if it has no ORDER BY clause and ** no temp tables are required. */ if ((p.selFlags & SF_UsesEphemeral) != 0) { int i; /* Loop counter */ KeyInfo pKeyInfo; /* Collating sequence for the result set */ Select pLoop; /* For looping through SELECT statements */ CollSeq apColl; /* For looping through pKeyInfo.aColl[] */ int nCol; /* Number of columns in result set */ Debug.Assert(p.pRightmost == p); nCol = p.pEList.nExpr; pKeyInfo = new KeyInfo(); //sqlite3DbMallocZero(db, pKeyInfo.aColl = new CollSeq[nCol]; //sizeof(*pKeyInfo)+nCol*(CollSeq*.Length + 1)); //if ( pKeyInfo == null ) //{ // rc = SQLITE_NOMEM; // goto multi_select_end; //} pKeyInfo.enc = db.aDbStatic[0].pSchema.enc;// ENC( pParse.db ); pKeyInfo.nField = (u16)nCol; for (i = 0; i < nCol; i++) {//, apColl++){ apColl = multiSelectCollSeq(pParse, p, i); if (null == apColl) { apColl = db.pDfltColl; } pKeyInfo.aColl[i] = apColl; } for (pLoop = p; pLoop != null; pLoop = pLoop.pPrior) { for (i = 0; i < 2; i++) { int addr = pLoop.addrOpenEphm[i]; if (addr < 0) { /* If [0] is unused then [1] is also unused. So we can ** always safely abort as soon as the first unused slot is found */ Debug.Assert(pLoop.addrOpenEphm[1] < 0); break; } sqlite3VdbeChangeP2(v, addr, nCol); sqlite3VdbeChangeP4(v, addr, pKeyInfo, P4_KEYINFO); pLoop.addrOpenEphm[i] = -1; } } sqlite3DbFree(db, ref pKeyInfo); } multi_select_end: pDest.iMem = dest.iMem; pDest.nMem = dest.nMem; sqlite3SelectDelete(db, ref pDelete); return rc; }
/* ** Return the appropriate collating sequence for the iCol-th column of ** the result set for the compound-select statement "p". Return NULL if ** the column has no default collating sequence. ** ** The collating sequence for the compound select is taken from the ** left-most term of the select that has a collating sequence. */ static CollSeq multiSelectCollSeq(Parse pParse, Select p, int iCol) { CollSeq pRet; if (p.pPrior != null) { pRet = multiSelectCollSeq(pParse, p.pPrior, iCol); } else { pRet = null; } Debug.Assert(iCol >= 0); if (pRet == null && iCol < p.pEList.nExpr) { pRet = sqlite3ExprCollSeq(pParse, p.pEList.a[iCol].pExpr); } return pRet; }
/* ** Compute the iLimit and iOffset fields of the SELECT based on the ** pLimit and pOffset expressions. pLimit and pOffset hold the expressions ** that appear in the original SQL statement after the LIMIT and OFFSET ** keywords. Or NULL if those keywords are omitted. iLimit and iOffset ** are the integer memory register numbers for counters used to compute ** the limit and offset. If there is no limit and/or offset, then ** iLimit and iOffset are negative. ** ** This routine changes the values of iLimit and iOffset only if ** a limit or offset is defined by pLimit and pOffset. iLimit and ** iOffset should have been preset to appropriate default values ** (usually but not always -1) prior to calling this routine. ** Only if pLimit!=0 or pOffset!=0 do the limit registers get ** redefined. The UNION ALL operator uses this property to force ** the reuse of the same limit and offset registers across multiple ** SELECT statements. */ static void computeLimitRegisters(Parse pParse, Select p, int iBreak) { Vdbe v = null; int iLimit = 0; int iOffset; int addr1, n = 0; if (p.iLimit != 0) return; /* ** "LIMIT -1" always shows all rows. There is some ** contraversy about what the correct behavior should be. ** The current implementation interprets "LIMIT 0" to mean ** no rows. */ sqlite3ExprCacheClear(pParse); Debug.Assert(p.pOffset == null || p.pLimit != null); if (p.pLimit != null) { p.iLimit = iLimit = ++pParse.nMem; v = sqlite3GetVdbe(pParse); if (NEVER(v == null)) return; /* VDBE should have already been allocated */ if (sqlite3ExprIsInteger(p.pLimit, ref n) != 0) { sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit); VdbeComment(v, "LIMIT counter"); if (n == 0) { sqlite3VdbeAddOp2(v, OP_Goto, 0, iBreak); } else { if (p.nSelectRow > (double)n) p.nSelectRow = (double)n; } } else { sqlite3ExprCode(pParse, p.pLimit, iLimit); sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); #if SQLITE_DEBUG VdbeComment( v, "LIMIT counter" ); #endif sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); } if (p.pOffset != null) { p.iOffset = iOffset = ++pParse.nMem; pParse.nMem++; /* Allocate an extra register for limit+offset */ sqlite3ExprCode(pParse, p.pOffset, iOffset); sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); #if SQLITE_DEBUG VdbeComment( v, "OFFSET counter" ); #endif addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset + 1); #if SQLITE_DEBUG VdbeComment( v, "LIMIT+OFFSET" ); #endif addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset + 1); sqlite3VdbeJumpHere(v, addr1); } } }
/* ** This routine processes the join information for a SELECT statement. ** ON and USING clauses are converted into extra terms of the WHERE clause. ** NATURAL joins also create extra WHERE clause terms. ** ** The terms of a FROM clause are contained in the Select.pSrc structure. ** The left most table is the first entry in Select.pSrc. The right-most ** table is the last entry. The join operator is held in the entry to ** the left. Thus entry 0 contains the join operator for the join between ** entries 0 and 1. Any ON or USING clauses associated with the join are ** also attached to the left entry. ** ** This routine returns the number of errors encountered. */ static int sqliteProcessJoin(Parse pParse, Select p) { SrcList pSrc; /* All tables in the FROM clause */ int i; int j; /* Loop counters */ SrcList_item pLeft; /* Left table being joined */ SrcList_item pRight; /* Right table being joined */ pSrc = p.pSrc; //pLeft = pSrc.a[0]; //pRight = pLeft[1]; for (i = 0; i < pSrc.nSrc - 1; i++) { pLeft = pSrc.a[i]; // pLeft ++ pRight = pSrc.a[i + 1];//Right++, Table pLeftTab = pLeft.pTab; Table pRightTab = pRight.pTab; bool isOuter; if (NEVER(pLeftTab == null || pRightTab == null)) continue; isOuter = (pRight.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) != 0) { if (pRight.pOn != null || pRight.pUsing != null) { sqlite3ErrorMsg(pParse, "a NATURAL join may not have " + "an ON or USING clause", ""); return 1; } for (j = 0; j < pRightTab.nCol; j++) { string zName; /* Name of column in the right table */ int iLeft = 0; /* Matching left table */ int iLeftCol = 0; /* Matching column in the left table */ zName = pRightTab.aCol[j].zName; int iRightCol = columnIndex(pRightTab, zName); if (tableAndColumnIndex(pSrc, i + 1, zName, ref iLeft, ref iLeftCol) != 0) { addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i + 1, j, isOuter ? 1 : 0, ref p.pWhere); } } } /* Disallow both ON and USING clauses in the same join */ if (pRight.pOn != null && pRight.pUsing != null) { sqlite3ErrorMsg(pParse, "cannot have both ON and USING " + "clauses in the same join"); return 1; } /* Add the ON clause to the end of the WHERE clause, connected by ** an AND operator. */ if (pRight.pOn != null) { if (isOuter) setJoinExpr(pRight.pOn, pRight.iCursor); p.pWhere = sqlite3ExprAnd(pParse.db, p.pWhere, pRight.pOn); pRight.pOn = null; } /* Create extra terms on the WHERE clause for each column named ** in the USING clause. Example: If the two tables to be joined are ** A and B and the USING clause names X, Y, and Z, then add this ** to the WHERE clause: A.X=B.X AND A.Y=B.Y AND A.Z=B.Z ** Report an error if any column mentioned in the USING clause is ** not contained in both tables to be joined. */ if (pRight.pUsing != null) { IdList pList = pRight.pUsing; for (j = 0; j < pList.nId; j++) { string zName; /* Name of the term in the USING clause */ int iLeft = 0; /* Table on the left with matching column name */ int iLeftCol = 0; /* Column number of matching column on the left */ int iRightCol; /* Column number of matching column on the right */ zName = pList.a[j].zName; iRightCol = columnIndex(pRightTab, zName); if (iRightCol < 0 || 0 == tableAndColumnIndex(pSrc, i + 1, zName, ref iLeft, ref iLeftCol) ) { sqlite3ErrorMsg(pParse, "cannot join using column %s - column " + "not present in both tables", zName); return 1; } addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i + 1, iRightCol, isOuter ? 1 : 0, ref p.pWhere); } } } return 0; }
/* ** This routine adds datatype and collating sequence information to ** the Table ures of all FROM-clause subqueries in a ** SELECT statement. ** ** Use this routine after name resolution. */ static void sqlite3SelectAddTypeInfo(Parse pParse, Select pSelect) { #if !SQLITE_OMIT_SUBQUERY Walker w = new Walker(); w.xSelectCallback = selectAddSubqueryTypeInfo; w.xExprCallback = exprWalkNoop; w.pParse = pParse; sqlite3WalkSelect(w, pSelect); #endif }
/// <summary> /// pE is a pointer to an expression which is a single term in the /// ORDER BY of a compound SELECT. The expression has not been /// name resolved. /// /// At the point this routine is called, we already know that the /// ORDER BY term is not an integer index into the result set. That /// case is handled by the calling routine. /// /// Attempt to match pE against result set columns in the left-most /// SELECT statement. Return the index i of the matching column, /// as an indication to the caller that it should sort by the i-th column. /// The left-most column is 1. In other words, the value returned is the /// same integer value that would be used in the SQL statement to indicate /// the column /// </summary> /// <returns> /// If there is no match, return 0. Return -1 if an error occurs. /// </returns> /// <param name='pParse'> /// Parsing context for error messages /// </param> /// <param name='pSelect'> /// The SELECT statement with the ORDER BY clause /// </param> /// <param name='pE'> /// The specific ORDER BY term /// </param> static int resolveOrderByTermToExprList(Parse pParse, Select pSelect, Expr pE) { int i = 0; /* Loop counter */ ExprList pEList; /* The columns of the result set */ NameContext nc; /* Name context for resolving pE */ sqlite3 db; /* Database connection */ int rc; /* Return code from subprocedures */ u8 savedSuppErr; /* Saved value of db->suppressErr */ Debug.Assert(sqlite3ExprIsInteger(pE, ref i) == 0); pEList = pSelect.pEList; /* Resolve all names in the ORDER BY term expression */ nc = new NameContext();// memset( &nc, 0, sizeof( nc ) ); nc.pParse = pParse; nc.pSrcList = pSelect.pSrc; nc.pEList = pEList; nc.allowAgg = 1; nc.nErr = 0; db = pParse.db; savedSuppErr = db.suppressErr; db.suppressErr = 1; rc = sqlite3ResolveExprNames(nc, ref pE); db.suppressErr = savedSuppErr; if (rc != 0) return 0; /* Try to match the ORDER BY expression against an expression ** in the result set. Return an 1-based index of the matching ** result-set entry. */ for (i = 0; i < pEList.nExpr; i++) { if (sqlite3ExprCompare(pEList.a[i].pExpr, pE) < 2) { return i + 1; } } return 0; }
/// <summary> /// Analyze the ORDER BY clause in a compound SELECT statement. Modify /// each term of the ORDER BY clause is a constant integer between 1 /// and N where N is the number of columns in the compound SELECT. /// /// ORDER BY terms that are already an integer between 1 and N are /// unmodified. ORDER BY terms that are integers outside the range of /// 1 through N generate an error. ORDER BY terms that are expressions /// are matched against result set expressions of compound SELECT /// beginning with the left-most SELECT and working toward the right. /// At the first match, the ORDER BY expression is transformed into /// the integer column number /// </summary> /// <returns> /// Return the number of errors seen. /// </returns> /// <param name='pParse'> /// Parsing context. Leave error messages here /// </param> /// <param name='pSelect'> /// The SELECT statement containing the ORDER BY /// </param> static int resolveCompoundOrderBy(Parse pParse, Select pSelect) { int i; ExprList pOrderBy; ExprList pEList; sqlite3 db; int moreToDo = 1; pOrderBy = pSelect.pOrderBy; if (pOrderBy == null) return 0; db = pParse.db; //#if SQLITE_MAX_COLUMN if (pOrderBy.nExpr > db.aLimit[SQLITE_LIMIT_COLUMN]) { sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause"); return 1; } //#endif for (i = 0; i < pOrderBy.nExpr; i++) { pOrderBy.a[i].done = 0; } pSelect.pNext = null; while (pSelect.pPrior != null) { pSelect.pPrior.pNext = pSelect; pSelect = pSelect.pPrior; } while (pSelect != null && moreToDo != 0) { ExprList_item pItem; moreToDo = 0; pEList = pSelect.pEList; Debug.Assert(pEList != null); for (i = 0; i < pOrderBy.nExpr; i++)//, pItem++) { pItem = pOrderBy.a[i]; int iCol = -1; Expr pE, pDup; if (pItem.done != 0) continue; pE = pItem.pExpr; if (sqlite3ExprIsInteger(pE, ref iCol) != 0) { if (iCol <= 0 || iCol > pEList.nExpr) { resolveOutOfRangeError(pParse, "ORDER", i + 1, pEList.nExpr); return 1; } } else { iCol = resolveAsName(pParse, pEList, pE); if (iCol == 0) { pDup = sqlite3ExprDup(db, pE, 0); ////if ( 0 == db.mallocFailed ) { Debug.Assert(pDup != null); iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); } sqlite3ExprDelete(db, ref pDup); } } if (iCol > 0) { CollSeq pColl = pE.pColl; int flags = pE.flags & EP_ExpCollate; sqlite3ExprDelete(db, ref pE); pItem.pExpr = pE = sqlite3Expr(db, TK_INTEGER, null); if (pE == null) return 1; pE.pColl = pColl; pE.flags = (u16)(pE.flags | EP_IntValue | flags); pE.u.iValue = iCol; pItem.iCol = (u16)iCol; pItem.done = 1; } else { moreToDo = 1; } } pSelect = pSelect.pNext; } for (i = 0; i < pOrderBy.nExpr; i++) { if (pOrderBy.a[i].done == 0) { sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any " + "column in the result set", i + 1); return 1; } } return 0; }
/* ** Add type and collation information to a column list based on ** a SELECT statement. ** ** The column list presumably came from selectColumnNamesFromExprList(). ** The column list has only names, not types or collations. This ** routine goes through and adds the types and collations. ** ** This routine requires that all identifiers in the SELECT ** statement be resolved. */ static void selectAddColumnTypeAndCollation( Parse pParse, /* Parsing contexts */ int nCol, /* Number of columns */ Column[] aCol, /* List of columns */ Select pSelect /* SELECT used to determine types and collations */ ) { sqlite3 db = pParse.db; NameContext sNC; Column pCol; CollSeq pColl; int i; Expr p; ExprList_item[] a; Debug.Assert(pSelect != null); Debug.Assert((pSelect.selFlags & SF_Resolved) != 0); Debug.Assert(nCol == pSelect.pEList.nExpr /*|| db.mallocFailed != 0 */ ); // if ( db.mallocFailed != 0 ) return; sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) ); sNC.pSrcList = pSelect.pSrc; a = pSelect.pEList.a; for (i = 0; i < nCol; i++)//, pCol++ ) { pCol = aCol[i]; p = a[i].pExpr; string bDummy = null; pCol.zType = columnType(sNC, p, ref bDummy, ref bDummy, ref bDummy);// sqlite3DbStrDup( db, columnType( sNC, p, 0, 0, 0 ) ); pCol.affinity = sqlite3ExprAffinity(p); if (pCol.affinity == 0) pCol.affinity = SQLITE_AFF_NONE; pColl = sqlite3ExprCollSeq(pParse, p); if (pColl != null) { pCol.zColl = pColl.zName;// sqlite3DbStrDup( db, pColl.zName ); } } }
/* ** Check every term in the ORDER BY or GROUP BY clause pOrderBy of ** the SELECT statement pSelect. If any term is reference to a ** result set expression (as determined by the ExprList.a.iCol field) ** then convert that term into a copy of the corresponding result set ** column. ** ** If any errors are detected, add an error message to pParse and ** return non-zero. Return zero if no errors are seen. */ static int sqlite3ResolveOrderGroupBy( Parse pParse, /* Parsing context. Leave error messages here */ Select pSelect, /* The SELECT statement containing the clause */ ExprList pOrderBy, /* The ORDER BY or GROUP BY clause to be processed */ string zType /* "ORDER" or "GROUP" */ ) { int i; sqlite3 db = pParse.db; ExprList pEList; ExprList_item pItem; if (pOrderBy == null /* || pParse.db.mallocFailed != 0 */ ) return 0; //#if SQLITE_MAX_COLUMN if (pOrderBy.nExpr > db.aLimit[SQLITE_LIMIT_COLUMN]) { sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType); return 1; } //#endif pEList = pSelect.pEList; Debug.Assert(pEList != null); /* sqlite3SelectNew() guarantees this */ for (i = 0; i < pOrderBy.nExpr; i++)//, pItem++) { pItem = pOrderBy.a[i]; if (pItem.iCol != 0) { if (pItem.iCol > pEList.nExpr) { resolveOutOfRangeError(pParse, zType, i + 1, pEList.nExpr); return 1; } resolveAlias(pParse, pEList, pItem.iCol - 1, pItem.pExpr, zType); } } return 0; }
/// <summary> /// Resolve all names in all expressions of a SELECT and in all /// decendents of the SELECT, including compounds off of p.pPrior, /// subqueries in expressions, and subqueries used as FROM clause /// terms. /// /// See sqlite3ResolveExprNames() for a description of the kinds of /// transformations that occur. /// /// All SELECT statements should have been expanded using /// sqlite3SelectExpand() prior to invoking this routine. /// </summary> /// <param name='pParse'> /// The parser context /// </param> /// <param name='p'> /// The SELECT statement being coded. /// </param> /// <param name='pOuterNC'> /// Name context for parent SELECT statement /// </param> static void sqlite3ResolveSelectNames(Parse pParse, Select p, NameContext pOuterNC) { Walker w = new Walker(); Debug.Assert(p != null); w.xExprCallback = resolveExprStep; w.xSelectCallback = resolveSelectStep; w.pParse = pParse; w.u.pNC = pOuterNC; sqlite3WalkSelect(w, p); }
/// <summary> /// pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. /// The Name context of the SELECT statement is pNC. zType is either /// "ORDER" or "GROUP" depending on which type of clause pOrderBy is. /// /// This routine resolves each term of the clause into an expression. /// If the order-by term is an integer I between 1 and N (where N is the /// number of columns in the result set of the SELECT) then the expression /// in the resolution is a copy of the I-th result-set expression. If /// the order-by term is an identify that corresponds to the AS-name of /// a result-set expression, then the term resolves to a copy of the /// result-set expression. Otherwise, the expression is resolved in /// the usual way - using sqlite3ResolveExprNames(). /// </summary> /// <returns> /// This routine returns the number of errors. If errors occur, then /// an appropriate error message might be left in pParse. (OOM errors /// excepted.) /// </returns> /// <param name='pNC'> /// The name context of the SELECT statement /// </param> /// <param name='pSelect'> /// The SELECT statement holding pOrderBy /// </param> /// <param name='pOrderBy'> /// An ORDER BY or GROUP BY clause to resolve /// </param> /// <param name='zType'> /// Either "ORDER" or "GROUP", as appropriate /// </param> static int resolveOrderGroupBy(NameContext pNC, Select pSelect, ExprList pOrderBy, string zType) { int i; /* Loop counter */ int iCol; /* Column number */ ExprList_item pItem; /* A term of the ORDER BY clause */ Parse pParse; /* Parsing context */ int nResult; /* Number of terms in the result set */ if (pOrderBy == null) return 0; nResult = pSelect.pEList.nExpr; pParse = pNC.pParse; for (i = 0; i < pOrderBy.nExpr; i++)//, pItem++ ) { pItem = pOrderBy.a[i]; Expr pE = pItem.pExpr; iCol = resolveAsName(pParse, pSelect.pEList, pE); if (iCol > 0) { /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ pItem.iCol = (u16)iCol; } else if (sqlite3ExprIsInteger(pE, ref iCol) != 0) { /* The ORDER BY term is an integer constant. Again, set the column ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if (iCol < 1) { resolveOutOfRangeError(pParse, zType, i + 1, nResult); return 1; } pItem.iCol = (u16)iCol; } else // Otherwise, treat the ORDER BY term as an ordinary expression { pItem.iCol = 0; if (sqlite3ResolveExprNames(pNC, ref pE) != 0) { return 1; } } } return sqlite3ResolveOrderGroupBy(pParse, pSelect, pOrderBy, zType); }
/// <summary> /// Resolve names in the SELECT statement p and all of its descendents. /// </summary> /// <returns> /// The select step. /// </returns> /// <param name='pWalker'> /// P walker. /// </param> /// <param name='p'> /// P. /// </param> static int resolveSelectStep(Walker pWalker, Select p) { NameContext pOuterNC; /* Context that contains this SELECT */ NameContext sNC; /* Name context of this SELECT */ bool isCompound; /* True if p is a compound select */ int nCompound; /* Number of compound terms processed so far */ Parse pParse; /* Parsing context */ ExprList pEList; /* Result set expression list */ int i; /* Loop counter */ ExprList pGroupBy; /* The GROUP BY clause */ Select pLeftmost; /* Left-most of SELECT of a compound */ sqlite3 db; /* Database connection */ Debug.Assert(p != null); if ((p.selFlags & SF_Resolved) != 0) { return WRC_Prune; } pOuterNC = pWalker.u.pNC; pParse = pWalker.pParse; db = pParse.db; /* Normally sqlite3SelectExpand() will be called first and will have ** already expanded this SELECT. However, if this is a subquery within ** an expression, sqlite3ResolveExprNames() will be called without a ** prior call to sqlite3SelectExpand(). When that happens, let ** sqlite3SelectPrep() do all of the processing for this SELECT. ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and ** this routine in the correct order. */ if ((p.selFlags & SF_Expanded) == 0) { sqlite3SelectPrep(pParse, p, pOuterNC); return (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) ? WRC_Abort : WRC_Prune; } isCompound = p.pPrior != null; nCompound = 0; pLeftmost = p; while (p != null) { Debug.Assert((p.selFlags & SF_Expanded) != 0); Debug.Assert((p.selFlags & SF_Resolved) == 0); p.selFlags |= SF_Resolved; /* Resolve the expressions in the LIMIT and OFFSET clauses. These ** are not allowed to refer to any names, so pass an empty NameContext. */ sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) ); sNC.pParse = pParse; if (sqlite3ResolveExprNames(sNC, ref p.pLimit) != 0 || sqlite3ResolveExprNames(sNC, ref p.pOffset) != 0) { return WRC_Abort; } /* Set up the local name-context to pass to sqlite3ResolveExprNames() to ** resolve the result-set expression list. */ sNC.allowAgg = 1; sNC.pSrcList = p.pSrc; sNC.pNext = pOuterNC; /* Resolve names in the result set. */ pEList = p.pEList; Debug.Assert(pEList != null); for (i = 0; i < pEList.nExpr; i++) { Expr pX = pEList.a[i].pExpr; if (sqlite3ResolveExprNames(sNC, ref pX) != 0) { return WRC_Abort; } } /* Recursively resolve names in all subqueries */ for (i = 0; i < p.pSrc.nSrc; i++) { SrcList_item pItem = p.pSrc.a[i]; if (pItem.pSelect != null) { string zSavedContext = pParse.zAuthContext; if (pItem.zName != null) pParse.zAuthContext = pItem.zName; sqlite3ResolveSelectNames(pParse, pItem.pSelect, pOuterNC); pParse.zAuthContext = zSavedContext; if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) return WRC_Abort; } } /* If there are no aggregate functions in the result-set, and no GROUP BY ** expression, do not allow aggregates in any of the other expressions. */ Debug.Assert((p.selFlags & SF_Aggregate) == 0); pGroupBy = p.pGroupBy; if (pGroupBy != null || sNC.hasAgg != 0) { p.selFlags |= SF_Aggregate; } else { sNC.allowAgg = 0; } /* If a HAVING clause is present, then there must be a GROUP BY clause. */ if (p.pHaving != null && pGroupBy == null) { sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); return WRC_Abort; } /* Add the expression list to the name-context before parsing the ** other expressions in the SELECT statement. This is so that ** expressions in the WHERE clause (etc.) can refer to expressions by ** aliases in the result set. ** ** Minor point: If this is the case, then the expression will be ** re-evaluated for each reference to it. */ sNC.pEList = p.pEList; if (sqlite3ResolveExprNames(sNC, ref p.pWhere) != 0 || sqlite3ResolveExprNames(sNC, ref p.pHaving) != 0 ) { return WRC_Abort; } /* The ORDER BY and GROUP BY clauses may not refer to terms in ** outer queries */ sNC.pNext = null; sNC.allowAgg = 1; /* Process the ORDER BY clause for singleton SELECT statements. ** The ORDER BY clause for compounds SELECT statements is handled ** below, after all of the result-sets for all of the elements of ** the compound have been resolved. */ if (!isCompound && resolveOrderGroupBy(sNC, p, p.pOrderBy, "ORDER") != 0) { return WRC_Abort; } /* Resolve the GROUP BY clause. At the same time, make sure ** the GROUP BY clause does not contain aggregate functions. */ if (pGroupBy != null) { ExprList_item pItem; if (resolveOrderGroupBy(sNC, p, pGroupBy, "GROUP") != 0 /*|| db.mallocFailed != 0 */ ) { return WRC_Abort; } for (i = 0; i < pGroupBy.nExpr; i++)//, pItem++) { pItem = pGroupBy.a[i]; if ((pItem.pExpr.flags & EP_Agg) != 0)//HasProperty(pItem.pExpr, EP_Agg) ) { sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " + "the GROUP BY clause"); return WRC_Abort; } } } /* Advance to the next term of the compound */ p = p.pPrior; nCompound++; } /* Resolve the ORDER BY on a compound SELECT after all terms of ** the compound have been resolved. */ if (isCompound && resolveCompoundOrderBy(pParse, pLeftmost) != 0) { return WRC_Abort; } return WRC_Prune; }
/* ** This routine generates the code for the inside of the inner loop ** of a SELECT. ** ** If srcTab and nColumn are both zero, then the pEList expressions ** are evaluated in order to get the data for this row. If nColumn>0 ** then data is pulled from srcTab and pEList is used only to get the ** datatypes for each column. */ static void selectInnerLoop( Parse pParse, /* The parser context */ Select p, /* The complete select statement being coded */ ExprList pEList, /* List of values being extracted */ int srcTab, /* Pull data from this table */ int nColumn, /* Number of columns in the source table */ ExprList pOrderBy, /* If not NULL, sort results using this key */ int distinct, /* If >=0, make sure results are distinct */ SelectDest pDest, /* How to dispose of the results */ int iContinue, /* Jump here to continue with next row */ int iBreak /* Jump here to break out of the inner loop */ ) { Vdbe v = pParse.pVdbe; int i; bool hasDistinct; /* True if the DISTINCT keyword is present */ int regResult; /* Start of memory holding result set */ int eDest = pDest.eDest; /* How to dispose of results */ int iParm = pDest.iParm; /* First argument to disposal method */ int nResultCol; /* Number of result columns */ Debug.Assert(v != null); if (NEVER(v == null)) return; Debug.Assert(pEList != null); hasDistinct = distinct >= 0; if (pOrderBy == null && !hasDistinct) { codeOffset(v, p, iContinue); } /* Pull the requested columns. */ if (nColumn > 0) { nResultCol = nColumn; } else { nResultCol = pEList.nExpr; } if (pDest.iMem == 0) { pDest.iMem = pParse.nMem + 1; pDest.nMem = nResultCol; pParse.nMem += nResultCol; } else { Debug.Assert(pDest.nMem == nResultCol); } regResult = pDest.iMem; if (nColumn > 0) { for (i = 0; i < nColumn; i++) { sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult + i); } } else if (eDest != SRT_Exists) { /* If the destination is an EXISTS(...) expression, the actual ** values returned by the SELECT are not required. */ sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest == SRT_Output); } nColumn = nResultCol; /* If the DISTINCT keyword was present on the SELECT statement ** and this row has been seen before, then do not make this row ** part of the result. */ if (hasDistinct) { Debug.Assert(pEList != null); Debug.Assert(pEList.nExpr == nColumn); codeDistinct(pParse, distinct, iContinue, nColumn, regResult); if (pOrderBy == null) { codeOffset(v, p, iContinue); } } switch (eDest) { /* In this mode, write each query result to the key of the temporary ** table iParm. */ #if !SQLITE_OMIT_COMPOUND_SELECT case SRT_Union: { int r1; r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); break; } /* Construct a record from the query result, but instead of ** saving that record, use it as a key to delete elements from ** the temporary table iParm. */ case SRT_Except: { sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn); break; } #endif /* Store the result as data using a unique key. */ case SRT_Table: case SRT_EphemTab: { int r1 = sqlite3GetTempReg(pParse); testcase(eDest == SRT_Table); testcase(eDest == SRT_EphemTab); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); if (pOrderBy != null) { pushOntoSorter(pParse, pOrderBy, p, r1); } else { int r2 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2); sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3ReleaseTempReg(pParse, r2); } sqlite3ReleaseTempReg(pParse, r1); break; } #if !SQLITE_OMIT_SUBQUERY /* If we are creating a set for an "expr IN (SELECT ...)" construct, ** then there should be a single item on the stack. Write this ** item into the set table with bogus data. */ case SRT_Set: { Debug.Assert(nColumn == 1); p.affinity = sqlite3CompareAffinity(pEList.a[0].pExpr, pDest.affinity); if (pOrderBy != null) { /* 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, pOrderBy, p, regResult); } else { int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, p.affinity, 1); sqlite3ExprCacheAffinityChange(pParse, regResult, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1); sqlite3ReleaseTempReg(pParse, r1); } break; } /* If any row exist in the result set, record that fact and abort. */ case SRT_Exists: { sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm); /* The LIMIT clause will terminate the loop for us */ break; } /* If this is a scalar select that is part of an expression, then ** store the results in the appropriate memory cell and break out ** of the scan loop. */ case SRT_Mem: { Debug.Assert(nColumn == 1); if (pOrderBy != null) { pushOntoSorter(pParse, pOrderBy, p, regResult); } else { sqlite3ExprCodeMove(pParse, regResult, iParm, 1); /* The LIMIT clause will jump out of the loop for us */ } break; } #endif // * #if !SQLITE_OMIT_SUBQUERY */ /* Send the data to the callback function or to a subroutine. In the ** case of a subroutine, the subroutine itself is responsible for ** popping the data from the stack. */ case SRT_Coroutine: case SRT_Output: { testcase(eDest == SRT_Coroutine); testcase(eDest == SRT_Output); if (pOrderBy != null) { int r1 = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); pushOntoSorter(pParse, pOrderBy, p, r1); sqlite3ReleaseTempReg(pParse, r1); } else if (eDest == SRT_Coroutine) { sqlite3VdbeAddOp1(v, OP_Yield, pDest.iParm); } else { sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn); sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn); } break; } #if !SQLITE_OMIT_TRIGGER /* Discard the results. This is used for SELECT statements inside ** the body of a TRIGGER. The purpose of such selects is to call ** user-defined functions that have side effects. We do not care ** about the actual results of the select. */ default: { Debug.Assert(eDest == SRT_Discard); break; } #endif } /* Jump to the end of the loop if the LIMIT is reached. Except, if ** there is a sorter, in which case the sorter has already limited ** the output for us. */ if (pOrderBy == null && p.iLimit != 0) { sqlite3VdbeAddOp3(v, OP_IfZero, p.iLimit, iBreak, -1); } }
static Select sqlite3SelectNew( Parse pParse, /* Parsing context */ ExprList pEList, /* which columns to include in the result */ SrcList pSrc, /* the FROM clause -- which tables to scan */ Expr pWhere, /* the WHERE clause */ ExprList pGroupBy, /* the GROUP BY clause */ Expr pHaving, /* the HAVING clause */ ExprList pOrderBy, /* the ORDER BY clause */ int isDistinct, /* true if the DISTINCT keyword is present */ 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 = new Select();//sqlite3DbMallocZero(db, sizeof(*pNew) ); Debug.Assert( //db.mallocFailed != 0 || null == pOffset || pLimit != null); /* OFFSET implies LIMIT */ //if( pNew==null ){ // pNew = standin; // memset(pNew, 0, sizeof(*pNew)); //} if (pEList == null) { pEList = sqlite3ExprListAppend(pParse, null, sqlite3Expr(db, TK_ALL, null)); } pNew.pEList = pEList; pNew.pSrc = pSrc; pNew.pWhere = pWhere; pNew.pGroupBy = pGroupBy; pNew.pHaving = pHaving; pNew.pOrderBy = pOrderBy; pNew.selFlags = (u16)(isDistinct != 0 ? SF_Distinct : 0); pNew.op = TK_SELECT; pNew.pLimit = pLimit; pNew.pOffset = pOffset; Debug.Assert(pOffset == null || pLimit != null); pNew.addrOpenEphm[0] = -1; pNew.addrOpenEphm[1] = -1; pNew.addrOpenEphm[2] = -1; //if ( db.mallocFailed != 0 ) //{ // clearSelect( db, pNew ); // //if ( pNew != standin ) sqlite3DbFree( db, ref pNew ); // pNew = null; //} return pNew; }
void sqlite3PrintSelect( Select p, int indent ) { sqlite3DebugPrintf( "%*sSELECT(%p) ", indent, "", p ); sqlite3PrintExprList( p.pEList ); sqlite3DebugPrintf( "\n" ); if ( p.pSrc != null ) { string zPrefix; int i; zPrefix = "FROM"; for ( i = 0; i < p.pSrc.nSrc; i++ ) { SrcList_item pItem = p.pSrc.a[i]; sqlite3DebugPrintf( "%*s ", indent + 6, zPrefix ); zPrefix = ""; if ( pItem.pSelect != null ) { sqlite3DebugPrintf( "(\n" ); sqlite3PrintSelect( pItem.pSelect, indent + 10 ); sqlite3DebugPrintf( "%*s)", indent + 8, "" ); } else if ( pItem.zName != null ) { sqlite3DebugPrintf( "%s", pItem.zName ); } if ( pItem.pTab != null ) { sqlite3DebugPrintf( "(vtable: %s)", pItem.pTab.zName ); } if ( pItem.zAlias != null ) { sqlite3DebugPrintf( " AS %s", pItem.zAlias ); } if ( i < p.pSrc.nSrc - 1 ) { sqlite3DebugPrintf( "," ); } sqlite3DebugPrintf( "\n" ); } } if ( p.pWhere != null ) { sqlite3DebugPrintf( "%*s WHERE ", indent, "" ); sqlite3PrintExpr( p.pWhere ); sqlite3DebugPrintf( "\n" ); } if ( p.pGroupBy != null ) { sqlite3DebugPrintf( "%*s GROUP BY ", indent, "" ); sqlite3PrintExprList( p.pGroupBy ); sqlite3DebugPrintf( "\n" ); } if ( p.pHaving != null ) { sqlite3DebugPrintf( "%*s HAVING ", indent, "" ); sqlite3PrintExpr( p.pHaving ); sqlite3DebugPrintf( "\n" ); } if ( p.pOrderBy != null ) { sqlite3DebugPrintf( "%*s ORDER BY ", indent, "" ); sqlite3PrintExprList( p.pOrderBy ); sqlite3DebugPrintf( "\n" ); } }
/* ** Add code to implement the OFFSET */ static void codeOffset( Vdbe v, /* Generate code into this VM */ Select p, /* The SELECT statement being coded */ int iContinue /* Jump here to skip the current record */ ) { if (p.iOffset != 0 && iContinue != 0) { int addr; sqlite3VdbeAddOp2(v, OP_AddImm, p.iOffset, -1); addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p.iOffset); sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue); #if SQLITE_DEBUG VdbeComment( v, "skip OFFSET records" ); #endif sqlite3VdbeJumpHere(v, addr); } }
/* ** Insert code into "v" that will push the record on the top of the ** stack into the sorter. */ static void pushOntoSorter( Parse pParse, /* Parser context */ ExprList pOrderBy, /* The ORDER BY clause */ Select pSelect, /* The whole SELECT statement */ int regData /* Register holding data to be sorted */ ) { Vdbe v = pParse.pVdbe; int nExpr = pOrderBy.nExpr; int regBase = sqlite3GetTempRange(pParse, nExpr + 2); int regRecord = sqlite3GetTempReg(pParse); sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, false); sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy.iECursor, regBase + nExpr); sqlite3ExprCodeMove(pParse, regData, regBase + nExpr + 1, 1); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy.iECursor, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nExpr + 2); if (pSelect.iLimit != 0) { int addr1, addr2; int iLimit; if (pSelect.iOffset != 0) { iLimit = pSelect.iOffset + 1; } else { iLimit = pSelect.iLimit; } addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1); addr2 = sqlite3VdbeAddOp0(v, OP_Goto); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_Last, pOrderBy.iECursor); sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy.iECursor); sqlite3VdbeJumpHere(v, addr2); } }
static int sqlite3Select( Parse pParse, /* The parser context */ Select p, /* The SELECT statement being coded. */ ref SelectDest pDest /* What to do with the query results */ ) { int i, j; /* Loop counters */ WhereInfo pWInfo; /* Return from sqlite3WhereBegin() */ Vdbe v; /* The virtual machine under construction */ bool isAgg; /* True for select lists like "count()" */ ExprList pEList = new ExprList(); /* List of columns to extract. */ SrcList pTabList = new SrcList(); /* List of tables to select from */ Expr pWhere; /* The WHERE clause. May be NULL */ ExprList pOrderBy; /* The ORDER BY clause. May be NULL */ ExprList pGroupBy; /* The GROUP BY clause. May be NULL */ Expr pHaving; /* The HAVING clause. May be NULL */ bool isDistinct; /* True if the DISTINCT keyword is present */ int distinct; /* Table to use for the distinct set */ int rc = 1; /* Value to return from this function */ int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */ AggInfo sAggInfo; /* Information used by aggregate queries */ int iEnd; /* Address of the end of the query */ sqlite3 db; /* The database connection */ #if !SQLITE_OMIT_EXPLAIN int iRestoreSelectId = pParse.iSelectId; pParse.iSelectId = pParse.iNextSelectId++; #endif db = pParse.db; if (p == null /*|| db.mallocFailed != 0 */ || pParse.nErr != 0) { return 1; } #if !SQLITE_OMIT_AUTHORIZATION if (sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0)) return 1; #endif sAggInfo = new AggInfo();// memset(sAggInfo, 0, sAggInfo).Length; if (pDest.eDest <= SRT_Discard) //IgnorableOrderby(pDest)) { Debug.Assert(pDest.eDest == SRT_Exists || pDest.eDest == SRT_Union || pDest.eDest == SRT_Except || pDest.eDest == SRT_Discard); /* If ORDER BY makes no difference in the output then neither does ** DISTINCT so it can be removed too. */ sqlite3ExprListDelete(db, ref p.pOrderBy); p.pOrderBy = null; p.selFlags = (u16)(p.selFlags & ~SF_Distinct); } sqlite3SelectPrep(pParse, p, null); pOrderBy = p.pOrderBy; pTabList = p.pSrc; pEList = p.pEList; if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) { goto select_end; } isAgg = (p.selFlags & SF_Aggregate) != 0; Debug.Assert(pEList != null); /* Begin generating code. */ v = sqlite3GetVdbe(pParse); if (v == null) goto select_end; /* If writing to memory or generating a set ** only a single column may be output. */ #if !SQLITE_OMIT_SUBQUERY if (checkForMultiColumnSelectError(pParse, pDest, pEList.nExpr)) { goto select_end; } #endif /* Generate code for all sub-queries in the FROM clause */ #if !SQLITE_OMIT_SUBQUERY || !SQLITE_OMIT_VIEW for (i = 0; p.pPrior == null && i < pTabList.nSrc; i++) { SrcList_item pItem = pTabList.a[i]; SelectDest dest = new SelectDest(); Select pSub = pItem.pSelect; bool isAggSub; if (pSub == null || pItem.isPopulated != 0) continue; /* Increment Parse.nHeight by the height of the largest expression ** tree refered to by this, the parent select. The child select ** may contain expression trees of at most ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit ** more conservative than necessary, but much easier than enforcing ** an exact limit. */ pParse.nHeight += sqlite3SelectExprHeight(p); /* Check to see if the subquery can be absorbed into the parent. */ isAggSub = (pSub.selFlags & SF_Aggregate) != 0; if (flattenSubquery(pParse, p, i, isAgg, isAggSub) != 0) { if (isAggSub) { isAgg = true; p.selFlags |= SF_Aggregate; } i = -1; } else { sqlite3SelectDestInit(dest, SRT_EphemTab, pItem.iCursor); Debug.Assert(0 == pItem.isPopulated); explainSetInteger(ref pItem.iSelectId, (int)pParse.iNextSelectId); sqlite3Select(pParse, pSub, ref dest); pItem.isPopulated = 1; pItem.pTab.nRowEst = (uint)pSub.nSelectRow; } //if ( /* pParse.nErr != 0 || */ db.mallocFailed != 0 ) //{ // goto select_end; //} pParse.nHeight -= sqlite3SelectExprHeight(p); pTabList = p.pSrc; if (!(pDest.eDest <= SRT_Discard))// if( null==IgnorableOrderby(pDest) ) { pOrderBy = p.pOrderBy; } } pEList = p.pEList; #endif pWhere = p.pWhere; pGroupBy = p.pGroupBy; pHaving = p.pHaving; isDistinct = (p.selFlags & SF_Distinct) != 0; #if !SQLITE_OMIT_COMPOUND_SELECT /* If there is are a sequence of queries, do the earlier ones first. */ if (p.pPrior != null) { if (p.pRightmost == null) { Select pLoop, pRight = null; int cnt = 0; int mxSelect; for (pLoop = p; pLoop != null; pLoop = pLoop.pPrior, cnt++) { pLoop.pRightmost = p; pLoop.pNext = pRight; pRight = pLoop; } mxSelect = db.aLimit[SQLITE_LIMIT_COMPOUND_SELECT]; if (mxSelect != 0 && cnt > mxSelect) { sqlite3ErrorMsg(pParse, "too many terms in compound SELECT"); goto select_end; } } rc = multiSelect(pParse, p, pDest); explainSetInteger(ref pParse.iSelectId, iRestoreSelectId); return rc; } #endif /* If possible, rewrite the query to use GROUP BY instead of DISTINCT. ** GROUP BY might use an index, DISTINCT never does. */ Debug.Assert(p.pGroupBy == null || (p.selFlags & SF_Aggregate) != 0); if ((p.selFlags & (SF_Distinct | SF_Aggregate)) == SF_Distinct) { p.pGroupBy = sqlite3ExprListDup(db, p.pEList, 0); pGroupBy = p.pGroupBy; p.selFlags = (u16)(p.selFlags & ~SF_Distinct); } /* If there is both a GROUP BY and an ORDER BY clause and they are ** identical, then disable the ORDER BY clause since the GROUP BY ** will cause elements to come out in the correct order. This is ** an optimization - the correct answer should result regardless. ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER ** to disable this optimization for testing purposes. */ if (sqlite3ExprListCompare(p.pGroupBy, pOrderBy) == 0 && (db.flags & SQLITE_GroupByOrder) == 0) { pOrderBy = null; } /* 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 (pOrderBy != null) { KeyInfo pKeyInfo; pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); pOrderBy.iECursor = pParse.nTab++; p.addrOpenEphm[2] = addrSortIndex = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pOrderBy.iECursor, pOrderBy.nExpr + 2, 0, pKeyInfo, P4_KEYINFO_HANDOFF); } else { addrSortIndex = -1; } /* If the output is destined for a temporary table, open that table. */ if (pDest.eDest == SRT_EphemTab) { sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pDest.iParm, pEList.nExpr); } /* Set the limiter. */ iEnd = sqlite3VdbeMakeLabel(v); p.nSelectRow = (double)LARGEST_INT64; computeLimitRegisters(pParse, p, iEnd); /* Open a virtual index to use for the distinct set. */ if ((p.selFlags & SF_Distinct) != 0) { KeyInfo pKeyInfo; Debug.Assert(isAgg || pGroupBy != null); distinct = pParse.nTab++; pKeyInfo = keyInfoFromExprList(pParse, p.pEList); sqlite3VdbeAddOp4(v, OP_OpenEphemeral, distinct, 0, 0, pKeyInfo, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, BTREE_UNORDERED); } else { distinct = -1; } /* Aggregate and non-aggregate queries are handled differently */ if (!isAgg && pGroupBy == null) { /* This case is for non-aggregate queries ** Begin the database scan */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref pOrderBy, 0); if (pWInfo == null) goto select_end; if (pWInfo.nRowOut < p.nSelectRow) p.nSelectRow = pWInfo.nRowOut; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if (addrSortIndex >= 0 && pOrderBy == null) { sqlite3VdbeChangeToNoop(v, addrSortIndex, 1); p.addrOpenEphm[2] = -1; } /* Use the standard inner loop */ Debug.Assert(!isDistinct); selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest, pWInfo.iContinue, pWInfo.iBreak); /* End the database scan loop. */ sqlite3WhereEnd(pWInfo); } else { /* This is the processing for aggregate queries */ NameContext sNC; /* Name context for processing aggregate information */ int iAMem; /* First Mem address for storing current GROUP BY */ int iBMem; /* First Mem address for previous GROUP BY */ int iUseFlag; /* Mem address holding flag indicating that at least ** one row of the input to the aggregator has been ** processed */ int iAbortFlag; /* Mem address which causes query abort if positive */ int groupBySort; /* Rows come from source in GR BY' clause thanROUP BY order */ int addrEnd; /* End of processing for this SELECT */ /* Remove any and all aliases between the result set and the ** GROUP BY clause. */ if (pGroupBy != null) { int k; /* Loop counter */ ExprList_item pItem; /* For looping over expression in a list */ for (k = p.pEList.nExpr; k > 0; k--)//, pItem++) { pItem = p.pEList.a[p.pEList.nExpr - k]; pItem.iAlias = 0; } for (k = pGroupBy.nExpr; k > 0; k--)//, pItem++ ) { pItem = pGroupBy.a[pGroupBy.nExpr - k]; pItem.iAlias = 0; } if (p.nSelectRow > (double)100) p.nSelectRow = (double)100; } else { p.nSelectRow = (double)1; } /* Create a label to jump to when we want to abort the query */ addrEnd = sqlite3VdbeMakeLabel(v); /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the ** SELECT statement. */ sNC = new NameContext(); // memset(sNC, 0, sNC).Length; sNC.pParse = pParse; sNC.pSrcList = pTabList; sNC.pAggInfo = sAggInfo; sAggInfo.nSortingColumn = pGroupBy != null ? pGroupBy.nExpr + 1 : 0; sAggInfo.pGroupBy = pGroupBy; sqlite3ExprAnalyzeAggList(sNC, pEList); sqlite3ExprAnalyzeAggList(sNC, pOrderBy); if (pHaving != null) { sqlite3ExprAnalyzeAggregates(sNC, ref pHaving); } sAggInfo.nAccumulator = sAggInfo.nColumn; for (i = 0; i < sAggInfo.nFunc; i++) { Debug.Assert(!ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect)); sqlite3ExprAnalyzeAggList(sNC, sAggInfo.aFunc[i].pExpr.x.pList); } // if ( db.mallocFailed != 0 ) goto select_end; /* Processing for aggregates with GROUP BY is very different and ** much more complex than aggregates without a GROUP BY. */ if (pGroupBy != null) { KeyInfo pKeyInfo; /* Keying information for the group by clause */ int j1; /* 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 */ int addrTopOfLoop; /* Top of the input loop */ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */ int addrReset; /* Subroutine for resetting the accumulator */ int regReset; /* Return address register for reset subroutine */ /* If there is a GROUP BY clause we might need a sorting index to ** implement it. Allocate that sorting index now. If it turns out ** that we do not need it after all, the OpenEphemeral instruction ** will be converted into a Noop. */ sAggInfo.sortingIdx = pParse.nTab++; pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sAggInfo.sortingIdx, sAggInfo.nSortingColumn, 0, pKeyInfo, P4_KEYINFO_HANDOFF); /* Initialize memory locations used by GROUP BY aggregate processing */ iUseFlag = ++pParse.nMem; iAbortFlag = ++pParse.nMem; regOutputRow = ++pParse.nMem; addrOutputRow = sqlite3VdbeMakeLabel(v); regReset = ++pParse.nMem; addrReset = sqlite3VdbeMakeLabel(v); iAMem = pParse.nMem + 1; pParse.nMem += pGroupBy.nExpr; iBMem = pParse.nMem + 1; pParse.nMem += pGroupBy.nExpr; sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag); #if SQLITE_DEBUG VdbeComment( v, "clear abort flag" ); #endif sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag); #if SQLITE_DEBUG VdbeComment( v, "indicate accumulator empty" ); #endif /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref pGroupBy, 0); if (pWInfo == null) goto select_end; if (pGroupBy == null) { /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo */ pGroupBy = p.pGroupBy; groupBySort = 0; } else { /* Rows are coming out in undetermined order. We have to push ** each row into a sorting index, terminate the first loop, ** then loop over the sorting index in order to get the output ** in sorted order */ int regBase; int regRecord; int nCol; int nGroupBy; explainTempTable(pParse, isDistinct && 0 == (p.selFlags & SF_Distinct) ? "DISTINCT" : "GROUP BY"); groupBySort = 1; nGroupBy = pGroupBy.nExpr; nCol = nGroupBy + 1; j = nGroupBy + 1; for (i = 0; i < sAggInfo.nColumn; i++) { if (sAggInfo.aCol[i].iSorterColumn >= j) { nCol++; j++; } } regBase = sqlite3GetTempRange(pParse, nCol); sqlite3ExprCacheClear(pParse); sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, false); sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx, regBase + nGroupBy); j = nGroupBy + 1; for (i = 0; i < sAggInfo.nColumn; i++) { 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); if (r1 != r2) { sqlite3VdbeAddOp2(v, OP_SCopy, r2, r1); } j++; } } regRecord = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol, regRecord); sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord); sqlite3ReleaseTempReg(pParse, regRecord); sqlite3ReleaseTempRange(pParse, regBase, nCol); sqlite3WhereEnd(pWInfo); sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); #if SQLITE_DEBUG VdbeComment( v, "GROUP BY sort" ); #endif sAggInfo.useSortingIdx = 1; sqlite3ExprCacheClear(pParse); } /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ addrTopOfLoop = sqlite3VdbeCurrentAddr(v); sqlite3ExprCacheClear(pParse); for (j = 0; j < pGroupBy.nExpr; j++) { if (groupBySort != 0) { sqlite3VdbeAddOp3(v, OP_Column, sAggInfo.sortingIdx, j, iBMem + j); } else { sAggInfo.directMode = 1; sqlite3ExprCode(pParse, pGroupBy.a[j].pExpr, iBMem + j); } } sqlite3VdbeAddOp4(v, OP_Compare, iAMem, iBMem, pGroupBy.nExpr, pKeyInfo, P4_KEYINFO); j1 = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp3(v, OP_Jump, j1 + 1, 0, j1 + 1); /* Generate code that runs whenever the GROUP BY changes. ** Changes in the GROUP BY are detected by the previous code ** block. If there were no changes, this block is skipped. ** ** This code copies current group by terms in b0,b1,b2,... ** over to a0,a1,a2. It then calls the output subroutine ** and resets the aggregate accumulator registers in preparation ** for the next GROUP BY batch. */ sqlite3ExprCodeMove(pParse, iBMem, iAMem, pGroupBy.nExpr); sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); #if SQLITE_DEBUG VdbeComment( v, "output one row" ); #endif sqlite3VdbeAddOp2(v, OP_IfPos, iAbortFlag, addrEnd); #if SQLITE_DEBUG VdbeComment( v, "check abort flag" ); #endif sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset); #if SQLITE_DEBUG VdbeComment( v, "reset accumulator" ); #endif /* Update the aggregate accumulators based on the content of ** the current row */ sqlite3VdbeJumpHere(v, j1); updateAccumulator(pParse, sAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); #if SQLITE_DEBUG VdbeComment( v, "indicate data in accumulator" ); #endif /* End of the loop */ if (groupBySort != 0) { sqlite3VdbeAddOp2(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); } else { sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx, 1); } /* Output the final row of result */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); #if SQLITE_DEBUG VdbeComment( v, "output final row" ); #endif /* Jump over the subroutines */ sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEnd); /* Generate a subroutine that outputs a single row of the result ** set. This subroutine first looks at the iUseFlag. If iUseFlag ** is less than or equal to zero, the subroutine is a no-op. If ** the processing calls for the query to abort, this subroutine ** increments the iAbortFlag memory location before returning in ** order to signal the caller to abort. */ addrSetAbort = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_Integer, 1, iAbortFlag); VdbeComment(v, "set abort flag"); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); sqlite3VdbeResolveLabel(v, addrOutputRow); addrOutputRow = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_IfPos, iUseFlag, addrOutputRow + 2); VdbeComment(v, "Groupby result generator entry point"); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); finalizeAggFunctions(pParse, sAggInfo); sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow + 1, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p.pEList, 0, 0, pOrderBy, distinct, pDest, addrOutputRow + 1, addrSetAbort); sqlite3VdbeAddOp1(v, OP_Return, regOutputRow); VdbeComment(v, "end groupby result generator"); /* Generate a subroutine that will reset the group-by accumulator */ sqlite3VdbeResolveLabel(v, addrReset); resetAccumulator(pParse, sAggInfo); sqlite3VdbeAddOp1(v, OP_Return, regReset); } /* endif pGroupBy. Begin aggregate queries without GROUP BY: */ else { ExprList pDel = null; #if !SQLITE_OMIT_BTREECOUNT Table pTab; if ((pTab = isSimpleCount(p, sAggInfo)) != null) { /* If isSimpleCount() returns a pointer to a Table structure, then ** the SQL statement is of the form: ** ** SELECT count() FROM <tbl> ** ** where the Table structure returned represents table <tbl>. ** ** This statement is so common that it is optimized specially. The ** OP_Count instruction is executed either on the intkey table that ** contains the data for table <tbl> or on one of its indexes. It ** is better to execute the op on an index, as indexes are almost ** always spread across less pages than their corresponding tables. */ int iDb = sqlite3SchemaToIndex(pParse.db, pTab.pSchema); int iCsr = pParse.nTab++; /* Cursor to scan b-tree */ Index pIdx; /* Iterator variable */ KeyInfo pKeyInfo = null; /* Keyinfo for scanned index */ Index pBest = null; /* Best index found so far */ int iRoot = pTab.tnum; /* Root page of scanned b-tree */ sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab.tnum, 0, pTab.zName); /* Search for the index that has the least amount of columns. If ** there is such an index, and it has less columns than the table ** does, then we can assume that it consumes less space on disk and ** will therefore be cheaper to scan to determine the query result. ** In this case set iRoot to the root page number of the index b-tree ** and pKeyInfo to the KeyInfo structure required to navigate the ** index. ** ** (2011-04-15) Do not do a full scan of an unordered index. ** ** In practice the KeyInfo structure will not be used. It is only ** passed to keep OP_OpenRead happy. */ for (pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext) { if (pIdx.bUnordered == 0 && (null == pBest || pIdx.nColumn < pBest.nColumn)) { pBest = pIdx; } } if (pBest != null && pBest.nColumn < pTab.nCol) { iRoot = pBest.tnum; pKeyInfo = sqlite3IndexKeyinfo(pParse, pBest); } /* Open a read-only cursor, execute the OP_Count, close the cursor. */ sqlite3VdbeAddOp3(v, OP_OpenRead, iCsr, iRoot, iDb); if (pKeyInfo != null) { sqlite3VdbeChangeP4(v, -1, pKeyInfo, P4_KEYINFO_HANDOFF); } sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem); sqlite3VdbeAddOp1(v, OP_Close, iCsr); explainSimpleCount(pParse, pTab, pBest); } else #endif //* SQLITE_OMIT_BTREECOUNT */ { /* Check if the query is of one of the following forms: ** ** SELECT min(x) FROM ... ** SELECT max(x) FROM ... ** ** If it is, then ask the code in where.c to attempt to sort results ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause. ** If where.c is able to produce results sorted in this order, then ** add vdbe code to break out of the processing loop after the ** first iteration (since the first iteration of the loop is ** guaranteed to operate on the row with the minimum or maximum ** value of x, the only row required). ** ** A special flag must be passed to sqlite3WhereBegin() to slightly ** modify behavior as follows: ** ** + If the query is a "SELECT min(x)", then the loop coded by ** where.c should not iterate over any values with a NULL value ** for x. ** ** + The optimizer code in where.c (the thing that decides which ** index or indices to use) should place a different priority on ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList pMinMax = null; int flag = minMaxQuery(p); if (flag != 0) { Debug.Assert(!ExprHasProperty(p.pEList.a[0].pExpr, EP_xIsSelect)); pMinMax = sqlite3ExprListDup(db, p.pEList.a[0].pExpr.x.pList, 0); pDel = pMinMax; if (pMinMax != null)///* && 0 == db.mallocFailed */ ) { pMinMax.a[0].sortOrder = (u8)(flag != WHERE_ORDERBY_MIN ? 1 : 0); pMinMax.a[0].pExpr.op = TK_COLUMN; } } /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, sAggInfo); pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref pMinMax, (byte)flag); if (pWInfo == null) { sqlite3ExprListDelete(db, ref pDel); goto select_end; } updateAccumulator(pParse, sAggInfo); if (pMinMax == null && flag != 0) { sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo.iBreak); #if SQLITE_DEBUG VdbeComment( v, "%s() by index", ( flag == WHERE_ORDERBY_MIN ? "min" : "max" ) ); #endif } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, sAggInfo); } pOrderBy = null; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); selectInnerLoop(pParse, p, p.pEList, 0, 0, null, -1, pDest, addrEnd, addrEnd); sqlite3ExprListDelete(db, ref pDel); } sqlite3VdbeResolveLabel(v, addrEnd); } /* endif aggregate query */ if (distinct >= 0) { explainTempTable(pParse, "DISTINCT"); } /* If there is an ORDER BY clause, then we need to sort the results ** and send them to the callback one by one. */ if (pOrderBy != null) { explainTempTable(pParse, "ORDER BY"); generateSortTail(pParse, p, v, pEList.nExpr, pDest); } /* Jump here to skip this query */ sqlite3VdbeResolveLabel(v, iEnd); /* The SELECT was successfully coded. Set the return code to 0 ** to indicate no errors. */ rc = 0; /* Control jumps to here if an error is encountered above, or upon ** successful coding of the SELECT. */ select_end: explainSetInteger(ref pParse.iSelectId, iRestoreSelectId); /* Identify column names if results of the SELECT are to be output. */ if (rc == SQLITE_OK && pDest.eDest == SRT_Output) { generateColumnNames(pParse, pTabList, pEList); } sqlite3DbFree(db, ref sAggInfo.aCol); sqlite3DbFree(db, ref sAggInfo.aFunc); return rc; }
/* ** This routine sets of a SELECT statement for processing. The ** following is accomplished: ** ** * VDBE VdbeCursor numbers are assigned to all FROM-clause terms. ** * Ephemeral Table objects are created for all FROM-clause subqueries. ** * ON and USING clauses are shifted into WHERE statements ** * Wildcards "*" and "TABLE.*" in result sets are expanded. ** * Identifiers in expression are matched to tables. ** ** This routine acts recursively on all subqueries within the SELECT. */ static void sqlite3SelectPrep( Parse pParse, /* The parser context */ Select p, /* The SELECT statement being coded. */ NameContext pOuterNC /* Name context for container */ ) { sqlite3 db; if (NEVER(p == null)) return; db = pParse.db; if ((p.selFlags & SF_HasTypeInfo) != 0) return; sqlite3SelectExpand(pParse, p); if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) return; sqlite3ResolveSelectNames(pParse, p, pOuterNC); if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) return; sqlite3SelectAddTypeInfo(pParse, p); }
/* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ************************************************************************* ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart ** C#-SQLite is an independent reimplementation of the SQLite software library ** ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 ** ************************************************************************* */ //#include "sqliteInt.h" /* ** Delete all the content of a Select structure but do not deallocate ** the select structure itself. */ static void clearSelect(sqlite3 db, Select p) { sqlite3ExprListDelete(db, ref p.pEList); sqlite3SrcListDelete(db, ref p.pSrc); sqlite3ExprDelete(db, ref p.pWhere); sqlite3ExprListDelete(db, ref p.pGroupBy); sqlite3ExprDelete(db, ref p.pHaving); sqlite3ExprListDelete(db, ref p.pOrderBy); sqlite3SelectDelete(db, ref p.pPrior); sqlite3ExprDelete(db, ref p.pLimit); sqlite3ExprDelete(db, ref p.pOffset); }
/* ** Given a SELECT statement, generate a Table structure that describes ** the result set of that SELECT. */ static Table sqlite3ResultSetOfSelect(Parse pParse, Select pSelect) { Table pTab; sqlite3 db = pParse.db; int savedFlags; savedFlags = db.flags; db.flags &= ~SQLITE_FullColNames; db.flags |= SQLITE_ShortColNames; sqlite3SelectPrep(pParse, pSelect, null); if (pParse.nErr != 0) return null; while (pSelect.pPrior != null) pSelect = pSelect.pPrior; db.flags = savedFlags; pTab = new Table();// sqlite3DbMallocZero( db, sizeof( Table ) ); if (pTab == null) { return null; } /* The sqlite3ResultSetOfSelect() is only used n contexts where lookaside ** is disabled */ Debug.Assert(db.lookaside.bEnabled == 0); pTab.nRef = 1; pTab.zName = null; pTab.nRowEst = 1000000; selectColumnsFromExprList(pParse, pSelect.pEList, ref pTab.nCol, ref pTab.aCol); selectAddColumnTypeAndCollation(pParse, pTab.nCol, pTab.aCol, pSelect); pTab.iPKey = -1; //if ( db.mallocFailed != 0 ) //{ // sqlite3DeleteTable(db, ref pTab ); // return null; //} return pTab; }