-C Autoincrement\scode\sinstalled.\s\sSimple\ssmoke-testing\sonly.\s\sNo\sregression\ntests\sdeveloped\syet.\s(CVS\s2091)
-D 2004-11-12T03:56:15
+C Add\sthe\s"ALTER\sTABLE\sxxx\sRENAME\sTO\syyy"\scommand.\s(CVS\s2092)
+D 2004-11-12T13:42:31
F Makefile.in c4d2416860f472a1e3393714d0372074197565df
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
F src/btree.c 9fd74df65bad768a441afefc3b73174d45b85d5b
F src/btree.h 861e40b759a195ba63819740e484390012cf81ab
-F src/build.c 6d1687c66138af18e210981465ee342fe36985d3
+F src/build.c cbd985e9d0168204fcca3e1123f0b7f621f402e6
F src/date.c 4fd4e90b3880dacd67305e96330940dc243ffc10
F src/delete.c f0af21a1ede15524a5edd59fe10ef486283a1ee9
F src/expr.c 4ee3e47358c92a919062255b14057a7a8f641e01
-F src/func.c 600e506bccf7648df8ad03efb417560d0f7ad4c1
+F src/func.c b68572e79ada56dd038b7e71755212215092b717
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c e80b009f9ef2864bbaaaae836286f56125a180f6
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c ee88fcecb081e3635c281bc09d604e934429e2f5
F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
-F src/parse.y 91a01b5f1170a574b4b9f19871b32bd0f00923a9
+F src/parse.y b64ebeb91d9fc1c813f4517b80e3a3659e94b032
F src/pragma.c bb1c76dae9911b9312997b353c1e316fa603a0c6
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 0fdf2b0cf6f2db12c4abefad0f1085268d911f74
+F src/sqliteInt.h 8569ce94e891a854de71d7bd628da1d25ee6dfe4
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008
F src/test1.c e80e070fe794cdc204ec144ce03bd7b27dab4946
F src/test3.c 6f1ec93e13632a004b527049535079eda84c459d
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
-F src/tokenize.c 4dc14256d80d25da622d506bfe3b817153b97032
+F src/tokenize.c 2ad3d1ae1a0a70746db0b31a0a74f58050a3c39a
F src/trigger.c f9a0a8d3a87238de1a934eeb7d0b6b1f13e6a55b
F src/update.c 3cc67f6053495152e82a6a48c93ed331218e936e
F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed
F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56
F src/where.c 6e637a6b3e61fe3104adc4e5caa4738bf6570daa
F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c
+F test/alter.test faf3440c4170033f5ea38d1343a0d82f4f3f7017
F test/attach.test e305dd59a375e37c658c6d401f19f8a95880bf9a
F test/attach2.test 399128a7b3b209a339a8dbf53ca2ed42eb982d1a
F test/attach3.test 8a0309e284cf9aa1d7d6cc444989031881f7a21c
F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
F tool/memleak3.tcl 336eb50b0849dbf99b1d5462d9c37291b01b2b43
-F tool/mkkeywordhash.c b651bd7f7e0b5efea1f9aea3957d5ca4e2067d56
+F tool/mkkeywordhash.c 27753dd082cb1a7132866a7b73b91a55c6c8f2d4
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/report1.txt 9eae07f26a8fc53889b45fc833a66a33daa22816
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
-P 60fb0cef093b9827ac2d36b8a94e37f4b79dd2ea
-R ab6b6f9534118088586ec8c53a8170c1
-U drh
-Z 72c9d0289de8ee06d1a20ab843f47f3d
+P 8fde833c812b91c5a574208a70b5f92b9d4b0a87
+R 8245e15b31d6598597e65a4dce12b056
+U danielk1977
+Z 014cc6af755028b6df88d60e431d5a3f
-8fde833c812b91c5a574208a70b5f92b9d4b0a87
\ No newline at end of file
+a1b2cc63e604785bd51e358ff72c485d858752e3
\ No newline at end of file
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.276 2004/11/12 03:56:15 drh Exp $
+** $Id: build.c,v 1.277 2004/11/12 13:42:31 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
*/
if( pStart && pEnd ){
/* A named index with an explicit CREATE INDEX statement */
- zStmt = sqlite3MPrintf("CREATE%s INDEX %.*q",
+ zStmt = sqlite3MPrintf("CREATE%s INDEX %.*s",
onError==OE_None ? "" : " UNIQUE",
Addr(pEnd->z) - Addr(pName->z) + 1,
pName->z);
sqlite3ErrorMsg(pParse, "unable to identify the object to be reindexed");
}
#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 */
+ Table *pTab; /* Table being renamed */
+ sqlite3 *db = pParse->db; /* Database connection */
+ char *zName = 0; /* NULL-terminated version of pName */
+ char *zWhere = 0; /* Where clause of schema elements to reparse */
+ Vdbe *v;
+
+ assert( pSrc->nSrc==1 );
+
+ pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ if( !pTab ) return;
+ iDb = pTab->iDb;
+
+ /* Get a NULL terminated version of the new table name. */
+ zName = sqlite3NameFromToken(pName);
+ if( !zName ) return;
+
+ /* 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, db->aDb[iDb].zName) ||
+ sqlite3FindIndex(db, zName, db->aDb[iDb].zName) ){
+ sqlite3ErrorMsg(pParse,
+ "there is already another table or index with this name: %s", zName);
+ sqliteFree(zName);
+ return;
+ }
+
+ /* 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 ) return;
+ 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 "
+ "sql = sqlite_alter_table(sql, %Q), "
+ "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 IN ('table', 'index');",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb), zName, zName, zName,
+ zName, strlen(pTab->zName), pTab->zName
+ );
+
+ /* 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 ){
+ sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+ zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
+ sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
+ }
+
+ sqliteFree(zName);
+}
+#endif
+
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
-** $Id: func.c,v 1.85 2004/10/06 15:41:17 drh Exp $
+** $Id: func.c,v 1.86 2004/11/12 13:42:31 danielk1977 Exp $
*/
#include <ctype.h>
#include <math.h>
sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
}
+#ifndef SQLITE_OMIT_ALTERTABLE
+/*
+** This function is used by SQL generated to implement the
+** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
+** CREATE INDEX command. The second is a table name. The table name in
+** the CREATE TABLE or CREATE INDEX statement is replaced with the second
+** argument and the result returned. Examples:
+**
+** sqlite_alter_table('CREATE TABLE abc(a, b, c)', 'def')
+** -> 'CREATE TABLE def(a, b, c)'
+**
+** sqlite_alter_table('CREATE INDEX i ON abc(a)', 'def')
+** -> 'CREATE INDEX i ON def(a, b, c)'
+*/
+static void altertableFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ char const *zSql = sqlite3_value_text(argv[0]);
+ char const *zTableName = sqlite3_value_text(argv[1]);
+
+ char const *zCsr = zSql;
+ char const *zPrev;
+ char *zRet = 0;
+ int tokenType = 0;
+ int len;
+
+ assert( argc==2 );
+ if( zSql ){
+ while( tokenType!=TK_LP ){
+ zPrev = zCsr-len;
+ len = sqlite3GetToken(zCsr, &tokenType);
+ zCsr += len;
+ }
+
+ zRet = sqlite3MPrintf("%.*s%Q(%s", zPrev-zSql, zSql, zTableName, zCsr);
+ sqlite3_result_text(context, zRet, -1, SQLITE_TRANSIENT);
+ sqliteFree(zRet);
+ }
+}
+#endif
+
/*
** EXPERIMENTAL - This is not an official function. The interface may
** change. This function may disappear. Do not write code that depends
{ "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid },
{ "changes", 0, 1, SQLITE_UTF8, 0, changes },
{ "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes },
+#ifndef SQLITE_OMIT_ALTERTABLE
+ { "sqlite_alter_table", 2, 0, SQLITE_UTF8, 0, altertableFunc},
+#endif
#ifdef SQLITE_SOUNDEX
{ "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc},
#endif
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.153 2004/11/12 03:56:15 drh Exp $
+** @(#) $Id: parse.y,v 1.154 2004/11/12 13:42:31 danielk1977 Exp $
*/
%token_prefix TK_
%token_type {Token}
cmd ::= REINDEX. {sqlite3Reindex(pParse, 0, 0);}
cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);}
%endif
+
+//////////////////////// ALTER TABLE table ... ////////////////////////////////
+%ifndef SQLITE_OMIT_ALTERTABLE
+cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
+ sqlite3AlterRenameTable(pParse,X,&Z);
+}
+%endif
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.338 2004/11/12 03:56:15 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.339 2004/11/12 13:42:31 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
/* #define SQLITE_OMIT_DATETIME_FUNCS 1 */
/* #define SQLITE_OMIT_PROGRESS_CALLBACK 1 */
/* #define SQLITE_OMIT_AUTOVACUUM */
+/* #define SQLITE_OMIT_ALTERTABLE */
/*
** GCC does not define the offsetof() macro so we'll have to do it
extern const unsigned char sqlite3UpperToLower[];
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
+void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
+int sqlite3GetToken(const unsigned char *, int *);
void sqlite3NestedParse(Parse*, const char*, ...);
#endif
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.96 2004/11/12 03:56:15 drh Exp $
+** $Id: tokenize.c,v 1.97 2004/11/12 13:42:31 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
** Return the length of the token that begins at z[0].
** Store the token type in *tokenType before returning.
*/
-static int sqliteGetToken(const unsigned char *z, int *tokenType){
+int sqlite3GetToken(const unsigned char *z, int *tokenType){
int i, c;
switch( *z ){
case ' ': case '\t': case '\n': case '\f': case '\r': {
assert( i>=0 );
pParse->sLastToken.z = &zSql[i];
assert( pParse->sLastToken.dyn==0 );
- pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType);
+ pParse->sLastToken.n = sqlite3GetToken((unsigned char*)&zSql[i],&tokenType);
i += pParse->sLastToken.n;
switch( tokenType ){
case TK_SPACE:
--- /dev/null
+#
+# The author or author's hereby grant to the public domain a non-exclusive,
+# fully paid-up, perpetual, license in the software and all related
+# intellectual property to make, have made, use, have used, reproduce,
+# prepare derivative works, distribute, perform and display the work.
+#
+#*************************************************************************
+# This file implements regression tests for SQLite library. The
+# focus of this script is testing the ALTER TABLE statement.
+#
+# $Id: alter.test,v 1.1 2004/11/12 13:42:32 danielk1977 Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+
+# Create some tables to rename. Be sure to include some TEMP tables
+# and some tables with odd names.
+#
+do_test alter-1.1 {
+ execsql {
+ CREATE TABLE t1(a,b);
+ INSERT INTO t1 VALUES(1,2);
+ CREATE TABLE [t1'x1](c UNIQUE, b PRIMARY KEY);
+ INSERT INTO [t1'x1] VALUES(3,4);
+ CREATE INDEX t1i1 ON T1(B);
+ CREATE INDEX t1i2 ON t1(a,b);
+ CREATE INDEX i3 ON [t1'x1](b,c);
+ CREATE TEMP TABLE "temp table"(e,f,g UNIQUE);
+ CREATE INDEX i2 ON [temp table](f);
+ INSERT INTO [temp table] VALUES(5,6,7);
+ }
+ execsql {
+ SELECT 't1', * FROM t1
+ UNION ALL
+ SELECT 't1''x1', * FROM "t1'x1"
+ UNION ALL
+ SELECT * FROM [temp table]
+ }
+} {t1 1 2 t1'x1 3 4 5 6 7}
+do_test alter-1.2 {
+ execsql {
+ SELECT type, name, tbl_name FROM sqlite_master
+ UNION ALL
+ SELECT type, name, tbl_name FROM sqlite_temp_master
+ ORDER BY tbl_name, type desc, name
+ }
+} [list \
+ table t1 t1 \
+ index t1i1 t1 \
+ index t1i2 t1 \
+ table t1'x1 t1'x1 \
+ index i3 t1'x1 \
+ index {sqlite_autoindex_t1'x1_1} t1'x1 \
+ index {sqlite_autoindex_t1'x1_2} t1'x1 \
+ table {temp table} {temp table} \
+ index i2 {temp table} \
+ index {sqlite_autoindex_temp table_1} {temp table} \
+ ]
+
+# Make some changes
+#
+do_test alter-1.3 {
+ execsql {
+ ALTER TABLE [T1] RENAME to [-t1-];
+ ALTER TABLE "t1'x1" RENAME TO T2;
+ ALTER TABLE [temp table] RENAME to TempTab;
+ }
+} {}
+integrity_check alter-1.3.1
+do_test alter-1.4 {
+ execsql {
+ SELECT 't1', * FROM [-t1-]
+ UNION ALL
+ SELECT 't2', * FROM t2
+ UNION ALL
+ SELECT * FROM temptab
+ }
+} {t1 1 2 t2 3 4 5 6 7}
+do_test alter-1.5 {
+ execsql {
+ SELECT type, name, tbl_name FROM sqlite_master
+ UNION ALL
+ SELECT type, name, tbl_name FROM sqlite_temp_master
+ ORDER BY tbl_name, type desc, name
+ }
+} [list \
+ table -t1- -t1- \
+ index t1i1 -t1- \
+ index t1i2 -t1- \
+ table T2 T2 \
+ index i3 T2 \
+ index {sqlite_autoindex_T2_1} T2 \
+ index {sqlite_autoindex_T2_2} T2 \
+ table {TempTab} {TempTab} \
+ index i2 {TempTab} \
+ index {sqlite_autoindex_TempTab_1} {TempTab} \
+ ]
+
+# Make sure the changes persist after restarting the database.
+# (The TEMP table will not persist, of course.)
+#
+do_test alter-1.6 {
+ db close
+ set DB [sqlite3 db test.db]
+ execsql {
+ SELECT type, name, tbl_name FROM sqlite_master
+ UNION ALL
+ SELECT type, name, tbl_name FROM sqlite_temp_master
+ ORDER BY tbl_name, type desc, name
+ }
+} [list \
+ table -t1- -t1- \
+ index t1i1 -t1- \
+ index t1i2 -t1- \
+ table T2 T2 \
+ index i3 T2 \
+ index {sqlite_autoindex_T2_1} T2 \
+ index {sqlite_autoindex_T2_2} T2 \
+ ]
+
+# Make sure the ALTER TABLE statements work with the
+# non-callback API
+#
+do_test alter-1.7 {
+ stepsql $DB {
+ ALTER TABLE [-t1-] RENAME to [*t1*];
+ ALTER TABLE T2 RENAME TO [<t2>];
+ }
+ execsql {
+ SELECT type, name, tbl_name FROM sqlite_master
+ UNION ALL
+ SELECT type, name, tbl_name FROM sqlite_temp_master
+ ORDER BY tbl_name, type desc, name
+ }
+} [list \
+ table *t1* *t1* \
+ index t1i1 *t1* \
+ index t1i2 *t1* \
+ table <t2> <t2> \
+ index i3 <t2> \
+ index {sqlite_autoindex_<t2>_1} <t2> \
+ index {sqlite_autoindex_<t2>_2} <t2> \
+ ]
+
+
+# Test error messages
+#
+do_test alter-2.1 {
+ catchsql {
+ ALTER TABLE none RENAME TO hi;
+ }
+} {1 {no such table: none}}
+do_test alter-2.2 {
+ execsql {
+ CREATE TABLE t3(p,q,r);
+ }
+ catchsql {
+ ALTER TABLE [<t2>] RENAME TO t3;
+ }
+} {1 {there is already another table or index with this name: t3}}
+do_test alter-2.3 {
+ catchsql {
+ ALTER TABLE [<t2>] RENAME TO i3;
+ }
+} {1 {there is already another table or index with this name: i3}}
+
+
+
+finish_test
{ "TEMP", "TK_TEMP", ALWAYS },
{ "TEMPORARY", "TK_TEMP", ALWAYS },
{ "THEN", "TK_THEN", ALWAYS },
+ { "TO", "TK_TO", ALWAYS },
{ "TRANSACTION", "TK_TRANSACTION", ALWAYS },
{ "TRIGGER", "TK_TRIGGER", TRIGGER },
{ "UNION", "TK_UNION", COMPOUND },