]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
First cut at a REINDEX command. Basic testing only. No documentation. (CVS 2072)
authordrh <drh@noemail.net>
Fri, 5 Nov 2004 23:46:15 +0000 (23:46 +0000)
committerdrh <drh@noemail.net>
Fri, 5 Nov 2004 23:46:15 +0000 (23:46 +0000)
FossilOrigin-Name: 11dba47e61279bdf3be6f64a6259b877f3bf6155

manifest
manifest.uuid
src/build.c
src/parse.y
src/sqliteInt.h
src/test1.c
test/reindex.test [new file with mode: 0644]

index 5adb28c0947e046962248336dcef53e988cb8470..14f12d8ea4c59890836f33707796a446573447c6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Use\ssqlite3NestedParse\sto\simplement\sDROP\sINDEX.\s(CVS\s2071)
-D 2004-11-05T22:18:49
+C First\scut\sat\sa\sREINDEX\scommand.\s\sBasic\stesting\sonly.\s\sNo\sdocumentation.\s(CVS\s2072)
+D 2004-11-05T23:46:15
 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 e498f958ebb4678e103224edd3a5c2ebcc42d18f
+F src/build.c 154e7a666a7b36da04c739a6af87d5e9bdcd0cda
 F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad
 F src/delete.c f0af21a1ede15524a5edd59fe10ef486283a1ee9
 F src/expr.c be18081d2959a2cc53846d0fbedfec40fbfa1d6e
@@ -54,17 +54,17 @@ F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 868c67e4ff8a1785c06caaf483fddb5a95013af0
 F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
-F src/parse.y 97247c0a89ca1667729db5035f1ee60140960984
+F src/parse.y 8456726833755ecd6dac9bcd8af205c8dc419d01
 F src/pragma.c 6a0ae7721e614c5a921e918ab5206d5e654f1a6f
 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b
 F src/shell.c 55adda3cf3c1cc2f6c1919aac17b2318f9c2a96f
 F src/sqlite.h.in 4f97b5907acfd2a5068cb0cec9d5178816734db7
-F src/sqliteInt.h 5d26b41b2ab7eeab1bd9db330ed7b7929d2ae875
+F src/sqliteInt.h 9f846c4b752b9a1237e8250f8f8b3ecd1347a086
 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
 F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008
-F src/test1.c df1d1ca2c40cafefb9a29860f072c4d0fee1a7b5
+F src/test1.c 91345097d94b4ad71f88776c2764e18c7955502a
 F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8
 F src/test3.c de9edf178c02707cd37fd80b54e4c2ea77251cc0
 F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
@@ -160,6 +160,7 @@ F test/printf.test 92ba4c510b4fc61120ffa4a01820446ed917ae57
 F test/progress.test 5ddba78cb6011fba36093973cfb3ac473b8fb96a x
 F test/quick.test 2dca186ebd5c418a7699944ba3b5e437d765eddd
 F test/quote.test 6d75cf635d93ba2484dc9cb378d88cbae9dc2c62
+F test/reindex.test 1d579cdb942c5f9c26c7f8c94cdc3024cabf2644
 F test/rollback.test 4097328d44510277244ef4fa51b22b2f11d7ef4c
 F test/rowid.test 1ce3f1520d2082b0363e7d9bdef904cb72b9efe8
 F test/select1.test 0e459a8066259445d707cc4f64ea00459441e29f
@@ -252,7 +253,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
-P 47d8ebdaaddcb7a05e1917dd1dee2029c34228a4
-R d45e3580de79d7367f59fbd57af5e6a1
+P 0f81aa5b057eab908b46b70ea9e9a42bc2ee8c21
+R 877c89049e39a4d803a0375d417e1d42
 U drh
-Z 4c43f2f11733856473822a7670e21c59
+Z 82c5d66bdd823220be3997a2e30a2b5d
index cc9caa8dd049c0a44169db89b0b3024985660c9f..0a6ff8bac4c7476394bd44fffd32d8de14840e36 100644 (file)
@@ -1 +1 @@
-0f81aa5b057eab908b46b70ea9e9a42bc2ee8c21
\ No newline at end of file
+11dba47e61279bdf3be6f64a6259b877f3bf6155
\ No newline at end of file
index c796cf3a948ae90d8131b7e0e1503edbfb69bd1a..92ddfd702b57ffbf9f6fc8c29c6c2ef4f3b7083b 100644 (file)
 **     BEGIN TRANSACTION
 **     COMMIT
 **     ROLLBACK
-**     PRAGMA
 **
-<<<<<<< build.c
-** $Id: build.c,v 1.270 2004/11/05 22:18:49 drh Exp $
-=======
-** $Id: build.c,v 1.270 2004/11/05 22:18:49 drh Exp $
->>>>>>> 1.262
+** $Id: build.c,v 1.271 2004/11/05 23:46:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1989,6 +1984,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   int addr1;                     /* Address of top of loop */
   int tnum;                      /* Root page of index */
   Vdbe *v;                       /* Generate code into this virtual machine */
+  int isUnique;                  /* True for a unique index */
 
   v = sqlite3GetVdbe(pParse);
   if( v==0 ) return;
@@ -2007,8 +2003,11 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   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);
+  isUnique = pIndex->onError!=OE_None;
+  sqlite3VdbeAddOp(v, OP_IdxPut, iIdx, isUnique);
+  if( isUnique ){
+    sqlite3VdbeChangeP3(v, -1, "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);
@@ -2760,3 +2759,107 @@ sqlite3_value *sqlite3GetTransientValue(sqlite3 *db){
   }
   return db->pValue;
 }
+
+/*
+** Check to see if pIndex uses the collating sequence pColl.  Return
+** true if it does and false if it does not.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+static int collationMatch(CollSeq *pColl, Index *pIndex){
+  int n = pIndex->keyInfo.nField;
+  CollSeq **pp = pIndex->keyInfo.aColl;
+  while( n-- ){
+    if( *pp==pColl ) return 1;
+    pp++;
+  }
+  return 0;
+}
+#endif
+
+/*
+** Recompute all indices of pTab that use the collating sequence pColl.
+** If pColl==0 then recompute all indices of pTab.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void reindexTable(Parse *pParse, Table *pTab, CollSeq *pColl){
+  Index *pIndex;              /* An index associated with pTab */
+
+  for(pIndex=pTab->pIndex; pIndex; pIndex=pIndex->pNext){
+    if( pColl==0 || collationMatch(pColl,pIndex) ){
+      sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
+      sqlite3RefillIndex(pParse, pIndex, -1);
+    }
+  }
+}
+#endif
+
+/*
+** Recompute all indices of all tables in all databases where the
+** indices use the collating sequence pColl.  If pColl==0 then recompute
+** all indices everywhere.
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void reindexDatabases(Parse *pParse, CollSeq *pColl){
+  Db *pDb;                    /* A single database */
+  int iDb;                    /* The database index number */
+  sqlite3 *db = pParse->db;   /* The database connection */
+  HashElem *k;                /* For looping over tables in pDb */
+  Table *pTab;                /* A table in the database */
+
+  for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
+    if( pDb==0 ) continue;
+      for(k=sqliteHashFirst(&pDb->tblHash);  k; k=sqliteHashNext(k)){
+      pTab = (Table*)sqliteHashData(k);
+      reindexTable(pParse, pTab, pColl);
+    }
+  }
+}
+#endif
+
+/*
+** Generate code for a REINDEX command.  If the argument is present it
+** is the name of a collating sequence and all indices that use that
+** collating sequence should be reindexed.  If no argument is present,
+** then rebuild all indices
+*/
+#ifndef SQLITE_OMIT_REINDEX
+void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
+  CollSeq *pColl;             /* Collating sequence to be reindexed, or NULL */
+  char *z;                    /* Name of a table or index */
+  const char *zDb;            /* Name of the database */
+  Table *pTab;                /* A table in the database */
+  Index *pIndex;              /* An index associated with pTab */
+  int iDb;                    /* The database index number */
+  sqlite3 *db = pParse->db;   /* The database connection */
+  Token *pObjName;            /* Name of the table or index to be reindexed */
+
+  if( pName1==0 ){
+    reindexDatabases(pParse, 0);
+    return;
+  }else if( pName2==0 ){
+    pColl = sqlite3FindCollSeq(db, db->enc, pName1->z, pName1->n, 0);
+    if( pColl ){
+      reindexDatabases(pParse, pColl);
+      return;
+    }
+  }
+  iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pObjName);
+  if( iDb<0 ) return;
+  z = sqlite3NameFromToken(pObjName);
+  zDb = db->aDb[iDb].zName;
+  pTab = sqlite3FindTable(db, z, zDb);
+  if( pTab ){
+    reindexTable(pParse, pTab, 0);
+    sqliteFree(z);
+    return;
+  }
+  pIndex = sqlite3FindIndex(db, z, zDb);
+  sqliteFree(z);
+  if( pIndex ){
+    sqlite3BeginWriteOperation(pParse, 0, iDb);
+    sqlite3RefillIndex(pParse, pIndex, -1);
+    return;
+  }
+  sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
+}
+#endif
index f9990525dddac0a13ec270efb27b4a1ad88dadfc..4193ac4c95839c8c7551400dce483c8ecdc41e28 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.149 2004/11/05 05:10:29 drh Exp $
+** @(#) $Id: parse.y,v 1.150 2004/11/05 23:46:15 drh Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -920,3 +920,9 @@ database_kw_opt ::= .
 cmd ::= DETACH database_kw_opt nm(D). {
   sqlite3Detach(pParse, &D);
 }
+
+////////////////////////// REINDEX collation //////////////////////////////////
+%ifndef SQLITE_OMIT_REINDEX
+cmd ::= REINDEX.                {sqlite3Reindex(pParse, 0, 0);}
+cmd ::= REINDEX nm(X) dbnm(Y).  {sqlite3Reindex(pParse, &X, &Y);}
+%endif
index a0d8ecddcb34a7895eeabb97d50917ae7beff758..b6e7dfcf81f32fb134b8b74d0f4ca76cb70be4f7 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.334 2004/11/05 17:17:50 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.335 2004/11/05 23:46:15 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1455,5 +1455,6 @@ sqlite3_value *sqlite3ValueNew();
 sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
 extern const unsigned char sqlite3UpperToLower[];
 void sqlite3RootPageMoved(Db*, int, int);
+void sqlite3Reindex(Parse*, Token*, Token*);
 
 #endif
index 1dd4a793d0dc2c8c8dea4d01cdf271b0a1fbc84c..02a722e835d9c0745ac3fe059cb1376b758f39cc 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.107 2004/11/03 16:27:01 drh Exp $
+** $Id: test1.c,v 1.108 2004/11/05 23:46:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -2558,6 +2558,11 @@ static void set_options(Tcl_Interp *interp){
 #else
   Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
 #endif
+#ifdef SQLITE_OMIT_REINDEX
+  Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
+#else
+  Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
+#endif
 }
 
 /*
diff --git a/test/reindex.test b/test/reindex.test
new file mode 100644 (file)
index 0000000..1dc7956
--- /dev/null
@@ -0,0 +1,66 @@
+# 2004 November 5
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+# This file implements tests for the REINDEX command.
+#
+# $Id: reindex.test,v 1.1 2004/11/05 23:46:15 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# There is nothing to test if REINDEX is disable for this build.
+#
+ifcapable {!reindex} {
+  finish_test
+  return
+}
+
+# Basic sanity checks.
+#
+do_test reindex-1.1 {
+  execsql {
+    CREATE TABLE t1(a,b);
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 VALUES(3,4);
+    CREATE INDEX i1 ON t1(a);
+    REINDEX;
+  }
+} {}
+integrity_check reindex-1.2
+do_test reindex-1.3 {
+  execsql {
+    REINDEX t1;
+  }
+} {}
+integrity_check reindex-1.4
+do_test reindex-1.5 {
+  execsql {
+    REINDEX i1;
+  }
+} {}
+integrity_check reindex-1.6
+do_test reindex-1.7 {
+  execsql {
+    REINDEX main.t1;
+  }
+} {}
+do_test reindex-1.8 {
+  execsql {
+    REINDEX main.i1;
+  }
+} {}
+do_test reindex-1.9 {
+  catchsql {
+    REINDEX bogus
+  }
+} {1 {unable to identify the object to be reindexed}}
+
+finish_test