Changeset: a903388a5459 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a903388a5459
Modified Files:
monetdb5/modules/mal/wlc.mal
sql/backends/monet5/sql_cat.c
sql/backends/monet5/sqlcatalog.mal
sql/backends/monet5/wlr.mal
sql/common/sql_changeset.c
sql/include/sql_catalog.h
sql/server/rel_schema.c
sql/storage/sql_storage.h
sql/storage/store.c
sql/test/BugTracker-2019/Tests/alter_table_set_schema.Bug-6701.stable.out
Branch: Apr2019
Log Message:
Fixes for bug 6701. Instead of recreating the table, we add the schema change
in the transaction level and apply it before any schema changes.
The case of a table changing it's schema twice during the transaction is not
handled properly yet, but anyway it's a rare case.
diffs (truncated from 447 to 300 lines):
diff --git a/monetdb5/modules/mal/wlc.mal b/monetdb5/modules/mal/wlc.mal
--- a/monetdb5/modules/mal/wlc.mal
+++ b/monetdb5/modules/mal/wlc.mal
@@ -234,7 +234,7 @@ pattern rename_schema(sname:str, newnme:
address WLCgeneric
comment "Catalog operation rename_schema";
-pattern rename_table(sname:str, tname:str, newnme:str)
+pattern rename_table(osname:str, nsname:str, otname:str, ntname:str)
address WLCgeneric
comment "Catalog operation rename_table";
diff --git a/sql/backends/monet5/sql_cat.c b/sql/backends/monet5/sql_cat.c
--- a/sql/backends/monet5/sql_cat.c
+++ b/sql/backends/monet5/sql_cat.c
@@ -1603,30 +1603,65 @@ SQLrename_table(Client cntxt, MalBlkPtr
{
mvc *sql = NULL;
str msg = MAL_SUCCEED;
- str schema_name = *getArgReference_str(stk, pci, 1);
- str old_name = *getArgReference_str(stk, pci, 2);
- str new_name = *getArgReference_str(stk, pci, 3);
- sql_schema *s;
+ str oschema_name = *getArgReference_str(stk, pci, 1);
+ str nschema_name = *getArgReference_str(stk, pci, 2);
+ str otable_name = *getArgReference_str(stk, pci, 3);
+ str ntable_name = *getArgReference_str(stk, pci, 4);
+ sql_schema *o, *s;
sql_table *t;
initcontext();
- if (!(s = mvc_bind_schema(sql, schema_name)))
- throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no
such schema '%s'", schema_name);
- if (!mvc_schema_privs(sql, s))
- throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE:
access denied for %s to schema '%s'", stack_get_string(sql, "current_user"),
schema_name);
- if (!(t = mvc_bind_table(sql, s, old_name)))
- throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER TABLE: no
such table '%s' in schema '%s'", old_name, schema_name);
- if (t->system)
- throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER TABLE:
cannot rename a system table");
- if (mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY, NULL))
- throw (SQL,"sql.rename_table", SQLSTATE(2BM37) "ALTER TABLE:
unable to rename table '%s' (there are database objects which depend on it)",
old_name);
- if (!new_name || strcmp(new_name, str_nil) == 0 || *new_name == '\0')
- throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER TABLE:
invalid new table name");
- if (mvc_bind_table(sql, s, new_name))
- throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER TABLE:
there is a table named '%s' in schema '%s'", new_name, schema_name);
+
+ if(strcmp(oschema_name, nschema_name) == 0) { //renaming the table
itself
+ if (!(s = mvc_bind_schema(sql, oschema_name)))
+ throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER
TABLE: no such schema '%s'", oschema_name);
+ if (!mvc_schema_privs(sql, s))
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: access denied for %s to schema '%s'", stack_get_string(sql,
"current_user"), oschema_name);
+ if (!(t = mvc_bind_table(sql, s, otable_name)))
+ throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER
TABLE: no such table '%s' in schema '%s'", otable_name, oschema_name);
+ if (t->system)
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: cannot rename a system table");
+ if (mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY,
NULL))
+ throw (SQL,"sql.rename_table", SQLSTATE(2BM37) "ALTER
TABLE: unable to rename table '%s' (there are database objects which depend on
it)", otable_name);
+ if (!ntable_name || strcmp(ntable_name, str_nil) == 0 ||
*ntable_name == '\0')
+ throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER
TABLE: invalid new table name");
+ if (mvc_bind_table(sql, s, ntable_name))
+ throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER
TABLE: there is a table named '%s' in schema '%s'", ntable_name, oschema_name);
+
+ if (!sql_trans_rename_table(sql->session->tr, s, t->base.id,
ntable_name))
+ throw(SQL, "sql.rename_table",SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ } else { //changing the schema of the table
+ assert(strcmp(otable_name, ntable_name) == 0);
- if (!sql_trans_rename_table(sql->session->tr, s, t->base.id, new_name))
- throw(SQL, "sql.rename_table",SQLSTATE(HY001) MAL_MALLOC_FAIL);
+ if (!(o = mvc_bind_schema(sql, oschema_name)))
+ throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER
TABLE: no such schema '%s'", oschema_name);
+ if (!mvc_schema_privs(sql, o))
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: access denied for %s to schema '%s'", stack_get_string(sql,
"current_user"), oschema_name);
+ if (!(t = mvc_bind_table(sql, o, otable_name)))
+ throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER
TABLE: no such table '%s' in schema '%s'", otable_name, oschema_name);
+ if (t->system)
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: cannot set schema of a system table");
+ if (isTempSchema(o) || isTempTable(t))
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: not possible to change a temporary table schema");
+ if (isView(t))
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: not possible to change schema of a view");
+ if (mvc_check_dependency(sql, t->base.id, TABLE_DEPENDENCY,
NULL))
+ throw(SQL, "sql.rename_table", SQLSTATE(2BM37) "ALTER
TABLE: unable to set schema of table '%s' (there are database objects which
depend on it)", otable_name);
+ if (t->members.set || t->triggers.set)
+ throw(SQL, "sql.rename_table", SQLSTATE(2BM37) "ALTER
TABLE: unable to set schema of table '%s' (there are database objects which
depend on it)", otable_name);
+ if (!(s = mvc_bind_schema(sql, nschema_name)))
+ throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER
TABLE: no such schema '%s'", nschema_name);
+ if (!mvc_schema_privs(sql, s))
+ throw(SQL, "sql.rename_table", SQLSTATE(42000) "ALTER
TABLE: access denied for '%s' to schema '%s'", stack_get_string(sql,
"current_user"), nschema_name);
+ if (isTempSchema(s))
+ throw(SQL, "sql.rename_table", SQLSTATE(3F000) "ALTER
TABLE: not possible to change table's schema to temporary");
+ if (mvc_bind_table(sql, s, otable_name))
+ throw(SQL, "sql.rename_table", SQLSTATE(42S02) "ALTER
TABLE: table '%s' on schema '%s' already exists", otable_name, nschema_name);
+
+ if (!sql_trans_set_table_schema(sql->session->tr, t->base.id,
o, s))
+ throw(SQL, "sql.rename_table",SQLSTATE(HY001)
MAL_MALLOC_FAIL);
+ }
+
return msg;
}
diff --git a/sql/backends/monet5/sqlcatalog.mal
b/sql/backends/monet5/sqlcatalog.mal
--- a/sql/backends/monet5/sqlcatalog.mal
+++ b/sql/backends/monet5/sqlcatalog.mal
@@ -167,7 +167,7 @@ pattern rename_schema(sname:str, newnme:
address SQLrename_schema
comment "Catalog operation rename_schema";
-pattern rename_table(sname:str, tname:str, newnme:str)
+pattern rename_table(osname:str, nsname:str, otname:str, ntname:str)
address SQLrename_table
comment "Catalog operation rename_table";
diff --git a/sql/backends/monet5/wlr.mal b/sql/backends/monet5/wlr.mal
--- a/sql/backends/monet5/wlr.mal
+++ b/sql/backends/monet5/wlr.mal
@@ -239,7 +239,7 @@ pattern rename_schema(sname:str, newnme:
address WLRgeneric
comment "Catalog operation rename_schema";
-pattern rename_table(sname:str, tname:str, newnme:str)
+pattern rename_table(osname:str, nsname:str, otname:str, ntname:str)
address WLRgeneric
comment "Catalog operation rename_table";
diff --git a/sql/common/sql_changeset.c b/sql/common/sql_changeset.c
--- a/sql/common/sql_changeset.c
+++ b/sql/common/sql_changeset.c
@@ -81,6 +81,14 @@ cs_del(changeset * cs, node *elm, int fl
}
}
+void
+cs_move(changeset *from, changeset *to, void *data)
+{
+ if (!to->set)
+ to->set = list_new(to->sa, to->destroy);
+ list_move_data(from->set, to->set, data);
+}
+
int
cs_size(changeset * cs)
{
diff --git a/sql/include/sql_catalog.h b/sql/include/sql_catalog.h
--- a/sql/include/sql_catalog.h
+++ b/sql/include/sql_catalog.h
@@ -85,6 +85,7 @@
#define SCALE_EQ 7 /* user defined functions need equal scales */
#define SCALE_DIGITS_FIX 8 /* the geom module requires the types and
functions to have the same scale and digits */
+/* Warning TR flags are a bitmask */
#define TR_NEW 1
#define TR_RENAMED 2
@@ -223,6 +224,7 @@ extern void cs_add(changeset * cs, void
extern void *cs_add_with_validate(changeset * cs, void *elm, int flag,
fvalidate cmp);
extern void cs_add_before(changeset * cs, node *n, void *elm);
extern void cs_del(changeset * cs, node *elm, int flag);
+extern void cs_move(changeset *from, changeset *to, void *data);
extern void *cs_transverse_with_validate(changeset * cs, void *elm, fvalidate
cmp);
extern int cs_size(changeset * cs);
extern node *cs_find_name(changeset * cs, const char *name);
@@ -244,6 +246,7 @@ typedef struct sql_trans {
int schema_updates; /* set on schema changes */
int status; /* status of the last query */
list *dropped; /* protection against recursive cascade action*/
+ list *moved_tables;
changeset schemas;
@@ -598,6 +601,12 @@ typedef struct sql_table {
} part;
} sql_table;
+typedef struct sql_moved_table {
+ sql_schema *from;
+ sql_schema *to;
+ sql_table *t;
+} sql_moved_table;
+
typedef struct res_col {
char *tn;
char *name;
diff --git a/sql/server/rel_schema.c b/sql/server/rel_schema.c
--- a/sql/server/rel_schema.c
+++ b/sql/server/rel_schema.c
@@ -2539,6 +2539,7 @@ rel_rename_table(mvc *sql, char* schema_
rel = rel_create(sql->sa);
exps = new_exp_list(sql->sa);
append(exps, exp_atom_clob(sql->sa, schema_name));
+ append(exps, exp_atom_clob(sql->sa, schema_name));
append(exps, exp_atom_clob(sql->sa, old_name));
append(exps, exp_atom_clob(sql->sa, new_name));
rel->op = op_ddl;
@@ -2595,15 +2596,13 @@ rel_rename_column(mvc *sql, char* schema
return rel;
}
-extern list *rel_dependencies(mvc *sql, sql_rel *r);
-
static sql_rel *
rel_set_table_schema(mvc *sql, char* old_schema, char *tname, char
*new_schema, int if_exists)
{
- node *n;
sql_schema *os, *ns;
- sql_table *ot, *nt;
- sql_rel *l, *r, *inserts;
+ sql_table *ot;
+ sql_rel *rel;
+ list *exps;
assert(old_schema && tname && new_schema);
@@ -2638,53 +2637,16 @@ rel_set_table_schema(mvc *sql, char* old
if (mvc_bind_table(sql, ns, tname))
return sql_error(sql, 02, SQLSTATE(42S02) "ALTER TABLE: table
'%s' on schema '%s' already exists", tname, new_schema);
- if ((nt = mvc_create_table(sql, ns, tname, ot->type, 0,
SQL_DECLARED_TABLE, ot->commit_action, -1, ot->properties)) == NULL)
- return NULL;
-
- for (n = ot->columns.set->h; n; n = n->next) {
- sql_column *nc, *oc = (sql_column*) n->data;
- if (!(nc = mvc_copy_column(sql, nt, oc)))
- return sql_error(sql, 02, SQLSTATE(42000) "ALTER TABLE:
%s_%s_%s conflicts", ns->base.name, nt->base.name, oc->base.name);
- if (isPartitionedByColumnTable(ot) && oc->base.id ==
ot->part.pcol->base.id)
- nt->part.pcol = nc;
- }
- if (isPartitionedByExpressionTable(ot)) {
- char *err = NULL;
- sql_allocator *oa = sql->sa;
-
- nt->part.pexp->exp = sa_strdup(sql->session->tr->sa,
ot->part.pexp->exp);
-
- sql->sa = sa_create();
- if (!sql->sa) {
- sql->sa = oa;
- return sql_error(sql, 02, SQLSTATE(HY001)
MAL_MALLOC_FAIL);
- }
-
- err = bootstrap_partition_expression(sql, sql->session->tr->sa,
nt, 0);
- sa_destroy(sql->sa);
- sql->sa = NULL;
- if (err) {
- sql->sa = oa;
- return sql_error(sql, 02, "%s", err);
- }
- }
-
- if (ot->idxs.set)
- for (n = ot->idxs.set->h; n; n = n->next)
- mvc_copy_idx(sql, nt, (sql_idx*) n->data);
-
- if (ot->keys.set)
- for (n = ot->keys.set->h; n; n = n->next)
- mvc_copy_key(sql, nt, (sql_key*) n->data);
-
- l = rel_table(sql, DDL_CREATE_TABLE, new_schema, nt, 0);
- if (!(isMergeTable(ot) || isRemote(ot) || isReplicaTable(ot))) {
- inserts = rel_basetable(sql, ot, tname);
- inserts = rel_project(sql->sa, inserts, rel_projections(sql,
inserts, NULL, 1, 0));
- l = rel_insert(sql, l, inserts);
- }
- r = rel_drop(sql->sa, DDL_DROP_TABLE, old_schema, tname, 0, 0);
- return rel_list(sql->sa, l, r);
+ rel = rel_create(sql->sa);
+ exps = new_exp_list(sql->sa);
+ append(exps, exp_atom_clob(sql->sa, old_schema));
+ append(exps, exp_atom_clob(sql->sa, new_schema));
+ append(exps, exp_atom_clob(sql->sa, tname));
+ append(exps, exp_atom_clob(sql->sa, tname));
+ rel->op = op_ddl;
+ rel->flag = DDL_RENAME_TABLE;
+ rel->exps = exps;
+ return rel;
}
sql_rel *
diff --git a/sql/storage/sql_storage.h b/sql/storage/sql_storage.h
--- a/sql/storage/sql_storage.h
+++ b/sql/storage/sql_storage.h
@@ -384,6 +384,7 @@ extern int sql_trans_add_range_partition
extern int sql_trans_add_value_partition(sql_trans *tr, sql_table *mt,
sql_table *pt, sql_subtype tpe, list* vals, int with_nills, int update,
sql_part **err);
extern sql_table *sql_trans_rename_table(sql_trans *tr, sql_schema *s, sqlid
id, const char *new_name);
+extern sql_table *sql_trans_set_table_schema(sql_trans *tr, sqlid id,
sql_schema *os, sql_schema *ns);
extern sql_table *sql_trans_del_table(sql_trans *tr, sql_table *mt, sql_table
*pt, int drop_action);
extern int sql_trans_drop_table(sql_trans *tr, sql_schema *s, sqlid id, int
drop_action);
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -3652,6 +3652,20 @@ rollforward_trans(sql_trans *tr, int mod
tr->parent->schema_updates = tr->schema_updates;
}
+ if (tr->moved_tables) {
+ for (node *n = tr->moved_tables->h ; n ; n = n->next) {
+ sql_moved_table *smt = (sql_moved_table*) n->data;
+ sql_schema *pfrom = find_sql_schema_id(tr->parent,
smt->from->base.id);
+ sql_schema *pto = find_sql_schema_id(tr->parent,
smt->to->base.id);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list