Changeset: 25610bd0191e for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/25610bd0191e Branch: default Log Message:
Merged with Jan2022 diffs (176 lines): diff --git a/sql/storage/store.c b/sql/storage/store.c --- a/sql/storage/store.c +++ b/sql/storage/store.c @@ -3412,6 +3412,12 @@ sql_trans_copy_idx( sql_trans *tr, sql_t if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset sql functions depending on the table */ return res; + /* this dependency is needed for merge tables */ + if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl))) + return res; + if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml))) + return res; + if (isDeclaredTable(i->t)) if (!isDeclaredTable(t) && isTable(ni->t) && idx_has_column(ni->type)) if ((res = store->storage_api.create_idx(tr, ni))) { @@ -3518,6 +3524,12 @@ sql_trans_copy_column( sql_trans *tr, sq if ((res = ol_add(t->columns, &col->base))) return res; + /* this dependency is needed for merge tables */ + if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, ddl))) + return res; + if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml))) + return res; + ATOMIC_PTR_INIT(&col->data, NULL); if (isDeclaredTable(c->t)) if (isTable(t)) @@ -3535,11 +3547,16 @@ sql_trans_copy_column( sql_trans *tr, sq ATOMIC_PTR_DESTROY(&col->data); return res; } - if (c->type.type->s) /* column depends on type */ + if (c->type.type->s) { /* column depends on type */ if ((res = sql_trans_create_dependency(tr, c->type.type->base.id, col->base.id, TYPE_DEPENDENCY))) { ATOMIC_PTR_DESTROY(&col->data); return res; } + if (!isNew(c->type.type) && (res = sql_trans_add_dependency(tr, c->type.type->base.id, ddl))) { + ATOMIC_PTR_DESTROY(&col->data); + return res; + } + } } if (cres) *cres = col; @@ -6056,6 +6073,9 @@ sql_trans_alter_null(sql_trans *tr, sql_ dup->null = isnull; /* disallow concurrent updates on the column if not null is set */ + /* this dependency is needed for merge tables */ + if (!isNew(col) && (res = sql_trans_add_dependency(tr, col->t->base.id, ddl))) + return res; if (!isnull && !isNew(col) && isGlobal(col->t) && !isGlobalTemp(col->t) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml))) return res; if ((res = store_reset_sql_functions(tr, col->t->base.id))) /* reset sql functions depending on the table */ @@ -6582,8 +6602,10 @@ sql_trans_create_idx(sql_idx **i, sql_tr ATOMIC_PTR_INIT(&ni->data, NULL); if (!isDeclaredTable(t) && isTable(ni->t) && idx_has_column(ni->type)) - if ((res = store->storage_api.create_idx(tr, ni))) + if ((res = store->storage_api.create_idx(tr, ni))) { + ATOMIC_PTR_DESTROY(&ni->data); return res; + } if (!isDeclaredTable(t)) if ((res = store->table_api.table_insert(tr, sysidx, &ni->base.id, &t->base.id, &ni->type, &ni->base.name))) { ATOMIC_PTR_DESTROY(&ni->data); diff --git a/sql/test/BugTracker-2021/Tests/All b/sql/test/BugTracker-2021/Tests/All --- a/sql/test/BugTracker-2021/Tests/All +++ b/sql/test/BugTracker-2021/Tests/All @@ -33,3 +33,4 @@ remote-table-large.Bug-7178 groupby-subquery.Bug-7180 grouping-sets-aliases.Bug-7185 copyinto-copyfrom.Bug-7186 +concurrent-add-column.Bug-7196 diff --git a/sql/test/BugTracker-2021/Tests/concurrent-add-column.Bug-7196.SQL.py b/sql/test/BugTracker-2021/Tests/concurrent-add-column.Bug-7196.SQL.py new file mode 100644 --- /dev/null +++ b/sql/test/BugTracker-2021/Tests/concurrent-add-column.Bug-7196.SQL.py @@ -0,0 +1,30 @@ +from MonetDBtesting.sqltest import SQLTestCase + +with SQLTestCase() as mdb1: + with SQLTestCase() as mdb2: + mdb1.connect(username="monetdb", password="monetdb") + mdb2.connect(username="monetdb", password="monetdb") + + mdb1.execute('create table test (id bigint);').assertSucceeded() + mdb1.execute("insert into test values (1);").assertSucceeded() + mdb1.execute('start transaction;').assertSucceeded() + mdb2.execute('start transaction;').assertSucceeded() + mdb1.execute('alter table test add column data int;').assertSucceeded() + mdb2.execute("insert into test values (2);").assertSucceeded() + mdb1.execute('commit;').assertSucceeded() + mdb2.execute('commit;').assertFailed(err_code="40000", err_message="COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead") + + mdb1.execute('select * from test;').assertDataResultMatch([(1,None)]) + mdb2.execute('select * from test;').assertDataResultMatch([(1,None)]) + + mdb1.execute('start transaction;').assertSucceeded() + mdb2.execute('start transaction;').assertSucceeded() + mdb1.execute('alter table test drop column data;').assertSucceeded() + mdb2.execute("insert into test values (3,4);").assertSucceeded() + mdb1.execute('commit;').assertSucceeded() + mdb2.execute('commit;').assertSucceeded() + + mdb1.execute('select * from test;').assertDataResultMatch([(1,),(3,)]) + mdb2.execute('select * from test;').assertDataResultMatch([(1,),(3,)]) + + mdb1.execute('drop table test;').assertSucceeded() diff --git a/sql/test/transactions/Tests/transaction_isolation5.SQL.py b/sql/test/transactions/Tests/transaction_isolation5.SQL.py --- a/sql/test/transactions/Tests/transaction_isolation5.SQL.py +++ b/sql/test/transactions/Tests/transaction_isolation5.SQL.py @@ -71,6 +71,60 @@ with SQLTestCase() as mdb1: mdb1.connect(username="monetdb", password="monetdb") mdb2.connect(username="monetdb", password="monetdb") + mdb1.execute('start transaction;').assertSucceeded() + mdb1.execute('create merge table parent(a int, b int);').assertSucceeded() + mdb1.execute('create table child1(a int, b int);').assertSucceeded() + mdb1.execute("insert into child1 values (1,1);").assertSucceeded() + mdb1.execute('create table child2(a int, b int);').assertSucceeded() + mdb1.execute("insert into child2 values (2,2);").assertSucceeded() + mdb1.execute('commit;').assertSucceeded() + mdb1.execute('start transaction;').assertSucceeded() + mdb2.execute('start transaction;').assertSucceeded() + mdb1.execute("alter table parent add table child1;").assertSucceeded() + mdb2.execute('alter table child1 add column data int;').assertSucceeded() # number of columns must match + mdb1.execute('commit;').assertSucceeded() + mdb2.execute('commit;').assertFailed(err_code="40000", err_message="COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead") + + mdb1.execute('select * from parent;').assertDataResultMatch([(1,1)]) + mdb2.execute('select * from parent;').assertDataResultMatch([(1,1)]) + + mdb1.execute("alter table parent drop table child1;").assertSucceeded() + mdb1.execute("alter table parent add table child2;").assertSucceeded() + mdb1.execute('start transaction;').assertSucceeded() + mdb2.execute('start transaction;').assertSucceeded() + mdb1.execute("alter table parent add table child1;").assertSucceeded() + mdb2.execute('alter table child1 alter column a set not null;').assertSucceeded() # null constraints must match + mdb1.execute('commit;').assertSucceeded() + mdb2.execute('commit;').assertFailed(err_code="40000", err_message="COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead") + + mdb1.execute('select * from parent;').assertDataResultMatch([(1,1),(2,2)]) + mdb2.execute('select * from parent;').assertDataResultMatch([(1,1),(2,2)]) + + mdb1.execute('alter table parent drop table child1;').assertSucceeded() + + mdb1.execute('start transaction;').assertSucceeded() + mdb2.execute('start transaction;').assertSucceeded() + mdb1.execute("alter table parent add table child1;").assertSucceeded() + mdb2.execute('alter table child1 drop column b;').assertSucceeded() # number of columns must match + mdb1.execute('commit;').assertSucceeded() + mdb2.execute('commit;').assertFailed(err_code="40000", err_message="COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead") + + mdb1.execute('select * from parent;').assertDataResultMatch([(1,1),(2,2)]) + mdb2.execute('select * from parent;').assertDataResultMatch([(1,1),(2,2)]) + + mdb1.execute('start transaction;').assertSucceeded() + mdb1.execute('alter table parent drop table child1;').assertSucceeded() + mdb1.execute('alter table parent drop table child2;').assertSucceeded() + mdb1.execute('drop table parent;').assertSucceeded() + mdb1.execute('drop table child1;').assertSucceeded() + mdb1.execute('drop table child2;').assertSucceeded() + mdb1.execute('commit;').assertSucceeded() + +with SQLTestCase() as mdb1: + with SQLTestCase() as mdb2: + mdb1.connect(username="monetdb", password="monetdb") + mdb2.connect(username="monetdb", password="monetdb") + # Test different instantiations of SQL functions and views on different transactions mdb1.execute('start transaction;').assertSucceeded() mdb1.execute('CREATE MERGE TABLE parent(a int)').assertSucceeded() _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list