]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Use sqlite3NestedParse to implement CREATE INDEX. (CVS 2070)
authordrh <drh@noemail.net>
Fri, 5 Nov 2004 20:58:39 +0000 (20:58 +0000)
committerdrh <drh@noemail.net>
Fri, 5 Nov 2004 20:58:39 +0000 (20:58 +0000)
FossilOrigin-Name: 47d8ebdaaddcb7a05e1917dd1dee2029c34228a4

manifest
manifest.uuid
src/build.c

index 67f06c361560e88d1227c775b57f83347ba6d283..3c0cd0577a529f18c9264bf1cd08a153eb9814cb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Create\stable\snow\sworks\swith\ssqlite3NestedParse.\s\sThis\schanged\suncovered\na\slatent\sbug\sin\sxprintf\swhich\sis\salso\sfixed.\s(CVS\s2069)
-D 2004-11-05T17:17:50
+C Use\ssqlite3NestedParse\sto\simplement\sCREATE\sINDEX.\s(CVS\s2070)
+D 2004-11-05T20:58:40
 F Makefile.in c4d2416860f472a1e3393714d0372074197565df
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -31,7 +31,7 @@ F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
 F src/btree.c bf0d3d59ec076f0a37378f8ac6090d157d925c24
 F src/btree.h 861e40b759a195ba63819740e484390012cf81ab
-F src/build.c f204aebf587f4543102dc6ea7c9283cb5949d7f0
+F src/build.c d1234774c8eec8f4e0365da14931236ac9ff323b
 F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad
 F src/delete.c f0af21a1ede15524a5edd59fe10ef486283a1ee9
 F src/expr.c be18081d2959a2cc53846d0fbedfec40fbfa1d6e
@@ -252,7 +252,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
-P cfee7f4a004c5e57d58edcf9de3ded0a199940a3
-R ec15467724d6da43213b204975fda018
+P b0506bdd701339d63166ada065445776dd499588
+R b008b9e3c2a495feb1a9866c40c60982
 U drh
-Z 4e4b37ba057c6cd50535fae2a97094d4
+Z 363f59f6d239c3e53daa03d8d94862e0
index f3fad82afe30b2f23c793bd285e419752dab9f25..af959ed97dbc94cd7ad775faafd6881fe3059772 100644 (file)
@@ -1 +1 @@
-b0506bdd701339d63166ada065445776dd499588
\ No newline at end of file
+47d8ebdaaddcb7a05e1917dd1dee2029c34228a4
\ No newline at end of file
index 5d9f9c0e86757aa8dbf556712d99ca5862f6c3a2..aec47521e93e0bb1b763e319a6fc831ed3e217d5 100644 (file)
@@ -24,9 +24,9 @@
 **     PRAGMA
 **
 <<<<<<< build.c
-** $Id: build.c,v 1.268 2004/11/05 17:17:50 drh Exp $
+** $Id: build.c,v 1.269 2004/11/05 20:58:40 drh Exp $
 =======
-** $Id: build.c,v 1.268 2004/11/05 17:17:50 drh Exp $
+** $Id: build.c,v 1.269 2004/11/05 20:58:40 drh Exp $
 >>>>>>> 1.262
 */
 #include "sqliteInt.h"
@@ -1420,38 +1420,6 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
       }
     }
 
-#if 0  
-    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_Pull, 3, 0);
-
-    if( pSelect ){
-      char *z = createTableStmt(p);
-      n = z ? strlen(z) : 0;
-      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
-      sqlite3VdbeChangeP3(v, -1, z, n);
-      sqliteFree(z);
-    }else{
-      if( p->pSelect ){
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE VIEW ", P3_STATIC);
-      }else{
-        sqlite3VdbeOp3(v, OP_String8, 0, 0, "CREATE TABLE ", P3_STATIC);
-      }
-      assert( pEnd!=0 );
-      n = Addr(pEnd->z) - Addr(pParse->sNameToken.z) + 1;
-      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
-      sqlite3VdbeChangeP3(v, -1, pParse->sNameToken.z, n);
-      sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
-    }
-    sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
-    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
-    sqlite3ChangeCookie(db, v, p->iDb);
-    sqlite3VdbeAddOp(v, OP_Close, 0, 0);
-#endif
-
     /* Compute the complete text of the CREATE statement */
     if( pSelect ){
       zStmt = createTableStmt(p);
@@ -1998,6 +1966,50 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
 #endif
 }
 
+/*
+** Generate code that will erase and refill index *pIdx.  This is
+** used to initialize a newly created index or to recompute the
+** content of an index in response to a REINDEX command.
+**
+** if memRootPage is not negative, it means that the index is newly
+** created.  The memory cell specified by memRootPage contains the
+** root page number of the index.  If memRootPage is negative, then
+** the index already exists and must be cleared before being refilled and
+** the root page number of the index is taken from pIndex->tnum.
+*/
+static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
+  Table *pTab = pIndex->pTable;  /* The table that is indexed */
+  int iTab = pParse->nTab;       /* Btree cursor used for pTab */
+  int iIdx = pParse->nTab+1;     /* Btree cursor used for pIndex */
+  int addr1;                     /* Address of top of loop */
+  int tnum;                      /* Root page of index */
+  Vdbe *v;                       /* Generate code into this virtual machine */
+
+  v = sqlite3GetVdbe(pParse);
+  if( v==0 ) return;
+  if( memRootPage>=0 ){
+    sqlite3VdbeAddOp(v, OP_MemLoad, memRootPage, 0);
+    tnum = 0;
+  }else{
+    tnum = pIndex->tnum;
+    sqlite3VdbeAddOp(v, OP_Clear, tnum, pIndex->iDb);
+  }
+  sqlite3VdbeAddOp(v, OP_Integer, pIndex->iDb, 0);
+  sqlite3VdbeOp3(v, OP_OpenWrite, iIdx, tnum,
+                    (char*)&pIndex->keyInfo, P3_KEYINFO);
+  sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
+  sqlite3VdbeAddOp(v, OP_OpenRead, iTab, pTab->tnum);
+  sqlite3VdbeAddOp(v, OP_SetNumColumns, iTab, pTab->nCol);
+  addr1 = sqlite3VdbeAddOp(v, OP_Rewind, iTab, 0);
+  sqlite3GenerateIndexKey(v, pIndex, iTab);
+  sqlite3VdbeOp3(v, OP_IdxPut, iIdx, pIndex->onError!=OE_None,
+                      "indexed columns are not unique", P3_STATIC);
+  sqlite3VdbeAddOp(v, OP_Next, iTab, addr1+1);
+  sqlite3VdbeChangeP2(v, addr1, sqlite3VdbeCurrentAddr(v));
+  sqlite3VdbeAddOp(v, OP_Close, iTab, 0);
+  sqlite3VdbeAddOp(v, OP_Close, iIdx, 0);
+}
+
 /*
 ** Create a new index for an SQL table.  pIndex is the name of the index 
 ** and pTable is the name of the table that is to be indexed.  Both will 
@@ -2277,58 +2289,50 @@ void sqlite3CreateIndex(
   ** step can be skipped.
   */
   else if( db->init.busy==0 ){
-    int n;
     Vdbe *v;
-    int lbl1, lbl2;
+    char *zStmt;
+    int iMem = pParse->nMem++;
 
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) goto exit_create_index;
-    if( pTblName!=0 ){
-      sqlite3BeginWriteOperation(pParse, 0, iDb);
-      sqlite3OpenMasterTable(v, iDb);
-    }
-    sqlite3VdbeAddOp(v, OP_NewRecno, 0, 0);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, "index", P3_STATIC);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, pIndex->zName, 0);
-    sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
+
+    /* Create the rootpage for the index
+    */
+    sqlite3BeginWriteOperation(pParse, 0, iDb);
     sqlite3VdbeAddOp(v, OP_CreateIndex, iDb, 0);
-    if( pTblName ){
-      sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
-      sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
-      sqlite3VdbeOp3(v, OP_OpenWrite, 1, 0,
-                     (char*)&pIndex->keyInfo, P3_KEYINFO);
-    }
-    sqlite3VdbeAddOp(v, OP_String8, 0, 0);
+    sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
+
+    /* Gather the complete text of the CREATE INDEX statement into
+    ** the zStmt variable
+    */
     if( pStart && pEnd ){
-      if( onError==OE_None ){
-        sqlite3VdbeChangeP3(v, -1, "CREATE INDEX ", P3_STATIC);
-      }else{
-        sqlite3VdbeChangeP3(v, -1, "CREATE UNIQUE INDEX ", P3_STATIC);
-      }
-      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
-      n = Addr(pEnd->z) - Addr(pName->z) + 1;
-      sqlite3VdbeChangeP3(v, -1, pName->z, n);
-      sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
+      /* A named index with an explicit CREATE INDEX statement */
+      zStmt = sqlite3MPrintf("CREATE%s INDEX %.*q",
+        onError==OE_None ? "" : " UNIQUE",
+        Addr(pEnd->z) - Addr(pName->z) + 1,
+        pName->z);
+    }else{
+      /* An automatic index created by a PRIMARY KEY or UNIQUE constraint */
+      zStmt = sqlite3MPrintf("");
     }
-    sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC);
-    sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0);
+
+    /* Add an entry in sqlite_master for this index
+    */
+    sqlite3NestedParse(pParse, 
+        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#0,'%s');",
+        db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+        pIndex->zName,
+        pTab->zName,
+        zStmt
+    );
+    sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
+    sqliteFree(zStmt);
+
+    /* Fill the index with data and reparse the schema
+    */
     if( pTblName ){
-      sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-      sqlite3VdbeAddOp(v, OP_OpenRead, 2, pTab->tnum);
-      /* VdbeComment((v, "%s", pTab->zName)); */
-      sqlite3VdbeAddOp(v, OP_SetNumColumns, 2, pTab->nCol);
-      lbl2 = sqlite3VdbeMakeLabel(v);
-      sqlite3VdbeAddOp(v, OP_Rewind, 2, lbl2);
-      lbl1 = sqlite3VdbeCurrentAddr(v);
-      sqlite3GenerateIndexKey(v, pIndex, 2);
-      sqlite3VdbeOp3(v, OP_IdxPut, 1, pIndex->onError!=OE_None,
-                      "indexed columns are not unique", P3_STATIC);
-      sqlite3VdbeAddOp(v, OP_Next, 2, lbl1);
-      sqlite3VdbeResolveLabel(v, lbl2);
-      sqlite3VdbeAddOp(v, OP_Close, 2, 0);
-      sqlite3VdbeAddOp(v, OP_Close, 1, 0);
+      sqlite3RefillIndex(pParse, pIndex, iMem);
       sqlite3ChangeCookie(db, v, iDb);
-      sqlite3VdbeAddOp(v, OP_Close, 0, 0);
       sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
          sqlite3MPrintf("name='%q'", pIndex->zName), P3_DYNAMIC);
     }