mirror of
https://github.com/sqlite/sqlite.git
synced 2025-10-25 20:58:26 +03:00
Split the logic for the ALTER TABLE command off into a separate source
code file. (CVS 2342) FossilOrigin-Name: 90d6573c2631fac92b9e572e9e21698ae2480c9d
This commit is contained in:
@@ -112,7 +112,7 @@ TCC += -DSQLITE_OMIT_CURSOR
|
|||||||
|
|
||||||
# Object files for the SQLite library.
|
# Object files for the SQLite library.
|
||||||
#
|
#
|
||||||
LIBOBJ = attach.lo auth.lo btree.lo build.lo date.lo \
|
LIBOBJ = alter.lo attach.lo auth.lo btree.lo build.lo date.lo \
|
||||||
delete.lo expr.lo func.lo hash.lo insert.lo \
|
delete.lo expr.lo func.lo hash.lo insert.lo \
|
||||||
main.lo opcodes.lo os_unix.lo os_win.lo \
|
main.lo opcodes.lo os_unix.lo os_win.lo \
|
||||||
pager.lo parse.lo pragma.lo printf.lo random.lo \
|
pager.lo parse.lo pragma.lo printf.lo random.lo \
|
||||||
@@ -123,6 +123,7 @@ LIBOBJ = attach.lo auth.lo btree.lo build.lo date.lo \
|
|||||||
# All of the source code files.
|
# All of the source code files.
|
||||||
#
|
#
|
||||||
SRC = \
|
SRC = \
|
||||||
|
$(TOP)/src/alter.c \
|
||||||
$(TOP)/src/attach.c \
|
$(TOP)/src/attach.c \
|
||||||
$(TOP)/src/auth.c \
|
$(TOP)/src/auth.c \
|
||||||
$(TOP)/src/btree.c \
|
$(TOP)/src/btree.c \
|
||||||
@@ -260,6 +261,9 @@ lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
|||||||
|
|
||||||
# Rules to build individual files
|
# Rules to build individual files
|
||||||
#
|
#
|
||||||
|
alter.lo: $(TOP)/src/alter.c $(HDR)
|
||||||
|
$(LTCOMPILE) -c $(TOP)/src/alter.c
|
||||||
|
|
||||||
attach.lo: $(TOP)/src/attach.c $(HDR)
|
attach.lo: $(TOP)/src/attach.c $(HDR)
|
||||||
$(LTCOMPILE) -c $(TOP)/src/attach.c
|
$(LTCOMPILE) -c $(TOP)/src/attach.c
|
||||||
|
|
||||||
|
|||||||
6
main.mk
6
main.mk
@@ -54,7 +54,7 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
|
|||||||
|
|
||||||
# Object files for the SQLite library.
|
# Object files for the SQLite library.
|
||||||
#
|
#
|
||||||
LIBOBJ+= attach.o auth.o btree.o build.o date.o delete.o \
|
LIBOBJ+= alter.o attach.o auth.o btree.o build.o date.o delete.o \
|
||||||
expr.o func.o hash.o insert.o \
|
expr.o func.o hash.o insert.o \
|
||||||
main.o opcodes.o os_unix.o os_win.o \
|
main.o opcodes.o os_unix.o os_win.o \
|
||||||
pager.o parse.o pragma.o printf.o random.o \
|
pager.o parse.o pragma.o printf.o random.o \
|
||||||
@@ -66,6 +66,7 @@ LIBOBJ+= attach.o auth.o btree.o build.o date.o delete.o \
|
|||||||
# All of the source code files.
|
# All of the source code files.
|
||||||
#
|
#
|
||||||
SRC = \
|
SRC = \
|
||||||
|
$(TOP)/src/alter.c \
|
||||||
$(TOP)/src/attach.c \
|
$(TOP)/src/attach.c \
|
||||||
$(TOP)/src/auth.c \
|
$(TOP)/src/auth.c \
|
||||||
$(TOP)/src/btree.c \
|
$(TOP)/src/btree.c \
|
||||||
@@ -195,6 +196,9 @@ lemon: $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
|
|||||||
|
|
||||||
# Rules to build individual files
|
# Rules to build individual files
|
||||||
#
|
#
|
||||||
|
alter.o: $(TOP)/src/alter.c $(HDR)
|
||||||
|
$(TCCX) -c $(TOP)/src/alter.c
|
||||||
|
|
||||||
attach.o: $(TOP)/src/attach.c $(HDR)
|
attach.o: $(TOP)/src/attach.c $(HDR)
|
||||||
$(TCCX) -c $(TOP)/src/attach.c
|
$(TCCX) -c $(TOP)/src/attach.c
|
||||||
|
|
||||||
|
|||||||
19
manifest
19
manifest
@@ -1,6 +1,6 @@
|
|||||||
C Btree\schecks\sthe\sautovacuum\sflag\safter\slocking\sthe\sdatabase\sfile.\s(CVS\s2341)
|
C Split\sthe\slogic\sfor\sthe\sALTER\sTABLE\scommand\soff\sinto\sa\sseparate\ssource\ncode\sfile.\s(CVS\s2342)
|
||||||
D 2005-02-15T16:23:02
|
D 2005-02-15T20:47:57
|
||||||
F Makefile.in d928187101fa3d78426cf48ca30e39d0fb714e57
|
F Makefile.in 76443a83549d1539105e12d13bd0054a05ab2214
|
||||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||||
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
||||||
F VERSION 9e556d0985199b130268c3b8e5615b90dda7e829
|
F VERSION 9e556d0985199b130268c3b8e5615b90dda7e829
|
||||||
@@ -16,7 +16,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
|
|||||||
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
|
||||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||||
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
|
||||||
F main.mk 834d5f2feb8d0f79fb3d2bb9db5afac2b3da7349
|
F main.mk 632150f494ae1a96c8ac3cda0229a77cd18cb843
|
||||||
F mkdll.sh 468d4f41d3ea98221371df4825cfbffbaac4d7e4
|
F mkdll.sh 468d4f41d3ea98221371df4825cfbffbaac4d7e4
|
||||||
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
|
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
|
||||||
F mkopcodeh.awk e4d010870a3e98fd4323635c31565a3ca8584741
|
F mkopcodeh.awk e4d010870a3e98fd4323635c31565a3ca8584741
|
||||||
@@ -27,16 +27,17 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
|||||||
F sqlite3.1 01fdb467ce387a83248857c92f9e801df9e4611c
|
F sqlite3.1 01fdb467ce387a83248857c92f9e801df9e4611c
|
||||||
F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863
|
F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863
|
||||||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||||
|
F src/alter.c 4e38440d4491a52b55c0c42d5c9b1b1890f0a13d
|
||||||
F src/attach.c f78f76bc6a8e5e487ca53636e21ccba2484a9a61
|
F src/attach.c f78f76bc6a8e5e487ca53636e21ccba2484a9a61
|
||||||
F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f
|
F src/auth.c 18c5a0befe20f3a58a41e3ddd78f372faeeefe1f
|
||||||
F src/btree.c 5c6e81855deec3d1eac5ae03e4c8db6c2595421f
|
F src/btree.c 5c6e81855deec3d1eac5ae03e4c8db6c2595421f
|
||||||
F src/btree.h 2e2cc923224649337d7217df0dd32b06673ca180
|
F src/btree.h 2e2cc923224649337d7217df0dd32b06673ca180
|
||||||
F src/build.c 09333b6006d26d411dbaa918601be1054c09fff3
|
F src/build.c 7db7f593093caeb223c849a0fd7ca428dcda631e
|
||||||
F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f
|
F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f
|
||||||
F src/delete.c 4b94395b52a8f7785acd71135c2ce54f3f5550b3
|
F src/delete.c 4b94395b52a8f7785acd71135c2ce54f3f5550b3
|
||||||
F src/experimental.c 8cc66b2be6a011055d75ef19ed2584bcfbb585ad
|
F src/experimental.c 8cc66b2be6a011055d75ef19ed2584bcfbb585ad
|
||||||
F src/expr.c e160aabb59ff3c02e8e00ca4b30d00b94664c519
|
F src/expr.c e160aabb59ff3c02e8e00ca4b30d00b94664c519
|
||||||
F src/func.c 4538f82c8ae5f753012f15c4f22cffd578280c56
|
F src/func.c deba954e40c9bcfaafa899f382176f2c1eb8b1d6
|
||||||
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
|
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
|
||||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||||
F src/insert.c 0456649d4d48396f918e7ea1fecbf3d66ed90816
|
F src/insert.c 0456649d4d48396f918e7ea1fecbf3d66ed90816
|
||||||
@@ -271,7 +272,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
|
|||||||
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
|
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
|
||||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
||||||
F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd
|
F www/whentouse.tcl 3e522a06ad41992023c80ca29a048ae2331ca5bd
|
||||||
P 138577d0a5c41f3de4f9adc9ab6e312a65ff8888
|
P 6610188f09d08c65c46a140685b403aa74f71a19
|
||||||
R f81718102e4042ffed922f8685264bda
|
R d76aba4c3459eff26416d9c4987a204d
|
||||||
U drh
|
U drh
|
||||||
Z ba532001e1e18d6f4d6553ba708c367b
|
Z ecefb64241ae1525534fd4f0e437a46d
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
6610188f09d08c65c46a140685b403aa74f71a19
|
90d6573c2631fac92b9e572e9e21698ae2480c9d
|
||||||
186
src/alter.c
Normal file
186
src/alter.c
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
** 2005 February 15
|
||||||
|
**
|
||||||
|
** 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 contains C code routines that used to generate VDBE code
|
||||||
|
** that implements the ALTER TABLE command.
|
||||||
|
**
|
||||||
|
** $Id: alter.c,v 1.1 2005/02/15 20:47:57 drh Exp $
|
||||||
|
*/
|
||||||
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||||
|
/*
|
||||||
|
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
|
||||||
|
** command.
|
||||||
|
*/
|
||||||
|
void sqlite3AlterRenameTable(
|
||||||
|
Parse *pParse, /* Parser context. */
|
||||||
|
SrcList *pSrc, /* The table to rename. */
|
||||||
|
Token *pName /* The new table name. */
|
||||||
|
){
|
||||||
|
int iDb; /* Database that contains the table */
|
||||||
|
char *zDb; /* Name of database iDb */
|
||||||
|
Table *pTab; /* Table being renamed */
|
||||||
|
char *zName = 0; /* NULL-terminated version of pName */
|
||||||
|
char *zWhere = 0; /* Where clause of schema elements to reparse */
|
||||||
|
sqlite3 *db = pParse->db; /* Database connection */
|
||||||
|
Vdbe *v;
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
char *zTempTrig = 0; /* Where clause to locate temp triggers */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert( pSrc->nSrc==1 );
|
||||||
|
|
||||||
|
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
|
||||||
|
if( !pTab ) goto exit_rename_table;
|
||||||
|
iDb = pTab->iDb;
|
||||||
|
zDb = db->aDb[iDb].zName;
|
||||||
|
|
||||||
|
/* Get a NULL terminated version of the new table name. */
|
||||||
|
zName = sqlite3NameFromToken(pName);
|
||||||
|
if( !zName ) goto exit_rename_table;
|
||||||
|
|
||||||
|
/* Check that a table or index named 'zName' does not already exist
|
||||||
|
** in database iDb. If so, this is an error.
|
||||||
|
*/
|
||||||
|
if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
|
||||||
|
sqlite3ErrorMsg(pParse,
|
||||||
|
"there is already another table or index with this name: %s", zName);
|
||||||
|
goto exit_rename_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure it is not a system table being altered, or a reserved name
|
||||||
|
** that the table is being renamed to.
|
||||||
|
*/
|
||||||
|
if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
|
||||||
|
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
|
||||||
|
goto exit_rename_table;
|
||||||
|
}
|
||||||
|
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
||||||
|
goto exit_rename_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||||
|
/* Invoke the authorization callback. */
|
||||||
|
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
|
||||||
|
goto exit_rename_table;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Begin a transaction and code the VerifyCookie for database iDb.
|
||||||
|
** Then modify the schema cookie (since the ALTER TABLE modifies the
|
||||||
|
** schema).
|
||||||
|
*/
|
||||||
|
v = sqlite3GetVdbe(pParse);
|
||||||
|
if( v==0 ){
|
||||||
|
goto exit_rename_table;
|
||||||
|
}
|
||||||
|
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||||
|
sqlite3ChangeCookie(db, v, iDb);
|
||||||
|
|
||||||
|
/* Modify the sqlite_master table to use the new table name. */
|
||||||
|
sqlite3NestedParse(pParse,
|
||||||
|
"UPDATE %Q.%s SET "
|
||||||
|
#ifdef SQLITE_OMIT_TRIGGER
|
||||||
|
"sql = sqlite_rename_table(sql, %Q), "
|
||||||
|
#else
|
||||||
|
"sql = CASE "
|
||||||
|
"WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
|
||||||
|
"ELSE sqlite_rename_table(sql, %Q) END, "
|
||||||
|
#endif
|
||||||
|
"tbl_name = %Q, "
|
||||||
|
"name = CASE "
|
||||||
|
"WHEN type='table' THEN %Q "
|
||||||
|
"WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
|
||||||
|
"'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
|
||||||
|
"ELSE name END "
|
||||||
|
"WHERE tbl_name=%Q AND "
|
||||||
|
"(type='table' OR type='index' OR type='trigger');",
|
||||||
|
zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
zName,
|
||||||
|
#endif
|
||||||
|
zName, strlen(pTab->zName), pTab->zName
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
||||||
|
/* If the sqlite_sequence table exists in this database, then update
|
||||||
|
** it with the new table name.
|
||||||
|
*/
|
||||||
|
if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
|
||||||
|
sqlite3NestedParse(pParse,
|
||||||
|
"UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
|
||||||
|
zDb, zName, pTab->zName);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
/* If there are TEMP triggers on this table, modify the sqlite_temp_master
|
||||||
|
** table. Don't do this if the table being ALTERed is itself located in
|
||||||
|
** the temp database.
|
||||||
|
*/
|
||||||
|
if( iDb!=1 ){
|
||||||
|
Trigger *pTrig;
|
||||||
|
char *tmp = 0;
|
||||||
|
for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
|
||||||
|
if( pTrig->iDb==1 ){
|
||||||
|
if( !zTempTrig ){
|
||||||
|
zTempTrig =
|
||||||
|
sqlite3MPrintf("type = 'trigger' AND (name=%Q", pTrig->name);
|
||||||
|
}else{
|
||||||
|
tmp = zTempTrig;
|
||||||
|
zTempTrig = sqlite3MPrintf("%s OR name=%Q", zTempTrig, pTrig->name);
|
||||||
|
sqliteFree(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( zTempTrig ){
|
||||||
|
tmp = zTempTrig;
|
||||||
|
zTempTrig = sqlite3MPrintf("%s)", zTempTrig);
|
||||||
|
sqliteFree(tmp);
|
||||||
|
sqlite3NestedParse(pParse,
|
||||||
|
"UPDATE sqlite_temp_master SET "
|
||||||
|
"sql = sqlite_rename_trigger(sql, %Q), "
|
||||||
|
"tbl_name = %Q "
|
||||||
|
"WHERE %s;", zName, zName, zTempTrig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Drop the elements of the in-memory schema that refered to the table
|
||||||
|
** renamed and load the new versions from the database.
|
||||||
|
*/
|
||||||
|
if( pParse->nErr==0 ){
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
Trigger *pTrig;
|
||||||
|
for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
|
||||||
|
assert( pTrig->iDb==iDb || pTrig->iDb==1 );
|
||||||
|
sqlite3VdbeOp3(v, OP_DropTrigger, pTrig->iDb, 0, pTrig->name, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
|
||||||
|
zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
|
||||||
|
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
|
||||||
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
|
if( zTempTrig ){
|
||||||
|
sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zTempTrig, P3_DYNAMIC);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
sqliteFree(zTempTrig);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_rename_table:
|
||||||
|
sqlite3SrcListDelete(pSrc);
|
||||||
|
sqliteFree(zName);
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_ALTER_TABLE */
|
||||||
170
src/build.c
170
src/build.c
@@ -22,7 +22,7 @@
|
|||||||
** COMMIT
|
** COMMIT
|
||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.310 2005/02/14 20:48:20 drh Exp $
|
** $Id: build.c,v 1.311 2005/02/15 20:47:57 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -3003,171 +3003,3 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
|
|||||||
sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
|
sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
|
||||||
/*
|
|
||||||
** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
|
|
||||||
** command.
|
|
||||||
*/
|
|
||||||
void sqlite3AlterRenameTable(
|
|
||||||
Parse *pParse, /* Parser context. */
|
|
||||||
SrcList *pSrc, /* The table to rename. */
|
|
||||||
Token *pName /* The new table name. */
|
|
||||||
){
|
|
||||||
int iDb; /* Database that contains the table */
|
|
||||||
char *zDb; /* Name of database iDb */
|
|
||||||
Table *pTab; /* Table being renamed */
|
|
||||||
char *zName = 0; /* NULL-terminated version of pName */
|
|
||||||
char *zWhere = 0; /* Where clause of schema elements to reparse */
|
|
||||||
sqlite3 *db = pParse->db; /* Database connection */
|
|
||||||
Vdbe *v;
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
|
||||||
char *zTempTrig = 0; /* Where clause to locate temp triggers */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
assert( pSrc->nSrc==1 );
|
|
||||||
|
|
||||||
pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
|
|
||||||
if( !pTab ) goto exit_alter_table;
|
|
||||||
iDb = pTab->iDb;
|
|
||||||
zDb = db->aDb[iDb].zName;
|
|
||||||
|
|
||||||
/* Get a NULL terminated version of the new table name. */
|
|
||||||
zName = sqlite3NameFromToken(pName);
|
|
||||||
if( !zName ) goto exit_alter_table;
|
|
||||||
|
|
||||||
/* Check that a table or index named 'zName' does not already exist
|
|
||||||
** in database iDb. If so, this is an error.
|
|
||||||
*/
|
|
||||||
if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
|
|
||||||
sqlite3ErrorMsg(pParse,
|
|
||||||
"there is already another table or index with this name: %s", zName);
|
|
||||||
goto exit_alter_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure it is not a system table being altered, or a reserved name
|
|
||||||
** that the table is being renamed to.
|
|
||||||
*/
|
|
||||||
if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
|
|
||||||
sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
|
|
||||||
goto exit_alter_table;
|
|
||||||
}
|
|
||||||
if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
|
||||||
goto exit_alter_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
||||||
/* Invoke the authorization callback. */
|
|
||||||
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
|
|
||||||
goto exit_alter_table;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Begin a transaction and code the VerifyCookie for database iDb.
|
|
||||||
** Then modify the schema cookie (since the ALTER TABLE modifies the
|
|
||||||
** schema).
|
|
||||||
*/
|
|
||||||
v = sqlite3GetVdbe(pParse);
|
|
||||||
if( v==0 ){
|
|
||||||
goto exit_alter_table;
|
|
||||||
}
|
|
||||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
|
||||||
sqlite3ChangeCookie(db, v, iDb);
|
|
||||||
|
|
||||||
/* Modify the sqlite_master table to use the new table name. */
|
|
||||||
sqlite3NestedParse(pParse,
|
|
||||||
"UPDATE %Q.%s SET "
|
|
||||||
#ifdef SQLITE_OMIT_TRIGGER
|
|
||||||
"sql = sqlite_alter_table(sql, %Q), "
|
|
||||||
#else
|
|
||||||
"sql = CASE "
|
|
||||||
"WHEN type = 'trigger' THEN sqlite_alter_trigger(sql, %Q)"
|
|
||||||
"ELSE sqlite_alter_table(sql, %Q) END, "
|
|
||||||
#endif
|
|
||||||
"tbl_name = %Q, "
|
|
||||||
"name = CASE "
|
|
||||||
"WHEN type='table' THEN %Q "
|
|
||||||
"WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
|
|
||||||
"'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
|
|
||||||
"ELSE name END "
|
|
||||||
"WHERE tbl_name=%Q AND "
|
|
||||||
"(type='table' OR type='index' OR type='trigger');",
|
|
||||||
zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
|
||||||
zName,
|
|
||||||
#endif
|
|
||||||
zName, strlen(pTab->zName), pTab->zName
|
|
||||||
);
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
|
||||||
/* If the sqlite_sequence table exists in this database, then update
|
|
||||||
** it with the new table name.
|
|
||||||
*/
|
|
||||||
if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
|
|
||||||
sqlite3NestedParse(pParse,
|
|
||||||
"UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
|
|
||||||
zDb, zName, pTab->zName);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
|
||||||
/* If there are TEMP triggers on this table, modify the sqlite_temp_master
|
|
||||||
** table. Don't do this if the table being ALTERed is itself located in
|
|
||||||
** the temp database.
|
|
||||||
*/
|
|
||||||
if( iDb!=1 ){
|
|
||||||
Trigger *pTrig;
|
|
||||||
char *tmp = 0;
|
|
||||||
for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
|
|
||||||
if( pTrig->iDb==1 ){
|
|
||||||
if( !zTempTrig ){
|
|
||||||
zTempTrig =
|
|
||||||
sqlite3MPrintf("type = 'trigger' AND (name=%Q", pTrig->name);
|
|
||||||
}else{
|
|
||||||
tmp = zTempTrig;
|
|
||||||
zTempTrig = sqlite3MPrintf("%s OR name=%Q", zTempTrig, pTrig->name);
|
|
||||||
sqliteFree(tmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if( zTempTrig ){
|
|
||||||
tmp = zTempTrig;
|
|
||||||
zTempTrig = sqlite3MPrintf("%s)", zTempTrig);
|
|
||||||
sqliteFree(tmp);
|
|
||||||
sqlite3NestedParse(pParse,
|
|
||||||
"UPDATE sqlite_temp_master SET "
|
|
||||||
"sql = sqlite_alter_trigger(sql, %Q), "
|
|
||||||
"tbl_name = %Q "
|
|
||||||
"WHERE %s;", zName, zName, zTempTrig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Drop the elements of the in-memory schema that refered to the table
|
|
||||||
** renamed and load the new versions from the database.
|
|
||||||
*/
|
|
||||||
if( pParse->nErr==0 ){
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
|
||||||
Trigger *pTrig;
|
|
||||||
for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
|
|
||||||
assert( pTrig->iDb==iDb || pTrig->iDb==1 );
|
|
||||||
sqlite3VdbeOp3(v, OP_DropTrigger, pTrig->iDb, 0, pTrig->name, 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
|
|
||||||
zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
|
|
||||||
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
|
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
|
||||||
if( zTempTrig ){
|
|
||||||
sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zTempTrig, P3_DYNAMIC);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
sqliteFree(zTempTrig);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_alter_table:
|
|
||||||
sqlite3SrcListDelete(pSrc);
|
|
||||||
sqliteFree(zName);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
16
src/func.c
16
src/func.c
@@ -16,7 +16,7 @@
|
|||||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||||
** All other code has file scope.
|
** All other code has file scope.
|
||||||
**
|
**
|
||||||
** $Id: func.c,v 1.94 2005/02/09 01:40:25 danielk1977 Exp $
|
** $Id: func.c,v 1.95 2005/02/15 20:47:57 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -541,13 +541,13 @@ static void versionFunc(
|
|||||||
** the CREATE TABLE or CREATE INDEX statement is replaced with the second
|
** the CREATE TABLE or CREATE INDEX statement is replaced with the second
|
||||||
** argument and the result returned. Examples:
|
** argument and the result returned. Examples:
|
||||||
**
|
**
|
||||||
** sqlite_alter_table('CREATE TABLE abc(a, b, c)', 'def')
|
** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
|
||||||
** -> 'CREATE TABLE def(a, b, c)'
|
** -> 'CREATE TABLE def(a, b, c)'
|
||||||
**
|
**
|
||||||
** sqlite_alter_table('CREATE INDEX i ON abc(a)', 'def')
|
** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
|
||||||
** -> 'CREATE INDEX i ON def(a, b, c)'
|
** -> 'CREATE INDEX i ON def(a, b, c)'
|
||||||
*/
|
*/
|
||||||
static void altertableFunc(
|
static void renameTableFunc(
|
||||||
sqlite3_context *context,
|
sqlite3_context *context,
|
||||||
int argc,
|
int argc,
|
||||||
sqlite3_value **argv
|
sqlite3_value **argv
|
||||||
@@ -594,10 +594,10 @@ static void altertableFunc(
|
|||||||
** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
|
** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
|
||||||
** statement. The second is a table name. The table name in the CREATE
|
** statement. The second is a table name. The table name in the CREATE
|
||||||
** TRIGGER statement is replaced with the second argument and the result
|
** TRIGGER statement is replaced with the second argument and the result
|
||||||
** returned. This is analagous to altertableFunc() above, except for CREATE
|
** returned. This is analagous to renameTableFunc() above, except for CREATE
|
||||||
** TRIGGER, not CREATE INDEX and CREATE TABLE.
|
** TRIGGER, not CREATE INDEX and CREATE TABLE.
|
||||||
*/
|
*/
|
||||||
static void altertriggerFunc(
|
static void renameTriggerFunc(
|
||||||
sqlite3_context *context,
|
sqlite3_context *context,
|
||||||
int argc,
|
int argc,
|
||||||
sqlite3_value **argv
|
sqlite3_value **argv
|
||||||
@@ -1123,9 +1123,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
|||||||
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
|
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
|
||||||
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
|
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
|
||||||
#ifndef SQLITE_OMIT_ALTERTABLE
|
#ifndef SQLITE_OMIT_ALTERTABLE
|
||||||
{ "sqlite_alter_table", 2, 0, SQLITE_UTF8, 0, altertableFunc},
|
{ "sqlite_rename_table", 2, 0, SQLITE_UTF8, 0, renameTableFunc},
|
||||||
#ifndef SQLITE_OMIT_TRIGGER
|
#ifndef SQLITE_OMIT_TRIGGER
|
||||||
{ "sqlite_alter_trigger", 2, 0, SQLITE_UTF8, 0, altertriggerFunc},
|
{ "sqlite_rename_trigger",2, 0, SQLITE_UTF8, 0, renameTriggerFunc},
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef SQLITE_SOUNDEX
|
#ifdef SQLITE_SOUNDEX
|
||||||
|
|||||||
Reference in New Issue
Block a user