[tarantool-patches] [PATCH 4/7] sql: refactor ALTER RENAME code generation
Nikita Pettik
korablev at tarantool.org
Fri Aug 24 01:55:50 MSK 2018
We are going to remove legacy cache of struct Table, so lets get rid of
using SQLite tables in alter routine.
Part of #3561
---
src/box/sql/alter.c | 114 ++++++++++++++------------------------------
src/box/sql/parse.y | 2 +-
src/box/sql/sqliteInt.h | 13 ++++-
src/box/sql/vdbe.c | 5 +-
test/sql-tap/alter.test.lua | 4 +-
5 files changed, 53 insertions(+), 85 deletions(-)
diff --git a/src/box/sql/alter.c b/src/box/sql/alter.c
index 349589be4..320dfdd05 100644
--- a/src/box/sql/alter.c
+++ b/src/box/sql/alter.c
@@ -34,91 +34,51 @@
* that implements the ALTER TABLE command.
*/
#include "sqliteInt.h"
-#include "src/box/session.h"
-#include "tarantoolInt.h"
+#include "box/box.h"
+#include "box/schema.h"
-/*
- * Generate code to drop and reload the internal representation of table
- * pTab from the database, including triggers.
- * Argument zName is the name of the table in the database schema at
- * the time the generated code is executed. This can be different from
- * pTab->zName if this function is being called to code part of an
- * "ALTER TABLE RENAME TO" statement.
- */
-static void
-reloadTableSchema(Parse * pParse, Table * pTab, const char *zName)
-{
- Vdbe *v;
- v = sqlite3GetVdbe(pParse);
- if (NEVER(v == 0))
- return;
-
- char *zNewName = sqlite3MPrintf(pParse->db, "%s", zName);
- sqlite3VdbeAddOp4(v, OP_RenameTable, pTab->def->id, 0, 0, zNewName,
- P4_DYNAMIC);
-}
-
-/*
- * 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. */
+sql_alter_table_rename(struct Parse *parse, struct SrcList *src_tab,
+ struct Token *new_name_tk)
{
- Table *pTab; /* Table being renamed */
- char *zName = 0; /* NULL-terminated version of pName */
- sqlite3 *db = pParse->db; /* Database connection */
- Vdbe *v;
- uint32_t savedDbFlags; /* Saved value of db->flags */
- struct session *user_session = current_session();
-
- savedDbFlags = user_session->sql_flags;
-
- if (NEVER(db->mallocFailed))
- goto exit_rename_table;
- assert(pSrc->nSrc == 1);
-
- pTab = sqlite3LocateTable(pParse, 0, pSrc->a[0].zName);
- if (pTab == NULL)
- goto exit_rename_table;
-
- user_session->sql_flags |= SQLITE_PreferBuiltin;
-
- /* Get a NULL terminated version of the new table name. */
- zName = sqlite3NameFromToken(db, pName);
- if (!zName)
- goto exit_rename_table;
-
- /* Check that a table named 'zName' does not already exist
- * in database. If so, this is an error.
- */
- if (sqlite3HashFind(&db->pSchema->tblHash, zName) != NULL) {
- sqlite3ErrorMsg(pParse,
- "there is already another table or index with this name: %s",
- zName);
+ assert(src_tab->nSrc == 1);
+ struct sqlite3 *db = parse->db;
+ char *new_name = sqlite3NameFromToken(db, new_name_tk);
+ if (new_name == NULL)
goto exit_rename_table;
+ /* Check that new name isn't occupied by another table. */
+ uint32_t space_id = box_space_id_by_name(new_name, strlen(new_name));
+ if (space_id != BOX_ID_NIL) {
+ diag_set(ClientError, ER_SQL_EXECUTE, tt_sprintf("there is "
+ "already another table with this name: %s", new_name));
+ goto tnt_error;
}
- if (pTab->def->opts.is_view) {
- sqlite3ErrorMsg(pParse, "view %s may not be altered",
- pTab->def->name);
- goto exit_rename_table;
+ const char *tbl_name = src_tab->a[0].zName;
+ space_id = box_space_id_by_name(tbl_name, strlen(tbl_name));
+ if (space_id == BOX_ID_NIL) {
+ diag_set(ClientError, ER_NO_SUCH_SPACE, tbl_name);
+ goto tnt_error;
}
- /* Begin a transaction for database. */
- v = sqlite3GetVdbe(pParse);
- if (v == 0) {
- goto exit_rename_table;
+ struct space *space = space_by_id(space_id);
+ assert(space != NULL);
+ if (space->def->opts.is_view) {
+ diag_set(ClientError, ER_SQL_EXECUTE,
+ "view may not be altered");
+ goto tnt_error;
}
- sql_set_multi_write(pParse, false);
-
+ sql_set_multi_write(parse, false);
/* Drop and reload the internal table schema. */
- reloadTableSchema(pParse, pTab, zName);
-
- exit_rename_table:
- sqlite3SrcListDelete(db, pSrc);
- sqlite3DbFree(db, zName);
- user_session->sql_flags = savedDbFlags;
+ struct Vdbe *v = sqlite3GetVdbe(parse);
+ sqlite3VdbeAddOp4(v, OP_RenameTable, space_id, 0, 0, new_name,
+ P4_DYNAMIC);
+exit_rename_table:
+ sqlite3SrcListDelete(db, src_tab);
+ return;
+tnt_error:
+ sqlite3DbFree(db, new_name);
+ parse->rc = SQL_TARANTOOL_ERROR;
+ parse->nErr++;
+ goto exit_rename_table;
}
/*
diff --git a/src/box/sql/parse.y b/src/box/sql/parse.y
index 60c0a8eed..92ce5a5bc 100644
--- a/src/box/sql/parse.y
+++ b/src/box/sql/parse.y
@@ -1432,7 +1432,7 @@ cmd ::= ANALYZE nm(X). {sqlite3Analyze(pParse, &X);}
//////////////////////// ALTER TABLE table ... ////////////////////////////////
cmd ::= ALTER TABLE fullname(X) RENAME TO nm(Z). {
- sqlite3AlterRenameTable(pParse,X,&Z);
+ sql_alter_table_rename(pParse,X,&Z);
}
cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT nm(Z) FOREIGN KEY
diff --git a/src/box/sql/sqliteInt.h b/src/box/sql/sqliteInt.h
index 96e2fff9f..3ae8db1bc 100644
--- a/src/box/sql/sqliteInt.h
+++ b/src/box/sql/sqliteInt.h
@@ -4427,7 +4427,18 @@ extern int sqlite3PendingByte;
#endif
#endif
void sqlite3Reindex(Parse *, Token *, Token *);
-void sqlite3AlterRenameTable(Parse *, SrcList *, Token *);
+
+/**
+ * Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
+ * command.
+ *
+ * @param parse Current parsing context.
+ * @param src_tab The table to rename.
+ * @param new_name_tk Token containing new name of the table.
+ */
+void
+sql_alter_table_rename(struct Parse *parse, struct SrcList *src_tab,
+ struct Token *new_name_tk);
/**
* Return the length (in bytes) of the token that begins at z[0].
diff --git a/src/box/sql/vdbe.c b/src/box/sql/vdbe.c
index d54d169ee..ad251ca99 100644
--- a/src/box/sql/vdbe.c
+++ b/src/box/sql/vdbe.c
@@ -4599,7 +4599,6 @@ case OP_RenameTable: {
struct space *space;
const char *zOldTableName;
const char *zNewTableName;
- Table *pTab;
struct init_data init;
char *zSqlStmt;
@@ -4610,15 +4609,13 @@ case OP_RenameTable: {
struct sql_trigger *triggers = space->sql_triggers;
zOldTableName = space_name(space);
assert(zOldTableName);
- pTab = sqlite3HashFind(&db->pSchema->tblHash, zOldTableName);
- assert(pTab);
zNewTableName = pOp->p4.z;
zOldTableName = sqlite3DbStrNDup(db, zOldTableName,
sqlite3Strlen30(zOldTableName));
rc = sql_rename_table(space_id, zNewTableName, &zSqlStmt);
if (rc) goto abort_due_to_error;
- sqlite3UnlinkAndDeleteTable(db, pTab->def->name);
+ sqlite3UnlinkAndDeleteTable(db, space->def->name);
init.db = db;
init.pzErrMsg = &p->zErrMsg;
diff --git a/test/sql-tap/alter.test.lua b/test/sql-tap/alter.test.lua
index db87c7003..ffd0ba6dc 100755
--- a/test/sql-tap/alter.test.lua
+++ b/test/sql-tap/alter.test.lua
@@ -72,7 +72,7 @@ test:do_catchsql_test(
ALTER TABLE none RENAME TO hi;
]], {
-- <alter-2.1>
- 1, "no such table: NONE"
+ 1, "Space 'NONE' does not exist"
-- </alter-2.1>
})
@@ -83,7 +83,7 @@ test:do_catchsql_test(
ALTER TABLE t2 RENAME TO t3;
]], {
-- <alter-2.2>
- 1, "there is already another table or index with this name: T3"
+ 1, "Failed to execute SQL statement: there is already another table with this name: T3"
-- </alter-2.2>
})
--
2.15.1
More information about the Tarantool-patches
mailing list