Add support for CREATE INDEX IF NOT EXISTS and DROP INDEX IF EXISTS. (CVS 2855)

FossilOrigin-Name: 551cdd6c309e75687abaeac5381b794cd5e4c10a
This commit is contained in:
drh 2006-01-04 15:54:36 +00:00
parent f93339decb
commit 4d91a701bd
7 changed files with 48 additions and 29 deletions

View File

@ -1,5 +1,5 @@
C Always\scase\s0\sto\s(char*)\son\svarargs\sfunctions.\s\sOtherwise\sthere\sare\sproblems\non\s64-bit\smachines.\s(CVS\s2854)
D 2006-01-03T15:16:26
C Add\ssupport\sfor\sCREATE\sINDEX\sIF\sNOT\sEXISTS\sand\sDROP\sINDEX\sIF\sEXISTS.\s(CVS\s2855)
D 2006-01-04T15:54:36
F Makefile.in e3c6b3a38d734d41574c04f2fc90d18de2b87102
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -36,7 +36,7 @@ F src/attach.c 07822dbd2dcf6de548aba6cb24142aec800fa3b6
F src/auth.c 31e2304bef67f44d635655f44234387ea7d21454
F src/btree.c ec89192ceeae9343c5d8f2564b8c9b8c958e6bfc
F src/btree.h d6481f9253f0b5fa40b35da4b93a54d0f9c5f9f2
F src/build.c bb4c9df2583246728167659d401fd75aa3d9997f
F src/build.c 6bf007d0da0527820329d5695c90e1042bef1e58
F src/callback.c 62066afd516f220575e81b1a1239ab92a2eae252
F src/complete.c df1681cef40dec33a286006981845f87b194e7a4
F src/date.c bb079317bff6a2b78aba5c0d2ddae5f6f03acfb7
@ -61,15 +61,15 @@ F src/os_win.c 7e2d09f81cb83709b9774ac6be80fa3cb08ac86d
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c 681b4e39d581ead8fd54283176138bec924a4bae
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
F src/parse.y fea607bdc0f4440e001ca277a49f507b5a3fb1e5
F src/parse.y 58258759fabdd48f1d2561e276097290b1ea2680
F src/pragma.c 8883b4d34796efa315bdd0ec1b03f580ef1575b9
F src/prepare.c 1f2bf83038792294ef4a307d95993f90e6c70561
F src/prepare.c 7639314c504f602d87730238c44ccddc4407ac60
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d
F src/select.c 5b0ccd6688e61c0720efa45075a3f9da60180554
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
F src/sqlite.h.in ba3a29daa6a16e054191ccb384a981964e882a1d
F src/sqliteInt.h bb648c5274d67060cb13f0cd0da141aff1205358
F src/sqliteInt.h a9b187e8621cd3c20c7ef6c0716d77cbed716d4d
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
F src/tclsqlite.c 124f822d6c55c5d95420672bf39fe3ba60ae1f76
F src/test1.c 988dbac66c3ca92d69fbe0283d77e86cd6f73ce8
@ -160,7 +160,7 @@ F test/fkey1.test 153004438d51e6769fb1ce165f6313972d6263ce
F test/func.test a7119afcc16abdf24b24486684fb888279008f75
F test/hook.test 3bae7892e04ba40f20e205027c3ba343e46d22ff
F test/in.test cead6165aebbe0d451bb2263a307173acfeb6240
F test/index.test 3871c47ec475f779f0b99dc36a3d177951995712
F test/index.test c90ab389586dbddfeb6817cd137737b2de1b6522
F test/index2.test 9ad98243fd7fe833795a9cc662f371f0eed4ff4f
F test/index3.test f66718cd92ce1216819d47e6a156755e4b2c4ca1
F test/insert.test b0a89e1568fe9890758f8f2b43b68e840e8f1a1a
@ -335,7 +335,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 7c3492c8404c39c808af4429b4fcdb7413539ab3
R ce1d0ff632d7208d0510c9231ee127d4
P 837dc77ff9f5271b7e1bb8602fc021670c7802d1
R ec161a22b551e019c6b2c8761d7b0084
U drh
Z 420d480c90c636c6935ddb788f609c13
Z 4a9af6bfc70464e631ff856496627e88

View File

@ -1 +1 @@
837dc77ff9f5271b7e1bb8602fc021670c7802d1
551cdd6c309e75687abaeac5381b794cd5e4c10a

View File

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.364 2005/12/29 23:33:54 drh Exp $
** $Id: build.c,v 1.365 2006/01/04 15:54:36 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -1056,7 +1056,7 @@ void sqlite3AddPrimaryKey(
"INTEGER PRIMARY KEY");
#endif
}else{
sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder);
sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0, sortOrder, 0);
pList = 0;
}
@ -2105,7 +2105,8 @@ void sqlite3CreateIndex(
int onError, /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
Token *pStart, /* The CREATE token that begins a CREATE TABLE statement */
Token *pEnd, /* The ")" that closes the CREATE INDEX statement */
int sortOrder /* Sort order of primary key when pList==NULL */
int sortOrder, /* Sort order of primary key when pList==NULL */
int ifNotExist /* Omit error if index already exists */
){
Table *pTab = 0; /* Table to be indexed */
Index *pIndex = 0; /* The index to be created */
@ -2199,7 +2200,9 @@ void sqlite3CreateIndex(
if( !db->init.busy ){
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ) goto exit_create_index;
if( sqlite3FindIndex(db, zName, pDb->zName)!=0 ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
if( !ifNotExist ){
sqlite3ErrorMsg(pParse, "index %s already exists", zName);
}
goto exit_create_index;
}
if( sqlite3FindTable(db, zName, 0)!=0 ){
@ -2525,7 +2528,7 @@ void sqlite3DefaultRowEst(Index *pIdx){
** This routine will drop an existing named index. This routine
** implements the DROP INDEX statement.
*/
void sqlite3DropIndex(Parse *pParse, SrcList *pName){
void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
Index *pIndex;
Vdbe *v;
sqlite3 *db = pParse->db;
@ -2539,7 +2542,9 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
}
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
if( !ifExists ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
}
pParse->checkSchema = 1;
goto exit_drop_index;
}

View 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.190 2005/12/29 23:33:54 drh Exp $
** @(#) $Id: parse.y,v 1.191 2006/01/04 15:54:36 drh Exp $
*/
// All token codes are small integers with #defines that begin with "TK_"
@ -262,7 +262,7 @@ ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);}
ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I).
{sqlite3AddPrimaryKey(pParse,0,R,I,Z);}
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0);}
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);}
ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X);}
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
{sqlite3CreateForeignKey(pParse,0,&T,TA,R);}
@ -312,7 +312,7 @@ tcons ::= CONSTRAINT nm.
tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R).
{sqlite3AddPrimaryKey(pParse,X,R,I,0);}
tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0);}
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);}
tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E);}
tcons ::= FOREIGN KEY LP idxlist(FA) RP
REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). {
@ -836,12 +836,12 @@ expritem(A) ::= . {A = 0;}
///////////////////////////// The CREATE INDEX command ///////////////////////
//
cmd ::= CREATE(S) uniqueflag(U) INDEX nm(X) dbnm(D)
cmd ::= CREATE(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D)
ON nm(Y) LP idxlist(Z) RP(E) onconf(R). {
if( U!=OE_None ) U = R;
if( U==OE_Default) U = OE_Abort;
sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(0,&Y,0), Z, U,
&S, &E, SQLITE_SO_ASC);
&S, &E, SQLITE_SO_ASC, NE);
}
%type uniqueflag {int}
@ -879,7 +879,7 @@ idxitem(A) ::= nm(X). {A = X;}
///////////////////////////// The DROP INDEX command /////////////////////////
//
cmd ::= DROP INDEX fullname(X). {sqlite3DropIndex(pParse, X);}
cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
///////////////////////////// The VACUUM command /////////////////////////////
//

View File

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.11 2005/12/29 19:23:07 drh Exp $
** $Id: prepare.c,v 1.12 2006/01/04 15:54:36 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -433,7 +433,7 @@ int sqlite3_prepare(
sParse.rc = SQLITE_NOMEM;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
if( sParse.rc!=SQLITE_OK && sParse.checkSchema && !schemaIsValid(db) ){
if( sParse.checkSchema && !schemaIsValid(db) ){
sParse.rc = SQLITE_SCHEMA;
}
if( sParse.rc==SQLITE_SCHEMA ){

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.446 2005/12/30 16:28:02 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.447 2006/01/04 15:54:36 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -1516,8 +1516,8 @@ void sqlite3SrcListAssignCursors(Parse*, SrcList*);
void sqlite3IdListDelete(IdList*);
void sqlite3SrcListDelete(SrcList*);
void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
Token*, int);
void sqlite3DropIndex(Parse*, SrcList*);
Token*, int, int);
void sqlite3DropIndex(Parse*, SrcList*, int);
void sqlite3AddKeyType(Vdbe*, ExprList*);
void sqlite3AddIdxKeyType(Vdbe*, Index*);
int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff);

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the CREATE INDEX statement.
#
# $Id: index.test,v 1.39 2005/11/14 22:29:06 drh Exp $
# $Id: index.test,v 1.40 2006/01/04 15:54:37 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -185,6 +185,9 @@ do_test index-6.1 {
do_test index-6.1b {
execsql {SELECT name FROM sqlite_master WHERE type!='meta' ORDER BY name}
} {index1 test1 test2}
do_test index-6.1c {
catchsql {CREATE INDEX IF NOT EXISTS index1 ON test1(f1)}
} {0 {}}
do_test index-6.2 {
set v [catch {execsql {CREATE INDEX test1 ON test2(g1)}} msg]
lappend v $msg
@ -589,6 +592,17 @@ do_test index-17.2 {
DROP INDEX sqlite_autoindex_t7_1;
}
} {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}}
do_test index-17.3 {
catchsql {
DROP INDEX IF EXISTS sqlite_autoindex_t7_1;
}
} {1 {index associated with UNIQUE or PRIMARY KEY constraint cannot be dropped}}
do_test index-17.4 {
catchsql {
DROP INDEX IF EXISTS no_such_index;
}
} {0 {}}
# The following tests ensure that it is not possible to explicitly name
# a schema object with a name beginning with "sqlite_". Granted that is a