?? select.c
字號:
** (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.
**
** Return 0 on success. If there are problems, leave an error message
** in pParse and return non-zero.
*/
static int prepSelectStmt(Parse *pParse, Select *p){
int i, j, k, rc;
SrcList *pTabList;
ExprList *pEList;
struct SrcList_item *pFrom;
if( p==0 || p->pSrc==0 || sqlite3MallocFailed() ){
return 1;
}
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, p->pSrc);
/* 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 structure to describe the subquery.
*/
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab;
if( pFrom->pTab!=0 ){
/* This statement has already been prepared. There is no need
** to go further. */
assert( i==0 );
return 0;
}
if( pFrom->zName==0 ){
#ifndef SQLITE_OMIT_SUBQUERY
/* A sub-query in the FROM clause of a SELECT */
assert( pFrom->pSelect!=0 );
if( pFrom->zAlias==0 ){
pFrom->zAlias =
sqlite3MPrintf("sqlite_subquery_%p_", (void*)pFrom->pSelect);
}
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
if( pTab==0 ){
return 1;
}
/* The isEphem flag indicates that the Table structure has been
** dynamically allocated and may be freed at any time. In other words,
** pTab is not pointing to a persistent table structure that defines
** part of the schema. */
pTab->isEphem = 1;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
assert( pFrom->pTab==0 );
pFrom->pTab = pTab =
sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase);
if( pTab==0 ){
return 1;
}
pTab->nRef++;
#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
if( pTab->pSelect || IsVirtual(pTab) ){
/* We reach here if the named table is a really a view */
if( sqlite3ViewGetColumnNames(pParse, pTab) ){
return 1;
}
/* If pFrom->pSelect!=0 it means we are dealing with a
** view within a view. The SELECT structure has already been
** copied by the outer view so we can skip the copy step here
** in the inner view.
*/
if( pFrom->pSelect==0 ){
pFrom->pSelect = sqlite3SelectDup(pTab->pSelect);
}
}
#endif
}
}
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
if( sqliteProcessJoin(pParse, p) ) return 1;
/* 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;
if( pE->op==TK_DOT && pE->pRight && pE->pRight->op==TK_ALL
&& pE->pLeft && pE->pLeft->op==TK_ID ) break;
}
rc = 0;
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.
*/
struct ExprList_item *a = pEList->a;
ExprList *pNew = 0;
int flags = pParse->db->flags;
int longNames = (flags & SQLITE_FullColNames)!=0 &&
(flags & SQLITE_ShortColNames)==0;
for(k=0; k<pEList->nExpr; k++){
Expr *pE = a[k].pExpr;
if( pE->op!=TK_ALL &&
(pE->op!=TK_DOT || pE->pRight==0 || pE->pRight->op!=TK_ALL) ){
/* This particular expression does not need to be expanded.
*/
pNew = sqlite3ExprListAppend(pNew, a[k].pExpr, 0);
if( pNew ){
pNew->a[pNew->nExpr-1].zName = a[k].zName;
}else{
rc = 1;
}
a[k].pExpr = 0;
a[k].zName = 0;
}else{
/* This expression is a "*" or a "TABLE.*" and needs to be
** expanded. */
int tableSeen = 0; /* Set to 1 when TABLE matches */
char *zTName; /* text of name of TABLE */
if( pE->op==TK_DOT && pE->pLeft ){
zTName = sqlite3NameFromToken(&pE->pLeft->token);
}else{
zTName = 0;
}
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab = pFrom->pTab;
char *zTabName = pFrom->zAlias;
if( zTabName==0 || zTabName[0]==0 ){
zTabName = pTab->zName;
}
if( zTName && (zTabName==0 || zTabName[0]==0 ||
sqlite3StrICmp(zTName, zTabName)!=0) ){
continue;
}
tableSeen = 1;
for(j=0; j<pTab->nCol; j++){
Expr *pExpr, *pRight;
char *zName = pTab->aCol[j].zName;
if( i>0 ){
struct SrcList_item *pLeft = &pTabList->a[i-1];
if( (pLeft->jointype & JT_NATURAL)!=0 &&
columnIndex(pLeft->pTab, zName)>=0 ){
/* In a NATURAL join, omit the join columns from the
** table on the right */
continue;
}
if( sqlite3IdListIndex(pLeft->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(TK_ID, 0, 0, 0);
if( pRight==0 ) break;
setToken(&pRight->token, zName);
if( zTabName && (longNames || pTabList->nSrc>1) ){
Expr *pLeft = sqlite3Expr(TK_ID, 0, 0, 0);
pExpr = sqlite3Expr(TK_DOT, pLeft, pRight, 0);
if( pExpr==0 ) break;
setToken(&pLeft->token, zTabName);
setToken(&pExpr->span, sqlite3MPrintf("%s.%s", zTabName, zName));
pExpr->span.dyn = 1;
pExpr->token.z = 0;
pExpr->token.n = 0;
pExpr->token.dyn = 0;
}else{
pExpr = pRight;
pExpr->span = pExpr->token;
}
if( longNames ){
pNew = sqlite3ExprListAppend(pNew, pExpr, &pExpr->span);
}else{
pNew = sqlite3ExprListAppend(pNew, pExpr, &pRight->token);
}
}
}
if( !tableSeen ){
if( zTName ){
sqlite3ErrorMsg(pParse, "no such table: %s", zTName);
}else{
sqlite3ErrorMsg(pParse, "no tables specified");
}
rc = 1;
}
sqliteFree(zTName);
}
}
sqlite3ExprListDelete(pEList);
p->pEList = pNew;
}
return rc;
}
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** This routine associates entries in an ORDER BY expression list with
** columns in a result. For each ORDER BY expression, the opcode of
** the top-level node is changed to TK_COLUMN and the iColumn value of
** the top-level node is filled in with column number and the iTable
** value of the top-level node is filled with iTable parameter.
**
** If there are prior SELECT clauses, they are processed first. A match
** in an earlier SELECT takes precedence over a later SELECT.
**
** Any entry that does not match is flagged as an error. The number
** of errors is returned.
*/
static int matchOrderbyToColumn(
Parse *pParse, /* A place to leave error messages */
Select *pSelect, /* Match to result columns of this SELECT */
ExprList *pOrderBy, /* The ORDER BY values to match against columns */
int iTable, /* Insert this value in iTable */
int mustComplete /* If TRUE all ORDER BYs must match */
){
int nErr = 0;
int i, j;
ExprList *pEList;
if( pSelect==0 || pOrderBy==0 ) return 1;
if( mustComplete ){
for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
}
if( prepSelectStmt(pParse, pSelect) ){
return 1;
}
if( pSelect->pPrior ){
if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){
return 1;
}
}
pEList = pSelect->pEList;
for(i=0; i<pOrderBy->nExpr; i++){
Expr *pE = pOrderBy->a[i].pExpr;
int iCol = -1;
if( pOrderBy->a[i].done ) continue;
if( sqlite3ExprIsInteger(pE, &iCol) ){
if( iCol<=0 || iCol>pEList->nExpr ){
sqlite3ErrorMsg(pParse,
"ORDER BY position %d should be between 1 and %d",
iCol, pEList->nExpr);
nErr++;
break;
}
if( !mustComplete ) continue;
iCol--;
}
for(j=0; iCol<0 && j<pEList->nExpr; j++){
if( pEList->a[j].zName && (pE->op==TK_ID || pE->op==TK_STRING) ){
char *zName, *zLabel;
zName = pEList->a[j].zName;
zLabel = sqlite3NameFromToken(&pE->token);
assert( zLabel!=0 );
if( sqlite3StrICmp(zName, zLabel)==0 ){
iCol = j;
}
sqliteFree(zLabel);
}
if( iCol<0 && sqlite3ExprCompare(pE, pEList->a[j].pExpr) ){
iCol = j;
}
}
if( iCol>=0 ){
pE->op = TK_COLUMN;
pE->iColumn = iCol;
pE->iTable = iTable;
pE->iAgg = -1;
pOrderBy->a[i].done = 1;
}
if( iCol<0 && mustComplete ){
sqlite3ErrorMsg(pParse,
"ORDER BY term number %d does not match any result column", i+1);
nErr++;
break;
}
}
return nErr;
}
#endif /* #ifndef SQLITE_OMIT_COMPOUND_SELECT */
/*
** 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);
}
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, addr2;
/*
** "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;
pParse->nMem += 2;
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
sqlite3ExprCode(pParse, p->pLimit);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 0);
VdbeComment((v, "# LIMIT counter"));
sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak);
}
if( p->pOffset ){
p->iOffset = iOffset = pParse->nMem++;
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
sqlite3ExprCode(pParse, p->pOffset);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0);
VdbeComment((v, "# OFFSET counter"));
addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
sqlite3VdbeJumpHere(v, addr1);
if( p->pLimit ){
sqlite3VdbeAddOp(v, OP_Add, 0, 0);
}
}
if( p->pLimit ){
addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1);
addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1);
VdbeComment((v, "# LIMIT+OFFSET"));
sqlite3VdbeJumpHere(v, addr2);
}
}
/*
** Allocate a virtual index to use for sorting.
*/
static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -