Changeset: d7378d64f5ca for MonetDB URL: https://dev.monetdb.org/hg/MonetDB/rev/d7378d64f5ca Modified Files: sql/backends/monet5/rel_bin.c sql/storage/store.c sql/test/miscellaneous/Tests/transaction_isolation3.SQL.py Branch: iso Log Message:
Added DML dependency checks diffs (211 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 @@ -4365,6 +4365,9 @@ rel2bin_insert(backend *be, sql_rel *rel /* update predicate list */ if (rel->r && !rel_predicates(be, rel->r)) return NULL; + if (!isNew(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK) + return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); + if (ddl) { ret = ddl; list_prepend(l, ddl); @@ -5355,6 +5358,8 @@ rel2bin_update(backend *be, sql_rel *rel sql->cascade_action = NULL; if (rel->r && !rel_predicates(be, rel->r)) return NULL; + if (!isNew(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK) + return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); return cnt; } @@ -5596,6 +5601,9 @@ rel2bin_delete(backend *be, sql_rel *rel } if (rel->r && !rel_predicates(be, rel->r)) return NULL; + if (!isNew(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK) + return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); + return stdelete; } @@ -5821,6 +5829,9 @@ rel2bin_truncate(backend *be, sql_rel *r restart_sequences = E_ATOM_INT(n->data); cascade = E_ATOM_INT(n->next->data); + if (!isNew(t) && sql_trans_add_dependency_change(be->mvc->session->tr, t->base.id, dml) != LOG_OK) + return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); + truncate = sql_truncate(be, t, restart_sequences, cascade); if (sql->cascade_action) sql->cascade_action = NULL; diff --git a/sql/storage/store.c b/sql/storage/store.c --- a/sql/storage/store.c +++ b/sql/storage/store.c @@ -3108,8 +3108,18 @@ sql_trans_copy_key( sql_trans *tr, sql_t if ((res = store->table_api.table_insert(tr, syskey, &nk->base.id, &t->base.id, &nk->type, &nk->base.name, (nk->type == fkey) ? &((sql_fkey *) nk)->rkey : &neg, &action))) return res; - if (nk->type == fkey && (res = sql_trans_create_dependency(tr, ((sql_fkey *) nk)->rkey, nk->base.id, FKEY_DEPENDENCY))) - return res; + if (nk->type == fkey) { + sql_key *rkey = (sql_key*)os_find_id(tr->cat->objects, tr, ((sql_fkey*)k)->rkey); + + if ((res = sql_trans_create_dependency(tr, rkey->base.id, nk->base.id, FKEY_DEPENDENCY))) + return res; + /* TODO this has to be cleaned out once the sql_cat.c cleanup is done */ + if (!isNew(rkey) && (res = sql_trans_add_dependency(tr, rkey->base.id, ddl))) + return res; + if (!isNew(rkey) && (res = sql_trans_add_dependency(tr, rkey->t->base.id, dml))) /* disallow concurrent updates on other key */ + return res; + } + for (n = nk->columns->h, nr = 0; n; n = n->next, nr++) { sql_kc *kc = n->data; @@ -3128,7 +3138,15 @@ sql_trans_copy_key( sql_trans *tr, sql_t if ((res = sql_trans_alter_null(tr, kc->c, 0))) return res; } - } + + /* TODO this has to be cleaned out too */ + if (!isNew(kc->c) && (res = sql_trans_add_dependency(tr, kc->c->base.id, ddl))) + return res; + } + + /* TODO this has to be cleaned out too */ + if (!isNew(t) && (res = sql_trans_add_dependency(tr, t->base.id, dml))) /* disallow concurrent updates on t */ + return res; if (kres) *kres = nk; return res; @@ -5091,6 +5109,8 @@ sql_trans_add_range_partition(sql_trans return res; if (!isNew(pt) && (res = sql_trans_add_dependency_change(tr, pt->base.id, ddl))) /* protect from being added twice */ return res; + if (!isNew(pt) && (res = sql_trans_add_dependency(tr, pt->base.id, dml))) /* disallow concurrent updates on pt */ + return res; finish: VALclear(&vmin); VALclear(&vmax); @@ -5221,6 +5241,8 @@ sql_trans_add_value_partition(sql_trans return res; if (!isNew(pt) && (res = sql_trans_add_dependency_change(tr, pt->base.id, ddl))) /* protect from being added twice */ return res; + if (!isNew(pt) && (res = sql_trans_add_dependency(tr, pt->base.id, dml))) /* disallow concurrent updates on pt */ + return res; return 0; } @@ -5669,7 +5691,7 @@ sql_trans_rename_column(sql_trans *tr, s return -1; sql_column *c = n->data; - if (!isNew(c->t) && (res = sql_trans_add_dependency_change(tr, c->t->base.id, ddl))) + if (!isNew(c) && (res = sql_trans_add_dependency_change(tr, c->t->base.id, ddl))) return res; if (!isNew(c) && (res = sql_trans_add_dependency_change(tr, id, ddl))) return res; @@ -5780,6 +5802,9 @@ sql_trans_alter_null(sql_trans *tr, sql_ if ((res = new_column(tr, col, &dup))) return res; dup->null = isnull; + + if (!isnull && !isNew(col) && (res = sql_trans_add_dependency(tr, col->t->base.id, dml))) /* disallow concurrent updates on pt */ + return res; } return res; } @@ -6054,8 +6079,6 @@ sql_trans_create_fkey(sql_trans *tr, sql return NULL; sql_trans_create_dependency(tr, ((sql_fkey *) nk)->rkey, nk->base.id, FKEY_DEPENDENCY); - if (!isNew(nk) && (res = sql_trans_add_dependency(tr, ((sql_fkey *) nk)->rkey, ddl))) - return NULL; return (sql_fkey*) nk; } @@ -6067,7 +6090,6 @@ sql_trans_create_kc(sql_trans *tr, sql_k int nr = list_length(k->columns); sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp"); sql_table *syskc = find_sql_table(tr, syss, "objects"); - int res = LOG_OK; assert(c); kc->c = c; @@ -6077,8 +6099,6 @@ sql_trans_create_kc(sql_trans *tr, sql_k if (k->type == pkey) { sql_trans_create_dependency(tr, c->base.id, k->base.id, KEY_DEPENDENCY); - if (!isNew(c) && (res = sql_trans_add_dependency(tr, c->base.id, ddl))) - return NULL; if (sql_trans_alter_null(tr, c, 0)) /* should never happen */ return NULL; } @@ -6097,7 +6117,6 @@ sql_trans_create_fkc(sql_trans *tr, sql_ int nr = list_length(k->columns); sql_schema *syss = find_sql_schema(tr, isGlobal(k->t)?"sys":"tmp"); sql_table *syskc = find_sql_table(tr, syss, "objects"); - int res = LOG_OK; assert(c); kc->c = c; @@ -6106,8 +6125,6 @@ sql_trans_create_fkc(sql_trans *tr, sql_ sql_trans_create_ic(tr, k->idx, c); sql_trans_create_dependency(tr, c->base.id, k->base.id, FKEY_DEPENDENCY); - if (!isNew(c) && (res = sql_trans_add_dependency(tr, c->base.id, ddl))) - return NULL; if (store->table_api.table_insert(tr, syskc, &k->base.id, &kc->c->base.name, &nr, ATOMnilptr(TYPE_int))) return NULL; diff --git a/sql/test/miscellaneous/Tests/transaction_isolation3.SQL.py b/sql/test/miscellaneous/Tests/transaction_isolation3.SQL.py --- a/sql/test/miscellaneous/Tests/transaction_isolation3.SQL.py +++ b/sql/test/miscellaneous/Tests/transaction_isolation3.SQL.py @@ -13,7 +13,7 @@ with SQLTestCase() as mdb1: mdb1.execute('commit;').assertSucceeded() mdb2.execute('rollback;').assertSucceeded() - mdb1.execute("CREATE TABLE notpossible (i int, j int);").assertSucceeded() # not fixed yet + mdb1.execute("CREATE TABLE notpossible (i int, j int);").assertSucceeded() mdb1.execute('start transaction;').assertSucceeded() mdb2.execute('start transaction;').assertSucceeded() mdb1.execute('insert into notpossible values (5,1),(5,2),(5,3);').assertSucceeded() @@ -21,7 +21,7 @@ with SQLTestCase() as mdb1: 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("CREATE TABLE integers (i int, j int);").assertSucceeded() # not fixed yet + mdb1.execute("CREATE TABLE integers (i int, j int);").assertSucceeded() mdb1.execute('start transaction;').assertSucceeded() mdb2.execute('start transaction;').assertSucceeded() mdb1.execute('alter table integers add primary key (i);').assertSucceeded() @@ -29,7 +29,7 @@ with SQLTestCase() as mdb1: 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('start transaction;').assertSucceeded() # not fixed yet + mdb1.execute('start transaction;').assertSucceeded() mdb2.execute('start transaction;').assertSucceeded() mdb1.execute('alter table integers alter j set not null;').assertSucceeded() mdb2.execute('insert into integers values (6,NULL),(7,NULL),(8,NULL);').assertSucceeded() @@ -46,7 +46,7 @@ with SQLTestCase() as mdb1: 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('create merge table parent2(a int) PARTITION BY RANGE ON (a);').assertSucceeded() # not fixed yet + mdb1.execute('create merge table parent2(a int) PARTITION BY RANGE ON (a);').assertSucceeded() mdb1.execute('create table child2(c int);').assertSucceeded() mdb1.execute('start transaction;').assertSucceeded() mdb2.execute('start transaction;').assertSucceeded() @@ -75,7 +75,7 @@ with SQLTestCase() as mdb1: mdb2.execute('commit;').assertFailed(err_code="40000", err_message="COMMIT: transaction is aborted because of concurrency conflicts, will ROLLBACK instead") mdb1.execute('select * from another();').assertSucceeded().assertDataResultMatch([(2,)]) - mdb1.execute("CREATE TABLE y (i int);").assertSucceeded() # not fixed yet + mdb1.execute("CREATE TABLE y (i int);").assertSucceeded() mdb1.execute('CREATE TABLE integers2 (i int, j int);').assertSucceeded() mdb1.execute('insert into integers2 values (1,1),(2,2),(3,3);').assertSucceeded() mdb1.execute('alter table integers2 add primary key (i);').assertSucceeded() _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list