-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
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
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
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
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
-0f81aa5b057eab908b46b70ea9e9a42bc2ee8c21
\ No newline at end of file
+11dba47e61279bdf3be6f64a6259b877f3bf6155
\ No newline at end of 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>
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;
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);
}
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
** 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}
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
*************************************************************************
** 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_
sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
extern const unsigned char sqlite3UpperToLower[];
void sqlite3RootPageMoved(Db*, int, int);
+void sqlite3Reindex(Parse*, Token*, Token*);
#endif
** 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"
#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
}
/*
--- /dev/null
+# 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