aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanielk1977 <danielk1977@noemail.net>2004-11-12 13:42:30 +0000
committerdanielk1977 <danielk1977@noemail.net>2004-11-12 13:42:30 +0000
commit9fd2a9a02854aa0cce1c57491d0935d14172cb36 (patch)
tree110c52475d179b88f8fdf7944c8d720facb9069d /src
parent2958a4e6a550b306c3958cbe0e7a8aa5f011718d (diff)
downloadsqlite-9fd2a9a02854aa0cce1c57491d0935d14172cb36.tar.gz
sqlite-9fd2a9a02854aa0cce1c57491d0935d14172cb36.zip
Add the "ALTER TABLE xxx RENAME TO yyy" command. (CVS 2092)
FossilOrigin-Name: a1b2cc63e604785bd51e358ff72c485d858752e3
Diffstat (limited to 'src')
-rw-r--r--src/build.c80
-rw-r--r--src/func.c48
-rw-r--r--src/parse.y9
-rw-r--r--src/sqliteInt.h5
-rw-r--r--src/tokenize.c6
5 files changed, 140 insertions, 8 deletions
diff --git a/src/build.c b/src/build.c
index ead40ec42..ab3877dab 100644
--- a/src/build.c
+++ b/src/build.c
@@ -22,7 +22,7 @@
** 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>
@@ -2359,7 +2359,7 @@ void sqlite3CreateIndex(
*/
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);
@@ -2919,3 +2919,79 @@ void sqlite3Reindex(Parse *pParse, Token *pName1, Token *pName2){
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
+
diff --git a/src/func.c b/src/func.c
index 46952284e..2d760b7f8 100644
--- a/src/func.c
+++ b/src/func.c
@@ -16,7 +16,7 @@
** 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>
@@ -507,6 +507,49 @@ static void versionFunc(
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
@@ -952,6 +995,9 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
{ "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
diff --git a/src/parse.y b/src/parse.y
index c8ebc76e1..1ff1b0dcc 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -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.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}
@@ -953,3 +953,10 @@ cmd ::= DETACH database_kw_opt nm(D). {
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
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 50f7f61a4..4f4e1b294 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** 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_
@@ -107,6 +107,7 @@
/* #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
@@ -1457,6 +1458,8 @@ sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
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
diff --git a/src/tokenize.c b/src/tokenize.c
index 9cda93948..5ae661379 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -15,7 +15,7 @@
** 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"
@@ -65,7 +65,7 @@ static const char isIdChar[] = {
** 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': {
@@ -349,7 +349,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
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: