Changeset: 556d4ebf0f83 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=556d4ebf0f83 Modified Files: sql/backends/monet5/rel_bin.c sql/include/sql_catalog.h sql/storage/store.c sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.sql sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.err sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.out sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.SQL.py sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.stable.out Branch: Oct2020 Log Message:
Fix for bug 7030, ie a sequence may not be created on sys schema diffs (237 lines): diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c --- a/sql/backends/monet5/rel_bin.c +++ b/sql/backends/monet5/rel_bin.c @@ -5314,15 +5314,11 @@ sql_truncate(backend *be, sql_table *t, mvc *sql = be->mvc; list *l = sa_list(sql->sa); stmt *v, *ret = NULL, *other = NULL; - const char *next_value_for = "next value for \"sys\".\"seq_"; - char *seq_name = NULL; - str seq_pos = NULL; + const char *next_value_for = "next value for "; sql_column *col = NULL; - sql_sequence *seq = NULL; sql_schema *sche = NULL; sql_table *next = NULL; sql_trans *tr = sql->session->tr; - node *n = NULL; int error = 0; struct tablelist* new_list = SA_NEW(sql->ta, struct tablelist), *list_node; @@ -5343,18 +5339,20 @@ sql_truncate(backend *be, sql_table *t, sche = next->s; if (restart_sequences) { /* restart the sequences if it's the case */ - for (n = next->columns.set->h; n; n = n->next) { + for (node *n = next->columns.set->h; n; n = n->next) { col = n->data; - if (col->def && (seq_pos = strstr(col->def, next_value_for))) { - seq_name = sa_strdup(sql->ta, seq_pos + (strlen(next_value_for) - strlen("seq_"))); - if (!seq_name) { - sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); - error = 1; - goto finalize; - } - seq_name[strlen(seq_name)-1] = '\0'; - seq = find_sql_sequence(sche, seq_name); - if (seq) { + + if (col->def && !strncmp(col->def, next_value_for, strlen(next_value_for))) { + sql_schema *s = NULL; + sql_sequence *seq = NULL; + char *schema = NULL, *seq_name = NULL; + + extract_schema_and_sequence_name(sql->ta, col->def + strlen(next_value_for), &schema, &seq_name); + if (!schema || !seq_name || !(s = find_sql_schema(tr, schema))) + continue; + + assert(s->base.id == sche->base.id); + if ((seq = find_sql_sequence(s, seq_name))) { if (!sql_trans_sequence_restart(tr, seq, seq->start)) { sql_error(sql, 02, SQLSTATE(HY005) "Could not restart sequence %s.%s", sche->base.name, seq_name); error = 1; 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 @@ -774,4 +774,55 @@ typedef struct { extern int nested_mergetable(sql_trans *tr, sql_table *t, const char *sname, const char *tname); extern sql_part *partition_find_part(sql_trans *tr, sql_table *pt, sql_part *pp); +#define outside_str 1 +#define inside_str 2 + +#define extracting_schema 1 +#define extracting_sequence 2 + +static inline void +extract_schema_and_sequence_name(sql_allocator *sa, char *default_value, char **schema, char **sequence) +{ + int status = outside_str, identifier = extracting_schema; + char next_identifier[1024]; /* needs one extra character for null terminator */ + size_t bp = 0; + + for (size_t i = 0; default_value[i]; i++) { + char next = default_value[i]; + + if (next == '"') { + if (status == inside_str && default_value[i + 1] == '"') { + next_identifier[bp++] = '"'; + i++; /* has to advance two positions */ + } else if (status == inside_str) { + next_identifier[bp++] = '\0'; + if (identifier == extracting_schema) { + *schema = sa_strdup(sa, next_identifier); + identifier = extracting_sequence; + } else if (identifier == extracting_sequence) { + *sequence = sa_strdup(sa, next_identifier); + break; /* done extracting */ + } + bp = 0; + status = outside_str; + } else { + assert(status == outside_str); + status = inside_str; + } + } else if (next == '.') { + if (status == outside_str && default_value[i + 1] == '"') { + status = inside_str; + i++; /* has to advance two positions */ + } else { + assert(status == inside_str); + next_identifier[bp++] = '.'; /* used inside an identifier name */ + } + } else if (status == inside_str) { + next_identifier[bp++] = next; + } else { + assert(status == outside_str); + } + } +} + #endif /* SQL_CATALOG_H */ diff --git a/sql/storage/store.c b/sql/storage/store.c --- a/sql/storage/store.c +++ b/sql/storage/store.c @@ -5512,27 +5512,26 @@ sys_drop_statistics(sql_trans *tr, sql_c static int sys_drop_default_object(sql_trans *tr, sql_column *col, int drop_action) { - char *seq_pos = NULL; - const char *next_value_for = "next value for \"sys\".\"seq_"; - sql_schema *syss = find_sql_schema(tr, isGlobal(col->t)?"sys":"tmp"); + const char *next_value_for = "next value for "; /* Drop sequence for generated column if it's the case */ - if (col->def && (seq_pos = strstr(col->def, next_value_for))) { + if (col->def && !strncmp(col->def, next_value_for, strlen(next_value_for))) { + sql_schema *s = NULL; sql_sequence *seq = NULL; - char *seq_name = _STRDUP(seq_pos + (strlen(next_value_for) - strlen("seq_"))); node *n = NULL; - - if (!seq_name) + char *schema = NULL, *seq_name = NULL; + + extract_schema_and_sequence_name(tr->sa, col->def + strlen(next_value_for), &schema, &seq_name); + if (!schema || !seq_name || !(s = find_sql_schema(tr, schema))) return -1; - seq_name[strlen(seq_name)-1] = '\0'; - n = cs_find_name(&syss->seqs, seq_name); - seq = find_sql_sequence(syss, seq_name); - if (seq && sql_trans_get_dependency_type(tr, seq->base.id, BEDROPPED_DEPENDENCY) > 0) { + + n = cs_find_name(&s->seqs, seq_name); + seq = find_sql_sequence(s, seq_name); + if (seq && n && sql_trans_get_dependency_type(tr, seq->base.id, BEDROPPED_DEPENDENCY) > 0) { sys_drop_sequence(tr, seq, drop_action); - seq->base.wtime = syss->base.wtime = tr->wtime = tr->wstime; - cs_del(&syss->seqs, n, seq->base.flags); - } - _DELETE(seq_name); + seq->base.wtime = s->base.wtime = tr->wtime = tr->wstime; + cs_del(&s->seqs, n, seq->base.flags); + } } return 0; } diff --git a/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.sql b/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.sql --- a/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.sql +++ b/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.sql @@ -1,4 +1,11 @@ +create local temp table "depend_count" ("a" bigint) on commit preserve rows; +insert into "depend_count" values ((select count(*) from dependencies, sequences)); + create schema s1; create table s1.t (i int not null auto_increment); drop table s1.t; drop schema s1; + +select cast(count(*) - (select "a" from "depend_count") as bigint) from dependencies, sequences; + -- the number of dependencies and sequences shouldn't increase +drop table "depend_count"; diff --git a/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.err b/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.err --- a/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.err +++ b/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.err @@ -5,10 +5,6 @@ stderr of test 'drop-table-with-auto_inc # 12:21:18 > "mclient" "-lsql" "-ftest" "-tnone" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-868236" "--port=30843" # 12:21:18 > -MAPI = (monetdb) /var/tmp/mtest-868236/.s.monetdb.30843 -QUERY = drop schema s1; - -CODE = 2BM37 # 12:21:18 > # 12:21:18 > "Done." diff --git a/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.out b/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.out --- a/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.out +++ b/sql/test/BugTracker-2020/Tests/drop-table-with-auto_increment.Bug-7030.stable.out @@ -5,10 +5,20 @@ stdout of test 'drop-table-with-auto_inc # 12:21:18 > "mclient" "-lsql" "-ftest" "-tnone" "-Eutf-8" "-i" "-e" "--host=/var/tmp/mtest-868236" "--port=30843" # 12:21:18 > +#create local temp table "depend_count" ("a" bigint) on commit preserve rows; +#insert into "depend_count" values ((select count(*) from dependencies, sequences)); +[ 1 ] #create schema s1; #create table s1.t (i int not null auto_increment); #drop table s1.t; #drop schema s1; +#select cast(count(*) - (select "a" from "depend_count") as bigint) from dependencies, sequences; +% .%3 # table_name +% %3 # name +% bigint # type +% 1 # length +[ 0 ] +#drop table "depend_count"; # 12:21:18 > # 12:21:18 > "Done." diff --git a/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.SQL.py b/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.SQL.py --- a/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.SQL.py +++ b/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.SQL.py @@ -63,3 +63,8 @@ run(c2, 'DELETE FROM test WHERE d = 42;' query(c2, 'SELECT * FROM test;') query(c2, 'SET role role1; -- verifies role1 is gone') +c2.close() +run(c1, 'DROP USER bruce;') +run(c1, 'DROP ROLE role1;') +run(c1, 'DROP SCHEMA s1 CASCADE;') +c1.close() diff --git a/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.stable.out b/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.stable.out --- a/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.stable.out +++ b/sql/test/BugTracker-2020/Tests/revokeRoleUserLoggedIN.Bug-7026.stable.out @@ -40,6 +40,12 @@ SELECT * FROM test; SET role role1; -- verifies role1 is gone ! 42000!Role (role1) missing +DROP USER bruce; +# OK +DROP ROLE role1; +# OK +DROP SCHEMA s1 CASCADE; +# OK # 14:34:37 > # 14:34:37 > "Done." _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list