?? select.c
字號:
sqlite3VdbeAddOp(v, OP_Close, pseudoTab, 0);
}
}
/*
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
** The declaration type is the exact datatype definition extracted from the
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
** is considered a column can be complex in the presence of subqueries. The
** result-set expression in all of the following SELECT statements is
** considered a column by this function.
**
** SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl;
** SELECT (SELECT col FROM tbl);
** SELECT abc FROM (SELECT col AS abc FROM tbl);
**
** The declaration type for any expression other than a column is NULL.
*/
static const char *columnType(
NameContext *pNC,
Expr *pExpr,
const char **pzOriginDb,
const char **pzOriginTab,
const char **pzOriginCol
){
char const *zType = 0;
char const *zOriginDb = 0;
char const *zOriginTab = 0;
char const *zOriginCol = 0;
int j;
if( pExpr==0 || pNC->pSrcList==0 ) return 0;
/* The TK_AS operator can only occur in ORDER BY, GROUP BY, HAVING,
** and LIMIT clauses. But pExpr originates in the result set of a
** SELECT. So pExpr can never contain an AS operator.
*/
assert( pExpr->op!=TK_AS );
switch( pExpr->op ){
case TK_AGG_COLUMN:
case TK_COLUMN: {
/* The expression is a column. Locate the table the column is being
** extracted from in NameContext.pSrcList. This table may be real
** database table or a subquery.
*/
Table *pTab = 0; /* Table structure column is extracted from */
Select *pS = 0; /* Select the column is extracted from */
int iCol = pExpr->iColumn; /* Index of column in pTab */
while( pNC && !pTab ){
SrcList *pTabList = pNC->pSrcList;
for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);
if( j<pTabList->nSrc ){
pTab = pTabList->a[j].pTab;
pS = pTabList->a[j].pSelect;
}else{
pNC = pNC->pNext;
}
}
if( pTab==0 ){
/* FIX ME:
** This can occurs if you have something like "SELECT new.x;" inside
** a trigger. In other words, if you reference the special "new"
** table in the result set of a select. We do not have a good way
** to find the actual table type, so call it "TEXT". This is really
** something of a bug, but I do not know how to fix it.
**
** This code does not produce the correct answer - it just prevents
** a segfault. See ticket #1229.
*/
zType = "TEXT";
break;
}
assert( pTab );
if( pS ){
/* The "table" is actually a sub-select or a view in the FROM clause
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
if( iCol>=0 && iCol<pS->pEList->nExpr ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
*/
NameContext sNC;
Expr *p = pS->pEList->a[iCol].pExpr;
sNC.pSrcList = pS->pSrc;
sNC.pNext = 0;
sNC.pParse = pNC->pParse;
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
}
}else if( pTab->pSchema ){
/* A real table */
assert( !pS );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
zType = "INTEGER";
zOriginCol = "rowid";
}else{
zType = pTab->aCol[iCol].zType;
zOriginCol = pTab->aCol[iCol].zName;
}
zOriginTab = pTab->zName;
if( pNC->pParse ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
zOriginDb = pNC->pParse->db->aDb[iDb].zName;
}
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT: {
/* The expression is a sub-select. Return the declaration type and
** origin info for the single column in the result set of the SELECT
** statement.
*/
NameContext sNC;
Select *pS = pExpr->pSelect;
Expr *p = pS->pEList->a[0].pExpr;
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
break;
}
#endif
}
if( pzOriginDb ){
assert( pzOriginTab && pzOriginCol );
*pzOriginDb = zOriginDb;
*pzOriginTab = zOriginTab;
*pzOriginCol = zOriginCol;
}
return zType;
}
/*
** Generate code that will tell the VDBE the declaration types of columns
** in the result set.
*/
static void generateColumnTypes(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i;
NameContext sNC;
sNC.pSrcList = pTabList;
sNC.pParse = pParse;
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
const char *zOrigDb = 0;
const char *zOrigTab = 0;
const char *zOrigCol = 0;
const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
/* The vdbe must make it's own copy of the column-type and other
** column specific strings, in case the schema is reset before this
** virtual machine is deleted.
*/
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P3_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P3_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P3_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P3_TRANSIENT);
}
}
/*
** Generate code that will tell the VDBE the names of columns
** in the result set. This information is used to provide the
** azCol[] values in the callback.
*/
static void generateColumnNames(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* List of tables */
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
int i, j;
sqlite3 *db = pParse->db;
int fullNames, shortNames;
#ifndef SQLITE_OMIT_EXPLAIN
/* If this is an EXPLAIN, skip this step */
if( pParse->explain ){
return;
}
#endif
assert( v!=0 );
if( pParse->colNamesSet || v==0 || sqlite3MallocFailed() ) return;
pParse->colNamesSet = 1;
fullNames = (db->flags & SQLITE_FullColNames)!=0;
shortNames = (db->flags & SQLITE_ShortColNames)!=0;
sqlite3VdbeSetNumCols(v, pEList->nExpr);
for(i=0; i<pEList->nExpr; i++){
Expr *p;
p = pEList->a[i].pExpr;
if( p==0 ) continue;
if( pEList->a[i].zName ){
char *zName = pEList->a[i].zName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, strlen(zName));
continue;
}
if( p->op==TK_COLUMN && pTabList ){
Table *pTab;
char *zCol;
int iCol = p->iColumn;
for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}
assert( j<pTabList->nSrc );
pTab = pTabList->a[j].pTab;
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
zCol = "rowid";
}else{
zCol = pTab->aCol[iCol].zName;
}
if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){
sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
}else if( fullNames || (!shortNames && pTabList->nSrc>1) ){
char *zName = 0;
char *zTab;
zTab = pTabList->a[j].zAlias;
if( fullNames || zTab==0 ) zTab = pTab->zName;
sqlite3SetString(&zName, zTab, ".", zCol, (char*)0);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P3_DYNAMIC);
}else{
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol));
}
}else if( p->span.z && p->span.z[0] ){
sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);
/* sqlite3VdbeCompressSpace(v, addr); */
}else{
char zName[30];
assert( p->op!=TK_COLUMN || pTabList==0 );
sprintf(zName, "column%d", i+1);
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0);
}
}
generateColumnTypes(pParse, pTabList, pEList);
}
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/*
** Name of the connection operator, used for error messages.
*/
static const char *selectOpName(int id){
char *z;
switch( id ){
case TK_ALL: z = "UNION ALL"; break;
case TK_INTERSECT: z = "INTERSECT"; break;
case TK_EXCEPT: z = "EXCEPT"; break;
default: z = "UNION"; break;
}
return z;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */
/*
** Forward declaration
*/
static int prepSelectStmt(Parse*, Select*);
/*
** Given a SELECT statement, generate a Table structure that describes
** the result set of that SELECT.
*/
Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
Table *pTab;
int i, j;
ExprList *pEList;
Column *aCol, *pCol;
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
if( prepSelectStmt(pParse, pSelect) ){
return 0;
}
if( sqlite3SelectResolve(pParse, pSelect, 0) ){
return 0;
}
pTab = sqliteMalloc( sizeof(Table) );
if( pTab==0 ){
return 0;
}
pTab->nRef = 1;
pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0;
pEList = pSelect->pEList;
pTab->nCol = pEList->nExpr;
assert( pTab->nCol>0 );
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
Expr *p, *pR;
char *zType;
char *zName;
int nName;
CollSeq *pColl;
int cnt;
NameContext sNC;
/* Get an appropriate name for the column
*/
p = pEList->a[i].pExpr;
assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
zName = sqliteStrDup(zName);
}else if( p->op==TK_DOT
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
/* For columns of the from A.B use B as the name */
zName = sqlite3MPrintf("%T", &pR->token);
}else if( p->span.z && p->span.z[0] ){
/* Use the original text of the column expression as its name */
zName = sqlite3MPrintf("%T", &p->span);
}else{
/* If all else fails, make up a name */
zName = sqlite3MPrintf("column%d", i+1);
}
sqlite3Dequote(zName);
if( sqlite3MallocFailed() ){
sqliteFree(zName);
sqlite3DeleteTable(0, pTab);
return 0;
}
/* Make sure the column name is unique. If the name is not unique,
** append a integer to the name so that it becomes unique.
*/
nName = strlen(zName);
for(j=cnt=0; j<i; j++){
if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
zName[nName] = 0;
zName = sqlite3MPrintf("%z:%d", zName, ++cnt);
j = -1;
if( zName==0 ) break;
}
}
pCol->zName = zName;
/* Get the typename, type affinity, and collating sequence for the
** column.
*/
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
zType = sqliteStrDup(columnType(&sNC, p, 0, 0, 0));
pCol->zType = zType;
pCol->affinity = sqlite3ExprAffinity(p);
pColl = sqlite3ExprCollSeq(pParse, p);
if( pColl ){
pCol->zColl = sqliteStrDup(pColl->zName);
}
}
pTab->iPKey = -1;
return pTab;
}
/*
** Prepare a SELECT statement for processing by doing the following
** things:
**
** (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[].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.
**
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -