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 checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list