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