Changeset: 2c608d1df054 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/2c608d1df054
Modified Files:
        sql/storage/bat/bat_storage.c
Branch: default
Log Message:

Merge with Jan2022 branch.


diffs (217 lines):

diff --git a/gdk/gdk_bat.c b/gdk/gdk_bat.c
--- a/gdk/gdk_bat.c
+++ b/gdk/gdk_bat.c
@@ -861,8 +861,8 @@ COLcopy(BAT *b, int tt, bool writable, r
                        if (bn->tvheap && HEAPextend(bn->tvheap, bi.vhfree, 
true) != GDK_SUCCEED) {
                                goto bunins_failed;
                        }
-                       memcpy(bn->theap->base, bi.base, bi.count << bi.shift);
-                       bn->theap->free = bi.count << bi.shift;
+                       memcpy(bn->theap->base, bi.base, bi.hfree);
+                       bn->theap->free = bi.hfree;
                        bn->theap->dirty = true;
                        if (bn->tvheap) {
                                memcpy(bn->tvheap->base, bi.vh->base, 
bi.vhfree);
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
@@ -2862,6 +2862,8 @@ rel2bin_semijoin(backend *be, sql_rel *r
                                        int oldvtop = be->mb->vtop, oldstop = 
be->mb->stop, oldvid = be->mb->vid, swap = 0;
                                        stmt *r, *l = exp_bin(be, e->l, left, 
NULL, NULL, NULL, NULL, NULL, 1, 0, 0);
 
+                                       if (l && left && l->nrcols==0 && 
left->nrcols >0)
+                                               l = stmt_const(be, 
bin_find_smallest_column(be, left), l);
                                        if (!l) {
                                                swap = 1;
                                                clean_mal_statements(be, 
oldstop, oldvtop, oldvid);
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -1959,6 +1959,8 @@ rel_in_value_exp(sql_query *query, sql_r
                        } else if (exp_is_rel(re)) {
                                sql_rel *r = exp_rel_get_rel(sql->sa, re);
                                add_select = 1;
+                               if (*rel)
+                                       set_dependent((*rel));
                                if (is_project(r->op) && is_project_true(r->l) 
&& list_length(r->exps) == 1)
                                        re = r->exps->h->data;
                        }
diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c
--- a/sql/server/rel_unnest.c
+++ b/sql/server/rel_unnest.c
@@ -1481,8 +1481,15 @@ rel_unnest_dependent(mvc *sql, sql_rel *
                }
 
                if (!rel_has_freevar(sql, r)) {
-                       reset_dependent(rel);
-                       return rel;
+                       if (rel_has_freevar(sql, l) && is_join(rel->op) && 
!rel->exps) {
+                               rel->l = r;
+                               rel->r = l;
+                               l = rel->l;
+                               r = rel->r;
+                       } else {
+                               reset_dependent(rel);
+                               return rel;
+                       }
                }
 
                /* try to push dependent join down */
@@ -3085,9 +3092,12 @@ exp_exist(mvc *sql, sql_exp *le, sql_exp
        if (!exists_func)
                return sql_error(sql, 02, SQLSTATE(42000) "exist operator on 
type %s missing", exp_subtype(le)->type->base.name);
        if (ne) { /* correlated case */
-               ne = rel_unop_(sql, NULL, ne, "sys", "isnull", card_value);
-               set_has_no_nil(ne);
-               le = rel_nop_(sql, NULL, ne, exp_atom_bool(sql->sa, !exists), 
exp_atom_bool(sql->sa, exists), NULL, "sys", "ifthenelse", card_value);
+               if (exists)
+                       le = rel_nop_(sql, NULL, ne, exp_atom_bool(sql->sa, 
exists), exp_atom_bool(sql->sa, !exists), NULL, "sys", "ifthenelse", 
card_value);
+               else {
+                       ne = rel_unop_(sql, NULL, ne, "sys", "not", card_value);
+                       le = rel_nop_(sql, NULL, ne, exp_atom_bool(sql->sa, 
exists), exp_atom_bool(sql->sa, !exists), NULL, "sys", "ifthenelse", 
card_value);
+               }
                return le;
        } else {
                sql_exp *res = exp_unop(sql->sa, le, exists_func);
diff --git a/sql/storage/bat/bat_storage.c b/sql/storage/bat/bat_storage.c
--- a/sql/storage/bat/bat_storage.c
+++ b/sql/storage/bat/bat_storage.c
@@ -2441,33 +2441,36 @@ min_max_col(sql_trans *tr, sql_column *c
                return 0;
        if (c->min && c->max)
                return 1;
-
-       lock_column(tr->store, c->base.id);
-       if (c->min && c->max) {
+       if ((d = ATOMIC_PTR_GET(&c->data))) {
+               if (d->cs.st == ST_FOR)
+                       return 0;
+               lock_column(tr->store, c->base.id);
+               if (c->min && c->max) {
+                       unlock_column(tr->store, c->base.id);
+                       return 1;
+               }
+               _DELETE(c->min);
+               _DELETE(c->max);
+               if ((b = temp_descriptor(d->cs.st == ST_DICT ? d->cs.ebid : 
d->cs.bid))) {
+                       BATiter bi = bat_iterator(b);
+                       if (bi.minpos != BUN_NONE && bi.maxpos != BUN_NONE) {
+                               void *nmin = BUNtail(bi, bi.minpos), *nmax = 
BUNtail(bi, bi.maxpos);
+                               size_t minlen = ATOMlen(bi.type, nmin), maxlen 
= ATOMlen(bi.type, nmax);
+
+                               if (!(c->min = GDKmalloc(minlen)) || !(c->max = 
GDKmalloc(maxlen))) {
+                                       _DELETE(c->min);
+                                       _DELETE(c->max);
+                               } else {
+                                       memcpy(c->min, nmin, minlen);
+                                       memcpy(c->max, nmax, maxlen);
+                                       ok = 1;
+                               }
+                       }
+                       bat_iterator_end(&bi);
+                       bat_destroy(b);
+               }
                unlock_column(tr->store, c->base.id);
-               return 1;
        }
-       _DELETE(c->min);
-       _DELETE(c->max);
-       if ((d = ATOMIC_PTR_GET(&c->data)) && (b = temp_descriptor(d->cs.bid))) 
{
-               BATiter bi = bat_iterator(b);
-               if (bi.minpos != BUN_NONE && bi.maxpos != BUN_NONE) {
-                       void *nmin = BUNtail(bi, bi.minpos), *nmax = 
BUNtail(bi, bi.maxpos);
-                       size_t minlen = ATOMlen(bi.type, nmin), maxlen = 
ATOMlen(bi.type, nmax);
-
-                       if (!(c->min = GDKmalloc(minlen)) || !(c->max = 
GDKmalloc(maxlen))) {
-                               _DELETE(c->min);
-                               _DELETE(c->max);
-                       } else {
-                               memcpy(c->min, nmin, minlen);
-                               memcpy(c->max, nmax, maxlen);
-                               ok = 1;
-                       }
-               }
-               bat_iterator_end(&bi);
-               bat_destroy(b);
-       }
-       unlock_column(tr->store, c->base.id);
        return ok;
 }
 
diff --git a/sql/storage/store.c b/sql/storage/store.c
--- a/sql/storage/store.c
+++ b/sql/storage/store.c
@@ -6072,6 +6072,8 @@ sql_trans_alter_access(sql_trans *tr, sq
                        return res;
                t = dup;
                t->access = access;
+               if (!isNew(t) && isGlobal(t) && !isGlobalTemp(t) && (res = 
sql_trans_add_dependency(tr, t->base.id, dml)))
+                       return res;
                if ((res = store_reset_sql_functions(tr, t->base.id))) /* reset 
sql functions depending on the table */
                        return res;
        }
@@ -6137,6 +6139,8 @@ sql_trans_alter_storage(sql_trans *tr, s
                dup->storage_type = NULL;
                if (storage)
                        dup->storage_type = SA_STRDUP(tr->sa, storage);
+               if (!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 */
                        return res;
        }
diff --git a/sql/test/dict/Tests/dict02.SQL.py 
b/sql/test/dict/Tests/dict02.SQL.py
--- a/sql/test/dict/Tests/dict02.SQL.py
+++ b/sql/test/dict/Tests/dict02.SQL.py
@@ -29,3 +29,30 @@ with SQLTestCase() as cli:
     DROP TABLE mct00;
     DROP PROCEDURE "sys"."dict_compress";
     COMMIT;""").assertSucceeded()
+
+# if one transaction compresses a column, disallow concurrent 
inserts/updates/deletes on the table
+with SQLTestCase() as mdb1:
+    with SQLTestCase() as mdb2:
+        mdb1.connect(username="monetdb", password="monetdb")
+        mdb2.connect(username="monetdb", password="monetdb")
+
+        mdb1.execute("""
+        START TRANSACTION;
+        create table t0(c0 int);
+        insert into t0 values (1),(2),(3);
+        create procedure "sys"."dict_compress"(sname string, tname string, 
cname string, ordered_values bool) external name "dict"."compress";
+        COMMIT;""").assertSucceeded()
+        mdb1.execute('start transaction;').assertSucceeded()
+        mdb2.execute('start transaction;').assertSucceeded()
+        mdb1.execute('call 
"sys"."dict_compress"(\'sys\',\'t0\',\'c0\',false);').assertSucceeded()
+        mdb2.execute("insert into t0 values (4),(5),(6);").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 c0 from 
t0;').assertSucceeded().assertDataResultMatch([(1,),(2,),(3,)])
+        mdb2.execute('select c0 from 
t0;').assertSucceeded().assertDataResultMatch([(1,),(2,),(3,)])
+
+        mdb1.execute("""
+        START TRANSACTION;
+        drop table t0;
+        drop procedure "sys"."dict_compress";
+        COMMIT;""").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
@@ -200,3 +200,18 @@ with SQLTestCase() as mdb1:
         mdb1.execute('drop function otherfunc;').assertSucceeded()
         mdb1.execute('drop view otherview;').assertSucceeded()
         mdb1.execute('commit;').assertSucceeded()
+
+        # If one transaction changes read access of a table, disallow 
concurrent dml
+        mdb1.execute('start transaction;').assertSucceeded()
+        mdb1.execute('create table t0(c0 int);').assertSucceeded()
+        mdb1.execute('insert into t0 values (1),(2),(3);').assertSucceeded()
+        mdb1.execute('commit;').assertSucceeded()
+        mdb1.execute('start transaction;').assertSucceeded()
+        mdb2.execute('start transaction;').assertSucceeded()
+        mdb1.execute('alter table t0 set read only;').assertSucceeded()
+        mdb2.execute("insert into t0 values (4),(5),(6);").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 c0 from 
t0;').assertSucceeded().assertDataResultMatch([(1,),(2,),(3,)])
+        mdb2.execute('select c0 from 
t0;').assertSucceeded().assertDataResultMatch([(1,),(2,),(3,)])
+        mdb1.execute('drop table t0;').assertSucceeded()
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to