]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Tables created with the CREATE TABLE <tbl> AS SELECT ... syntax now inherit
authordanielk1977 <danielk1977@noemail.net>
Mon, 7 Jun 2004 10:00:31 +0000 (10:00 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Mon, 7 Jun 2004 10:00:31 +0000 (10:00 +0000)
column declaration types from the SELECT statement. (CVS 1538)

FossilOrigin-Name: 31c1668dbc2b84438a5b78b0270f58b37b03791d

manifest
manifest.uuid
src/build.c
src/select.c
test/table.test

index 84c236d7e236365790ad76a00c5011aa7e484c0c..0eeee68559c1a00b048532d899e7a72d959a6cfa 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\spragma\sto\sset/get\stext\sencoding.\sAlso\sfix\san\sobscure\sproblem\swhere\sa\ntemp\strigger\scould\sbe\saccidently\sdropped.\s(CVS\s1537)
-D 2004-06-07T07:52:18
+C Tables\screated\swith\sthe\sCREATE\sTABLE\s<tbl>\sAS\sSELECT\s...\ssyntax\snow\sinherit\ncolumn\sdeclaration\stypes\sfrom\sthe\sSELECT\sstatement.\s(CVS\s1538)
+D 2004-06-07T10:00:31
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -27,7 +27,7 @@ F src/attach.c e76e4590ec5dd389e5646b171881b5243a6ef391
 F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
 F src/btree.c 3f0c22ab8c0c000ee5de4ad875836c111c4191c6
 F src/btree.h 589427ac13bb544d298cd99726e2572a6fe4bdaa
-F src/build.c 92144f30d30fa00cb21c9c9e51de49cfb948d113
+F src/build.c e8043747608eba9ff293f4fcb52cbf958625d599
 F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
 F src/delete.c b30f08250c9ed53a25a13c7c04599c1e8753992d
 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
@@ -53,7 +53,7 @@ F src/parse.y 27c1ce09f9d309be91f9e537df2fb00892990af4
 F src/pragma.c 54b4d67fa81fd38b911aa3325348dcae9ceac5a4
 F src/printf.c 77ee9ec6dbf1b7512b17d63ccf8322ea9466278b
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
-F src/select.c 02d711160100ef3a730060f7cfb5bc85fde06d72
+F src/select.c 0ac0adeb2ae15255ac4399d9ee1b0d25a266a676
 F src/shell.c 79af86d39b2149c7f16219fcbe636e7c2da9df8e
 F src/sqlite.h.in 4705697dd7213f322d59ffc69b48b8ac32b23373
 F src/sqliteInt.h 845d2a3ffdb9a9050a1b55044d4856227b649b84
@@ -144,7 +144,7 @@ F test/select5.test 3f3f0f31e674fa61f8a3bdb6af1517dfae674081
 F test/select6.test a9e31906e700e7c7592c4d0acfc022808f718baf
 F test/sort.test 863f07884fb68a70b738998e9a548132a0d0b7d9
 F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
-F test/table.test 71f808817b50ae3a9a693a88b3ea003f1031cdbb
+F test/table.test 1defd90e8200661a822618b18748b9339a7fef2f
 F test/tableapi.test e0c4cce61e58343caa84dab33fa6823cb35fe1e1
 F test/tclsqlite.test 853e4372004d209e2ff0d4b0b35c91d4f64cd7d8
 F test/temptable.test a770ba6308d7f7332fce985086b8e06bed6430c2
@@ -215,7 +215,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 4f7c0961ad6cb7082bf7716f0c7ca16a8742c039
-R ec69eb8a9c750d8d0b48358a8267ec3f
+P 983221b038813c5a7892564896e39597c223c4c3
+R 9252a60acb4c967bd956d4d623f3bcb8
 U danielk1977
-Z 53de26870eaceb80255c757bed464dd0
+Z b067b126b336d1aa6d04e5d165e845dc
index 1b432f643fc633a7ebbca714aeea46fc07702614..f9cb27eb021f5817eb2225aaaf7e3f897140717c 100644 (file)
@@ -1 +1 @@
-983221b038813c5a7892564896e39597c223c4c3
\ No newline at end of file
+31c1668dbc2b84438a5b78b0270f58b37b03791d
\ No newline at end of file
index a0cd3b589c4774a1dc1bd52ec092f674cc35cc30..6600d16da59dfa5fbcebdd9aa5777ad71ca15040 100644 (file)
@@ -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);
   }
 
index d6d60bb30f355afc48887eb2d4b0be0c8106ab5f..083f19782e1e6ffbee894261f20eb2780ba21715 100644 (file)
@@ -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;
index 5367ac40465b2b234df76ed98b1792c015d27f3f..3314800db215d41b608768b6b7c6f87e71e8713a 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the CREATE TABLE statement.
 #
-# $Id: table.test,v 1.24 2004/05/24 12:55:55 danielk1977 Exp $
+# $Id: table.test,v 1.25 2004/06/07 10:00:31 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -305,6 +305,7 @@ do_test table-7.3 {
 # Try out the CREATE TABLE AS syntax
 #
 do_test table-8.1 {
+breakpoint
   execsql2 {
     CREATE TABLE t2 AS SELECT * FROM weird;
     SELECT * FROM t2;
@@ -315,13 +316,13 @@ do_test table-8.1.1 {
     SELECT sql FROM sqlite_master WHERE name='t2';
   }
 } {{CREATE TABLE t2(
-  'desc',
-  'asc',
-  'explain',
-  '14_vac',
-  fuzzy_dog_12,
-  'begin',
-  'end'
+  'desc' text,
+  'asc' text,
+  'explain' int,
+  '14_vac' boolean,
+  fuzzy_dog_12 varchar(10),
+  'begin' blob,
+  'end' clob
 )}}
 do_test table-8.2 {
   execsql {
@@ -340,7 +341,7 @@ do_test table-8.3.1 {
   execsql {
     SELECT sql FROM sqlite_master WHERE name='t4''abc'
   }
-} {{CREATE TABLE 't4''abc'(cnt,'max(b+c)')}}
+} {{CREATE TABLE 't4''abc'(cnt NUMERIC,'max(b+c)' NUMERIC)}}
 do_test table-8.4 {
   execsql2 {
     CREATE TEMPORARY TABLE t5 AS SELECT count(*) AS [y'all] FROM [t3'xyz];