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

📄 select.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    */    nName = strlen(zName);    for(j=cnt=0; j<i; j++){      if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){        char *zNewName;        zName[nName] = 0;        zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);        sqlite3DbFree(db, zName);        zName = zNewName;        j = -1;        if( zName==0 ) break;      }    }    pCol->zName = zName;  }  if( db->mallocFailed ){    int j;    for(j=0; j<i; j++){      sqlite3DbFree(db, aCol[j].zName);    }    sqlite3DbFree(db, aCol);    *paCol = 0;    *pnCol = 0;    return SQLITE_NOMEM;  }  return SQLITE_OK;}/*** 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 indentifiers 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;  struct ExprList_item *a;  assert( pSelect!=0 );  assert( (pSelect->selFlags & SF_Resolved)!=0 );  assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );  if( db->mallocFailed ) return;  memset(&sNC, 0, sizeof(sNC));  sNC.pSrcList = pSelect->pSrc;  a = pSelect->pEList->a;  for(i=0, pCol=aCol; i<nCol; i++, pCol++){    p = a[i].pExpr;    pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));    pCol->affinity = sqlite3ExprAffinity(p);    pColl = sqlite3ExprCollSeq(pParse, p);    if( pColl ){      pCol->zColl = sqlite3DbStrDup(db, pColl->zName);    }  }}/*** Given a SELECT statement, generate a Table structure that describes** the result set of that SELECT.*/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, 0);  if( pParse->nErr ) return 0;  while( pSelect->pPrior ) pSelect = pSelect->pPrior;  db->flags = savedFlags;  pTab = sqlite3DbMallocZero(db, sizeof(Table) );  if( pTab==0 ){    return 0;  }  pTab->db = db;  pTab->nRef = 1;  pTab->zName = 0;  selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);  selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);  pTab->iPKey = -1;  if( db->mallocFailed ){    sqlite3DeleteTable(pTab);    return 0;  }  return pTab;}/*** Get a VDBE for the given parser context.  Create a new one if necessary.** If an error occurs, return NULL and leave a message in pParse.*/Vdbe *sqlite3GetVdbe(Parse *pParse){  Vdbe *v = pParse->pVdbe;  if( v==0 ){    v = pParse->pVdbe = sqlite3VdbeCreate(pParse->db);#ifndef SQLITE_OMIT_TRACE    if( v ){      sqlite3VdbeAddOp0(v, OP_Trace);    }#endif  }  return v;}/*** 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 = 0;  int iLimit = 0;  int iOffset;  int addr1;  if( p->iLimit ) 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.  */  if( p->pLimit ){    p->iLimit = iLimit = ++pParse->nMem;    v = sqlite3GetVdbe(pParse);    if( v==0 ) return;    sqlite3ExprCode(pParse, p->pLimit, iLimit);    sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);    VdbeComment((v, "LIMIT counter"));    sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);  }  if( p->pOffset ){    p->iOffset = iOffset = ++pParse->nMem;    if( p->pLimit ){      pParse->nMem++;   /* Allocate an extra register for limit+offset */    }    v = sqlite3GetVdbe(pParse);    if( v==0 ) return;    sqlite3ExprCode(pParse, p->pOffset, iOffset);    sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset);    VdbeComment((v, "OFFSET counter"));    addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);    sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);    sqlite3VdbeJumpHere(v, addr1);    if( p->pLimit ){      sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);      VdbeComment((v, "LIMIT+OFFSET"));      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);      sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);      sqlite3VdbeJumpHere(v, addr1);    }  }}#ifndef SQLITE_OMIT_COMPOUND_SELECT/*** 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 ){    pRet = multiSelectCollSeq(pParse, p->pPrior, iCol);  }else{    pRet = 0;  }  if( pRet==0 ){    pRet = sqlite3ExprCollSeq(pParse, p->pEList->a[iCol].pExpr);  }  return pRet;}#endif /* SQLITE_OMIT_COMPOUND_SELECT *//* 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 */);#ifndef 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;      /* Alternative data destination */  Select *pDelete = 0;  /* Chain of simple selects to delete */  sqlite3 *db;          /* Database connection */  /* 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.  */  assert( p && p->pPrior );  /* Calling function guarantees this much */  db = pParse->db;  pPrior = p->pPrior;  assert( pPrior->pRightmost!=pPrior );  assert( pPrior->pRightmost==p->pRightmost );  dest = *pDest;  if( pPrior->pOrderBy ){    sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",      selectOpName(p->op));    rc = 1;    goto multi_select_end;  }  if( pPrior->pLimit ){    sqlite3ErrorMsg(pParse,"LIMIT clause should come after %s not before",      selectOpName(p->op));    rc = 1;    goto multi_select_end;  }  v = sqlite3GetVdbe(pParse);  assert( v!=0 );  /* The VDBE already created by calling function */  /* Create the destination temporary table if necessary  */  if( dest.eDest==SRT_EphemTab ){    assert( p->pEList );    sqlite3VdbeAddOp2(v, OP_OpenEphemeral, dest.iParm, p->pEList->nExpr);    dest.eDest = SRT_Table;  }  /* 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;  }  /* Compound SELECTs that have an ORDER BY clause are handled separately.  */  if( p->pOrderBy ){    return multiSelectOrderBy(pParse, p, pDest);  }  /* Generate code for the left and right SELECT statements.  */  switch( p->op ){    case TK_ALL: {      int addr = 0;      assert( !pPrior->pLimit );      pPrior->pLimit = p->pLimit;      pPrior->pOffset = p->pOffset;      rc = sqlite3Select(pParse, pPrior, &dest);      p->pLimit = 0;      p->pOffset = 0;      if( rc ){        goto multi_select_end;      }      p->pPrior = 0;      p->iLimit = pPrior->iLimit;      p->iOffset = pPrior->iOffset;      if( p->iLimit ){        addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit);        VdbeComment((v, "Jump ahead if LIMIT reached"));      }      rc = sqlite3Select(pParse, p, &dest);      pDelete = p->pPrior;      p->pPrior = pPrior;      if( rc ){        goto multi_select_end;      }      if( addr ){        sqlite3VdbeJumpHere(v, addr);      }      break;    }    case TK_EXCEPT:    case TK_UNION: {      int unionTab;    /* Cursor number of the temporary table holding result */      int 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;      priorOp = SRT_Union;      if( dest.eDest==priorOp && !p->pLimit && !p->pOffset ){        /* We can reuse a temporary table generated by a SELECT to our        ** right.        */        unionTab = dest.iParm;      }else{        /* We will need to create our own temporary table to hold the        ** intermediate results.        */        unionTab = pParse->nTab++;        assert( p->pOrderBy==0 );        addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, unionTab, 0);        assert( p->addrOpenEphm[0] == -1 );        p->addrOpenEphm[0] = addr;        p->pRightmost->selFlags |= SF_UsesEphemeral;        assert( p->pEList );      }      /* Code the SELECT statements to our left      */      assert( !pPrior->pOrderBy );      sqlite3SelectDestInit(&uniondest, priorOp, unionTab);      rc = sqlite3Select(pParse, pPrior, &uniondest);      if( rc ){        goto multi_select_end;      }      /* Code the current SELECT statement      */      if( p->op==TK_EXCEPT ){        op = SRT_Except;      }else{        assert( p->op==TK_UNION );        op = SRT_Union;      }      p->pPrior = 0;      pLimit = p->pLimit;      p->pLimit = 0;      pOffset = p->pOffset;      p->pOffset = 0;      uniondest.eDest = op;      rc = sqlite3Select(pParse, p, &uniondest);      /* Query flattening in sqlite3Select() might refill p->pOrderBy.      ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */      sqlite3ExprListDelete(db, p->pOrderBy);

⌨️ 快捷键说明

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