aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c68
-rw-r--r--src/select.c94
2 files changed, 102 insertions, 60 deletions
diff --git a/src/build.c b/src/build.c
index a0cd3b589..6600d16da 100644
--- a/src/build.c
+++ b/src/build.c
@@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
-** $Id: build.c,v 1.207 2004/06/07 07:52:18 danielk1977 Exp $
+** $Id: build.c,v 1.208 2004/06/07 10:00:31 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -714,7 +714,6 @@ void sqlite3AddColumnType(Parse *pParse, Token *pFirst, Token *pLast){
z[j++] = c;
}
z[j] = 0;
-// pCol->sortOrder = sqlite3CollateType(z, n);
pCol->affinity = sqlite3AffinityType(z, n);
}
@@ -985,6 +984,9 @@ static char *createTableStmt(Table *p){
n = 0;
for(i=0; i<p->nCol; i++){
n += identLength(p->aCol[i].zName);
+ if( p->aCol[i].zType ){
+ n += (strlen(p->aCol[i].zType) + 1);
+ }
}
n += identLength(p->zName);
if( n<40 ){
@@ -1008,6 +1010,11 @@ static char *createTableStmt(Table *p){
k += strlen(&zStmt[k]);
zSep = zSep2;
identPut(zStmt, &k, p->aCol[i].zName);
+ if( p->aCol[i].zType ){
+ zStmt[k++] = ' ';
+ strcpy(&zStmt[k], p->aCol[i].zType);
+ k += strlen(p->aCol[i].zType);
+ }
}
strcpy(&zStmt[k], zEnd);
return zStmt;
@@ -1041,18 +1048,12 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
p = pParse->pNewTable;
if( p==0 ) return;
+ assert( !db->init.busy || !pSelect );
+
/* If the table is generated from a SELECT, then construct the
** list of columns and the text of the table.
*/
if( pSelect ){
- Table *pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
- if( pSelTab==0 ) return;
- assert( p->aCol==0 );
- p->nCol = pSelTab->nCol;
- p->aCol = pSelTab->aCol;
- pSelTab->nCol = 0;
- pSelTab->aCol = 0;
- sqlite3DeleteTable(0, pSelTab);
}
/* If the db->init.busy is 1 it means we are reading the SQL off the
@@ -1078,6 +1079,7 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
+
if( p->pSelect==0 ){
/* A regular table */
sqlite3VdbeOp3(v, OP_CreateTable, 0, p->iDb, (char*)&p->tnum, P3_POINTER);
@@ -1086,11 +1088,44 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
}
p->tnum = 0;
- sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, p->pSelect==0?"table":"view", P3_STATIC);
+
+ sqlite3VdbeAddOp(v, OP_Close, 0, 0);
+
+ /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
+ ** statement to populate the new table. The root-page number for the
+ ** new table is on the top of the vdbe stack.
+ **
+ ** Once the SELECT has been coded by sqlite3Select(), it is in a
+ ** suitable state to query for the column names and types to be used
+ ** by the new table.
+ */
+ if( pSelect ){
+ Table *pSelTab;
+ sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0);
+ sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0);
+ pParse->nTab = 2;
+ sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0);
+ sqlite3VdbeAddOp(v, OP_Close, 1, 0);
+ if( pParse->nErr==0 ){
+ pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
+ if( pSelTab==0 ) return;
+ assert( p->aCol==0 );
+ p->nCol = pSelTab->nCol;
+ p->aCol = pSelTab->aCol;
+ pSelTab->nCol = 0;
+ pSelTab->aCol = 0;
+ sqlite3DeleteTable(0, pSelTab);
+ }
+ }
+
+ sqlite3OpenMasterTable(v, p->iDb);
+
+ sqlite3VdbeOp3(v, OP_String8, 0, 0, p->pSelect==0?"table":"view",P3_STATIC);
sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
sqlite3VdbeOp3(v, OP_String8, 0, 0, p->zName, 0);
- sqlite3VdbeAddOp(v, OP_Dup, 4, 0);
+ sqlite3VdbeAddOp(v, OP_Pull, 3, 0);
+
if( pSelect ){
char *z = createTableStmt(p);
n = z ? strlen(z) : 0;
@@ -1115,12 +1150,7 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
sqlite3ChangeCookie(db, v, p->iDb);
}
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
- if( pSelect ){
- sqlite3VdbeAddOp(v, OP_Integer, p->iDb, 0);
- sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0);
- pParse->nTab = 2;
- sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0);
- }
+
sqlite3EndWriteOperation(pParse);
}
diff --git a/src/select.c b/src/select.c
index d6d60bb30..083f19782 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.183 2004/06/05 00:01:46 drh Exp $
+** $Id: select.c,v 1.184 2004/06/07 10:00:31 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -612,19 +612,45 @@ static void generateSortTail(
}
/*
-** Generate code that will tell the VDBE the datatypes of
-** columns in the result set.
-**
-** This routine only generates code if the "PRAGMA show_datatypes=on"
-** has been executed. The datatypes are reported out in the azCol
-** parameter to the callback function. The first N azCol[] entries
-** are the names of the columns, and the second N entries are the
-** datatypes for the columns.
-**
-** The "datatype" for a result that is a column of a type is the
-** datatype definition extracted from the CREATE TABLE statement.
-** The datatype for an expression is either TEXT or NUMERIC. The
-** datatype for a ROWID field is INTEGER.
+** Return a pointer to a string containing the 'declaration type' of the
+** expression pExpr. The string may be treated as static by the caller.
+**
+** If 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 an expression is either TEXT, NUMERIC or ANY.
+** The declaration type for a ROWID field is INTEGER.
+*/
+static const char *columnType(Parse *pParse, SrcList *pTabList, Expr *pExpr){
+ char const *zType = 0;
+ int j;
+ if( pExpr==0 ) return 0;
+ if( pExpr->op==TK_COLUMN && pTabList ){
+ Table *pTab;
+ int iCol = pExpr->iColumn;
+ for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->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 ){
+ zType = "INTEGER";
+ }else{
+ zType = pTab->aCol[iCol].zType;
+ }
+ }else{
+ switch( sqlite3ExprType(pExpr) ){
+ case SQLITE_AFF_TEXT: zType = "TEXT"; break;
+ case SQLITE_AFF_NUMERIC: zType = "NUMERIC"; break;
+ default: zType = "ANY"; break;
+ }
+ }
+ 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 */
@@ -632,31 +658,11 @@ static void generateColumnTypes(
ExprList *pEList /* Expressions defining the result set */
){
Vdbe *v = pParse->pVdbe;
- int i, j;
+ int i;
for(i=0; i<pEList->nExpr; i++){
Expr *p = pEList->a[i].pExpr;
- char *zType = 0;
+ const char *zType = columnType(pParse, pTabList, p);
if( p==0 ) continue;
- if( p->op==TK_COLUMN && pTabList ){
- Table *pTab;
- 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 ){
- zType = "INTEGER";
- }else{
- zType = pTab->aCol[iCol].zType;
- }
- }else{
- switch( sqlite3ExprType(p) ){
- case SQLITE_AFF_TEXT: zType = "TEXT"; break;
- case SQLITE_AFF_NUMERIC: zType = "NUMERIC"; break;
- default: zType = "ANY"; break;
- }
- }
sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, P3_STATIC);
}
}
@@ -779,10 +785,12 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
assert( pTab->nCol>0 );
pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
for(i=0; i<pTab->nCol; i++){
- Expr *p, *pR;
+ Expr *pR;
+ char *zType;
+ Expr *p = pEList->a[i].pExpr;
if( pEList->a[i].zName ){
aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
- }else if( (p=pEList->a[i].pExpr)->op==TK_DOT
+ }else if( p->op==TK_DOT
&& (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
int cnt;
sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
@@ -803,9 +811,13 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
sprintf(zBuf, "column%d", i+1);
pTab->aCol[i].zName = sqliteStrDup(zBuf);
}
-
- /* Affinity is always NONE, as there is no type name. */
- pTab->aCol[i].affinity = SQLITE_AFF_NONE;
+
+ zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
+ pTab->aCol[i].zType = zType;
+ pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
+ if( zType ){
+ pTab->aCol[i].affinity = sqlite3AffinityType(zType, strlen(zType));
+ }
}
pTab->iPKey = -1;
return pTab;