⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 select.c

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 C
📖 第 1 页 / 共 5 页
字号:
          p->pRightmost->usesVirt = 1;        }        createSortingIndex(pParse, p, pOrderBy);        assert( p->pEList );      }      /* Code the SELECT statements to our left      */      assert( !pPrior->pOrderBy );      rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);      if( rc ){        goto multi_select_end;      }      /* Code the current SELECT statement      */      switch( p->op ){         case TK_EXCEPT:  op = SRT_Except;   break;         case TK_UNION:   op = SRT_Union;    break;         case TK_ALL:     op = SRT_Table;    break;      }      p->pPrior = 0;      p->pOrderBy = 0;      p->disallowOrderBy = pOrderBy!=0;      pLimit = p->pLimit;      p->pLimit = 0;      pOffset = p->pOffset;      p->pOffset = 0;      rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);      p->pPrior = pPrior;      p->pOrderBy = pOrderBy;      sqlite3ExprDelete(p->pLimit);      p->pLimit = pLimit;      p->pOffset = pOffset;      p->iLimit = -1;      p->iOffset = -1;      if( rc ){        goto multi_select_end;      }      /* Convert the data in the temporary table into whatever form      ** it is that we currently need.      */            if( eDest!=priorOp || unionTab!=iParm ){        int iCont, iBreak, iStart;        assert( p->pEList );        if( eDest==SRT_Callback ){          generateColumnNames(pParse, 0, p->pEList);        }        iBreak = sqlite3VdbeMakeLabel(v);        iCont = sqlite3VdbeMakeLabel(v);        sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak);        computeLimitRegisters(pParse, p);        iStart = sqlite3VdbeCurrentAddr(v);        rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,                             pOrderBy, -1, eDest, iParm,                              iCont, iBreak, 0);        if( rc ){          rc = 1;          goto multi_select_end;        }        sqlite3VdbeResolveLabel(v, iCont);        sqlite3VdbeAddOp(v, OP_Next, unionTab, iStart);        sqlite3VdbeResolveLabel(v, iBreak);        sqlite3VdbeAddOp(v, OP_Close, unionTab, 0);      }      break;    }    case TK_INTERSECT: {      int tab1, tab2;      int iCont, iBreak, iStart;      Expr *pLimit, *pOffset;      int addr;      /* 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++;      if( pOrderBy && matchOrderbyToColumn(pParse,p,pOrderBy,tab1,1) ){        rc = 1;        goto multi_select_end;      }      createSortingIndex(pParse, p, pOrderBy);      addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0);      assert( p->addrOpenVirt[0] == -1 );      p->addrOpenVirt[0] = addr;      p->pRightmost->usesVirt = 1;      assert( p->pEList );      /* Code the SELECTs to our left into temporary table "tab1".      */      rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff);      if( rc ){        goto multi_select_end;      }      /* Code the current SELECT into temporary table "tab2"      */      addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0);      assert( p->addrOpenVirt[1] == -1 );      p->addrOpenVirt[1] = addr;      p->pPrior = 0;      pLimit = p->pLimit;      p->pLimit = 0;      pOffset = p->pOffset;      p->pOffset = 0;      rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff);      p->pPrior = pPrior;      sqlite3ExprDelete(p->pLimit);      p->pLimit = pLimit;      p->pOffset = pOffset;      if( rc ){        goto multi_select_end;      }      /* Generate code to take the intersection of the two temporary      ** tables.      */      assert( p->pEList );      if( eDest==SRT_Callback ){        generateColumnNames(pParse, 0, p->pEList);      }      iBreak = sqlite3VdbeMakeLabel(v);      iCont = sqlite3VdbeMakeLabel(v);      sqlite3VdbeAddOp(v, OP_Rewind, tab1, iBreak);      computeLimitRegisters(pParse, p);      iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0);      sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont);      rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,                             pOrderBy, -1, eDest, iParm,                              iCont, iBreak, 0);      if( rc ){        rc = 1;        goto multi_select_end;      }      sqlite3VdbeResolveLabel(v, iCont);      sqlite3VdbeAddOp(v, OP_Next, tab1, iStart);      sqlite3VdbeResolveLabel(v, iBreak);      sqlite3VdbeAddOp(v, OP_Close, tab2, 0);      sqlite3VdbeAddOp(v, OP_Close, tab1, 0);      break;    }  }  /* Make sure all SELECTs in the statement have the same number of elements  ** in their result sets.  */  assert( p->pEList && pPrior->pEList );  if( p->pEList->nExpr!=pPrior->pEList->nExpr ){    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;  }  /* Set the number of columns in temporary tables  */  nCol = p->pEList->nExpr;  while( nSetP2 ){    sqlite3VdbeChangeP2(v, aSetP2[--nSetP2], nCol);  }  /* Compute collating sequences used by either the ORDER BY clause or  ** by any temporary tables needed to implement the compound select.  ** Attach the KeyInfo structure to all temporary tables.  Invoke the  ** ORDER BY processing if there is an ORDER BY clause.  **  ** 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( pOrderBy || p->usesVirt ){    int i;                        /* Loop counter */    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */    Select *pLoop;                /* For looping through SELECT statements */    CollSeq **apColl;    CollSeq **aCopy;    assert( p->pRightmost==p );    pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*2*sizeof(CollSeq*) + nCol);    if( !pKeyInfo ){      rc = SQLITE_NOMEM;      goto multi_select_end;    }    pKeyInfo->enc = pParse->db->enc;    pKeyInfo->nField = nCol;    for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){      *apColl = multiSelectCollSeq(pParse, p, i);      if( 0==*apColl ){        *apColl = pParse->db->pDfltColl;      }    }    for(pLoop=p; pLoop; pLoop=pLoop->pPrior){      for(i=0; i<2; i++){        int addr = pLoop->addrOpenVirt[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 */          assert( pLoop->addrOpenVirt[1]<0 );          break;        }        sqlite3VdbeChangeP2(v, addr, nCol);        sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO);      }    }    if( pOrderBy ){      struct ExprList_item *pOTerm = pOrderBy->a;      int nExpr = pOrderBy->nExpr;      int addr;      u8 *pSortOrder;      aCopy = (CollSeq**)&pKeyInfo[1];      pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nExpr];      memcpy(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*));      apColl = pKeyInfo->aColl;      for(i=0; i<pOrderBy->nExpr; i++, pOTerm++, apColl++, pSortOrder++){        Expr *pExpr = pOTerm->pExpr;        char *zName = pOTerm->zName;        assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol );        if( zName ){          *apColl = sqlite3LocateCollSeq(pParse, zName, -1);        }else{          *apColl = aCopy[pExpr->iColumn];        }        *pSortOrder = pOTerm->sortOrder;      }      assert( p->pRightmost==p );      assert( p->addrOpenVirt[2]>=0 );      addr = p->addrOpenVirt[2];      sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2);      pKeyInfo->nField = pOrderBy->nExpr;      sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);      pKeyInfo = 0;      generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);    }    sqliteFree(pKeyInfo);  }multi_select_end:  return rc;}#endif /* SQLITE_OMIT_COMPOUND_SELECT */#ifndef SQLITE_OMIT_VIEW/*** Scan through the expression pExpr.  Replace every reference to** a column in table number iTable with a copy of the iColumn-th** entry in pEList.  (But leave references to the ROWID column ** unchanged.)**** This routine is part of the flattening procedure.  A subquery** whose result set is defined by pEList appears as entry in the** FROM clause of a SELECT such that the VDBE cursor assigned to that** FORM clause entry is iTable.  This routine make the necessary ** changes to pExpr so that it refers directly to the source table** of the subquery rather the result set of the subquery.*/static void substExprList(ExprList*,int,ExprList*);  /* Forward Decl */static void substSelect(Select *, int, ExprList *);  /* Forward Decl */static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){  if( pExpr==0 ) return;  if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){    if( pExpr->iColumn<0 ){      pExpr->op = TK_NULL;    }else{      Expr *pNew;      assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );      assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );      pNew = pEList->a[pExpr->iColumn].pExpr;      assert( pNew!=0 );      pExpr->op = pNew->op;      assert( pExpr->pLeft==0 );      pExpr->pLeft = sqlite3ExprDup(pNew->pLeft);      assert( pExpr->pRight==0 );      pExpr->pRight = sqlite3ExprDup(pNew->pRight);      assert( pExpr->pList==0 );      pExpr->pList = sqlite3ExprListDup(pNew->pList);      pExpr->iTable = pNew->iTable;      pExpr->iColumn = pNew->iColumn;      pExpr->iAgg = pNew->iAgg;      sqlite3TokenCopy(&pExpr->token, &pNew->token);      sqlite3TokenCopy(&pExpr->span, &pNew->span);      pExpr->pSelect = sqlite3SelectDup(pNew->pSelect);      pExpr->flags = pNew->flags;    }  }else{    substExpr(pExpr->pLeft, iTable, pEList);    substExpr(pExpr->pRight, iTable, pEList);    substSelect(pExpr->pSelect, iTable, pEList);    substExprList(pExpr->pList, iTable, pEList);  }}static void substExprList(ExprList *pList, int iTable, ExprList *pEList){  int i;  if( pList==0 ) return;  for(i=0; i<pList->nExpr; i++){    substExpr(pList->a[i].pExpr, iTable, pEList);  }}static void substSelect(Select *p, int iTable, ExprList *pEList){  if( !p ) return;  substExprList(p->pEList, iTable, pEList);  substExprList(p->pGroupBy, iTable, pEList);  substExprList(p->pOrderBy, iTable, pEList);  substExpr(p->pHaving, iTable, pEList);  substExpr(p->pWhere, iTable, pEList);}#endif /* !defined(SQLITE_OMIT_VIEW) */#ifndef SQLITE_OMIT_VIEW/*** 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, or**        the subquery is not itself a join.  (Ticket #306)****   (4)  The subquery is not DISTINCT or the outer query is not a join.****   (5)  The subquery is not DISTINCT or the outer query does not use**        aggregates.****   (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.****  (12)  The subquery is not the right term of a LEFT OUTER JOIN or the**        subquery has no WHERE clause.  (added by ticket #350)**** 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.*/static int flattenSubquery(  Parse *pParse,       /* The parsing context */  Select *p,           /* The parent or outer SELECT statemen

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -