Changeset: 7e358a6f1fa0 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7e358a6f1fa0
Modified Files:
        gdk/gdk_bbp.c
        sql/server/rel_distribute.c
        testing/sqllogictest.py
Branch: default
Log Message:

Merged with Jul2021


diffs (truncated from 325 to 300 lines):

diff --git a/gdk/gdk_bbp.c b/gdk/gdk_bbp.c
--- a/gdk/gdk_bbp.c
+++ b/gdk/gdk_bbp.c
@@ -2899,16 +2899,24 @@ decref(bat i, bool logical, bool release
        if (lock)
                MT_lock_unset(&GDKswapLock(i));
 
-       if (swap && b != NULL) {
-               if (lrefs == 0 && (BBP_status(i) & BBPDELETED) == 0) {
-                       /* free memory (if loaded) and delete from
-                        * disk (if transient but saved) */
-                       BBPdestroy(b);
+       if (swap) {
+               if (b != NULL) {
+                       if (lrefs == 0 && (BBP_status(i) & BBPDELETED) == 0) {
+                               /* free memory (if loaded) and delete from
+                                * disk (if transient but saved) */
+                               BBPdestroy(b);
+                       } else {
+                               TRC_DEBUG(BAT_, "%s unload and free bat %d\n", 
func, i);
+                               /* free memory of transient */
+                               if (BBPfree(b) != GDK_SUCCEED)
+                                       return -1;      /* indicate failure */
+                       }
+               } else if (lrefs == 0 && (BBP_status(i) & BBPDELETED) == 0) {
+                       if ((b = BBP_desc(i)) != NULL)
+                               BATdelete(b);
+                       BBPclear(i, true);
                } else {
-                       TRC_DEBUG(BAT_, "%s unload and free bat %d\n", func, i);
-                       /* free memory of transient */
-                       if (BBPfree(b) != GDK_SUCCEED)
-                               return -1;      /* indicate failure */
+                       BBP_status_off(i, BBPUNLOADING);
                }
        }
        if (tp)
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -283,7 +283,13 @@ typedef struct relation {
         outer:1,       /* used as outer (ungrouped) */
         grouped:1,     /* groupby processed all the group by exps */
         single:1,
-        used:2;        /* used by rewriters at rel_unnest and rel_dce, so a 
relation is not modified twice */
+       /*
+        * Used by rewriters at rel_unnest, rel_optimizer and rel_distribute so 
a relation is not modified twice
+        * The first two bits are used by rel_unnest modifiers and always reset 
after.
+        * The first bit is also used by rel_dce and rel_merge_select_rse 
optimizers.
+        * The third bit is used by rel_remote_func only and it's not reset.
+        */
+        used:3;
        void *p;        /* properties for the optimizer, distribution */
 } sql_rel;
 
diff --git a/sql/server/rel_distribute.c b/sql/server/rel_distribute.c
--- a/sql/server/rel_distribute.c
+++ b/sql/server/rel_distribute.c
@@ -161,7 +161,8 @@ replica_rewrite(visitor *v, sql_table *t
 static sql_rel *
 replica(visitor *v, sql_rel *rel)
 {
-       if (rel_is_ref(rel)) {
+       /* for merge statement join, ignore the multiple references */
+       if (rel_is_ref(rel) && !(rel->flag&MERGE_LEFT)) {
                if (has_remote_or_replica(rel)) {
                        sql_rel *nrel = rel_copy(v->sql, rel, 1);
 
@@ -192,7 +193,8 @@ distribute(visitor *v, sql_rel *rel)
        sql_rel *l = rel->l, *r = rel->r;
        prop *p, *pl, *pr;
 
-       if (rel_is_ref(rel)) {
+       /* for merge statement join, ignore the multiple references */
+       if (rel_is_ref(rel) && !(rel->flag&MERGE_LEFT)) {
                if (has_remote_or_replica(rel)) {
                        sql_rel *nrel = rel_copy(v->sql, rel, 1);
 
@@ -274,6 +276,9 @@ distribute(visitor *v, sql_rel *rel)
                                return NULL;
                }
 
+               if (rel->flag&MERGE_LEFT) /* search for any remote tables but 
don't propagate over to this relation */
+                       return rel;
+
                if (l && (pl = find_prop(l->p, PROP_REMOTE)) != NULL &&
                        r && (pr = find_prop(r->p, PROP_REMOTE)) != NULL &&
                        strcmp(pl->value, pr->value) == 0) {
@@ -330,6 +335,12 @@ rel_remote_func(visitor *v, sql_rel *rel
 {
        (void) v;
 
+       if (rel_is_ref(rel)) { /* Don't modify the same relation twice */
+               int rused = 1 << 2;
+               if (rel->used & rused)
+                       return rel;
+               rel->used |= rused;
+       }
        if (find_prop(rel->p, PROP_REMOTE) != NULL) {
                list *exps = rel_projections(v->sql, rel, NULL, 1, 1);
                rel = rel_relational_func(v->sql->sa, rel, exps);
diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -936,7 +936,8 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
        char *tname = NULL, *cname = NULL, *var_cname = NULL, *e, *b = r + 
*pos, *st;
        sql_exp *exp = NULL;
        list *exps = NULL;
-       sql_subtype *tpe;
+       sql_type *t = NULL;
+       sql_subtype tpe;
 
        quote = (r[*pos] == '"');
        b += quote;
@@ -1060,8 +1061,11 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
                                (*pos)++;
                        }
                        convertIdent(tname);
-                       if (!(tpe = sql_bind_subtype(sql->sa, tname, d, s)))
-                               return sql_error(sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SQL type %s(%d, %d) not found\n", tname, d, s);
+                       if (!sql_find_subtype(&tpe, tname, d, s)) {
+                               if (!(t = mvc_bind_type(sql, tname))) /* try an 
external type */
+                                       return sql_error(sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SQL type %s(%d, %d) not found\n", tname, d, s);
+                               sql_init_subtype(&tpe, t, d, s);
+                       }
                        skipWS(r, pos);
                        *e = old;
                        if (r[*pos] == '[') { /* convert */
@@ -1073,13 +1077,13 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
                                        return sql_error(sql, -1, 
SQLSTATE(42000) "Convert: missing ']'\n");
                                (*pos)++;
                                skipWS(r, pos);
-                               exp = exp_convert(sql->sa, exp, 
exp_subtype(exp), tpe);
+                               exp = exp_convert(sql->sa, exp, 
exp_subtype(exp), &tpe);
                        } else {
                                st = readString(r,pos);
                                if (st && strcmp(st, "NULL") == 0)
-                                       exp = exp_atom(sql->sa, 
atom_general(sql->sa, tpe, NULL));
+                                       exp = exp_atom(sql->sa, 
atom_general(sql->sa, &tpe, NULL));
                                else
-                                       exp = exp_atom(sql->sa, 
atom_general(sql->sa, tpe, st));
+                                       exp = exp_atom(sql->sa, 
atom_general(sql->sa, &tpe, st));
                                skipWS(r, pos);
                        }
                }
@@ -1088,13 +1092,16 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
                *e = 0;
                tname = b;
                convertIdent(tname);
-               if (!(tpe = sql_bind_subtype(sql->sa, tname, 0, 0)))
-                       return sql_error(sql, ERR_NOTFOUND, SQLSTATE(42000) 
"SQL type %s not found\n", tname);
+               if (!sql_find_subtype(&tpe, tname, 0, 0)) {
+                       if (!(t = mvc_bind_type(sql, tname))) /* try an 
external type */
+                               return sql_error(sql, ERR_NOTFOUND, 
SQLSTATE(42000) "SQL type %s not found\n", tname);
+                       sql_init_subtype(&tpe, t, 0, 0);
+               }
                st = readString(r,pos);
                if (st && strcmp(st, "NULL") == 0)
-                       exp = exp_atom(sql->sa, atom_general(sql->sa, tpe, 
NULL));
+                       exp = exp_atom(sql->sa, atom_general(sql->sa, &tpe, 
NULL));
                else
-                       exp = exp_atom(sql->sa, atom_general(sql->sa, tpe, st));
+                       exp = exp_atom(sql->sa, atom_general(sql->sa, &tpe, 
st));
                skipWS(r, pos);
                break;
        default:
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
@@ -4001,11 +4001,13 @@ temp_del_tab(sql_trans *tr, sql_table *t
 {
        ulng tid = tr->tid;
        lock_table(tr->store, t->base.id);
+  table_retry:
        for (storage *d = ATOMIC_PTR_GET(&t->data), *p = NULL, *n = NULL; d; d 
= n) {
                n = d->next;
                if (d->cs.ts == tid) {
                        if (p == NULL) {
-                               ATOMIC_PTR_SET(&t->data, n);
+                               if (!ATOMIC_PTR_CAS(&t->data, (void **) &d, n))
+                                       goto table_retry;
                        } else {
                                p->next = n;
                        }
@@ -4019,11 +4021,13 @@ temp_del_tab(sql_trans *tr, sql_table *t
        for (node *nd = t->columns->l->h; nd; nd = nd->next) {
                sql_column *c = nd->data;
                lock_column(tr->store, c->base.id);
+         column_retry:
                for (sql_delta *d = ATOMIC_PTR_GET(&c->data), *p = NULL, *n = 
NULL; d; d = n) {
                        n = d->next;
                        if (d->cs.ts == tid) {
                                if (p == NULL) {
-                                       ATOMIC_PTR_SET(&c->data, n);
+                                       if (!ATOMIC_PTR_CAS(&c->data, (void **) 
&d, n))
+                                               goto column_retry;
                                } else {
                                        p->next = n;
                                }
diff --git a/sql/test/SQLancer/Tests/All b/sql/test/SQLancer/Tests/All
--- a/sql/test/SQLancer/Tests/All
+++ b/sql/test/SQLancer/Tests/All
@@ -16,3 +16,4 @@ sqlancer15
 sqlancer16
 sqlancer17
 sqlancer18
+sqlancer19
diff --git a/sql/test/SQLancer/Tests/sqlancer19.SQL.py 
b/sql/test/SQLancer/Tests/sqlancer19.SQL.py
new file mode 100644
--- /dev/null
+++ b/sql/test/SQLancer/Tests/sqlancer19.SQL.py
@@ -0,0 +1,40 @@
+import os
+
+from MonetDBtesting.sqltest import SQLTestCase
+
+port = os.environ['MAPIPORT']
+db = os.environ['TSTDB']
+
+with SQLTestCase() as cli:
+    cli.connect(username="monetdb", password="monetdb")
+    cli.execute("""
+    START TRANSACTION;
+    CREATE TABLE "t0" ("c0" INTERVAL SECOND NOT NULL, "c1" JSON);
+    INSERT INTO "t0" VALUES (INTERVAL '9' SECOND, '""');
+
+    CREATE TABLE "t1" ("c0" BINARY LARGE OBJECT,"c1" BIGINT);
+    INSERT INTO "t1" VALUES (NULL, 1),(NULL, 6),(NULL, 0),(BINARY LARGE OBJECT 
'50', NULL),(BINARY LARGE OBJECT 'ACBC2EDEF0', NULL),
+    (BINARY LARGE OBJECT '65', NULL),(BINARY LARGE OBJECT 'EF43C0', 
NULL),(BINARY LARGE OBJECT '90', NULL),(BINARY LARGE OBJECT '', NULL);
+
+    CREATE TABLE "t3" ("c0" BIGINT,"c1" INTERVAL MONTH);
+    INSERT INTO "t3" VALUES (1, INTERVAL '9' MONTH),(5, INTERVAL '6' 
MONTH),(5, NULL),(7, NULL),(2, INTERVAL '1' MONTH),(2, INTERVAL '1' MONTH);
+    COMMIT;
+
+    START TRANSACTION;
+    CREATE REMOTE TABLE "rt1" ("c0" BINARY LARGE OBJECT,"c1" BIGINT) ON 
'mapi:monetdb://localhost:%s/%s/sys/t1';
+    CREATE REMOTE TABLE "rt3" ("c0" BIGINT,"c1" INTERVAL MONTH) ON 
'mapi:monetdb://localhost:%s/%s/sys/t3';
+    COMMIT;""" % (port, db, port, db)).assertSucceeded()
+
+    cli.execute('SELECT json."integer"(JSON \'1\') FROM 
rt3;').assertSucceeded().assertDataResultMatch([(1,),(1,),(1,),(1,),(1,),(1,)])
+
+    cli.execute('MERGE INTO t0 USING (SELECT 1 FROM rt1) AS mergejoined(c0) ON 
TRUE WHEN NOT MATCHED THEN INSERT (c0) VALUES (INTERVAL \'5\' SECOND);') \
+        .assertSucceeded().assertRowCount(0)
+
+    cli.execute("""
+    START TRANSACTION;
+    DROP TABLE rt1;
+    DROP TABLE rt3;
+    DROP TABLE t0;
+    DROP TABLE t1;
+    DROP TABLE t3;
+    COMMIT;""").assertSucceeded()
diff --git a/testing/sqllogictest.py b/testing/sqllogictest.py
--- a/testing/sqllogictest.py
+++ b/testing/sqllogictest.py
@@ -218,12 +218,15 @@ class SQLLogic:
                        expected_err_code=None,
                        expected_err_msg=None,
                        expected_rowcount=None,
-                       conn=None):
+                       conn=None,
+                       verbose=False):
         crs = conn.cursor() if conn else self.crs
         if skipidx.search(statement) is not None:
             # skip creation of ascending or descending index
             return ['statement', 'ok']
         try:
+            if verbose:
+                print(f'Executing:\n{err_stmt or statement}')
             affected_rowcount = crs.execute(statement)
         except (pymonetdb.Error, ValueError) as e:
             msg = e.args[0]
@@ -352,10 +355,12 @@ class SQLLogic:
                     sep = '|'
                 print('', file=self.out)
 
-    def exec_query(self, query, columns, sorting, pyscript, hashlabel, 
nresult, hash, expected, conn=None) -> bool:
+    def exec_query(self, query, columns, sorting, pyscript, hashlabel, 
nresult, hash, expected, conn=None, verbose=False) -> bool:
         err = False
         crs = conn.cursor() if conn else self.crs
         try:
+            if verbose:
+                print(f'Executing:\n{query}')
             crs.execute(query)
         except (pymonetdb.Error, ValueError) as e:
             self.query_error(query, 'query failed', e.args[0])
@@ -598,7 +603,7 @@ class SQLLogic:
                 self.raise_error('invalid connection parameters definition, 
username or password missing!')
         return res
 
-    def parse(self, f, approve=None):
+    def parse(self, f, approve=None, verbose=False):
         self.approve = approve
         self.initfile(f)
         if self.language == 'sql':
@@ -659,9 +664,9 @@ class SQLLogic:
                 if not skipping:
                     if is_copyfrom_stmt(statement):
                         stmt, stmt_less_data = prepare_copyfrom_stmt(statement)
-                        result = self.exec_statement(stmt, expectok, 
err_stmt=stmt_less_data, expected_err_code=expected_err_code, 
expected_err_msg=expected_err_msg, expected_rowcount=expected_rowcount, 
conn=conn)
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to