Changeset: 15c6525a8a58 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/15c6525a8a58
Modified Files:
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_select.c
        sql/test/SQLancer/Tests/sqlancer19.SQL.py
Branch: Jul2021
Log Message:

Do a more detailed scale fix for mul, div and concat functions


diffs (214 lines):

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
@@ -1198,29 +1198,27 @@ exp_read(mvc *sql, sql_rel *lrel, sql_re
 
                                if (f && !execute_priv(sql, f->func))
                                        return sql_error(sql, -1, 
SQLSTATE(42000) "Function: no privilege to call function '%s%s%s %d'\n", tname 
? tname : "", tname ? "." : "", cname, nops);
-                               /* fix scale of mul function, other type casts 
are explicit */
-                               if (f && f->func->fix_scale == SCALE_MUL && 
list_length(exps) == 2) {
-                                       sql_arg *ares = f->func->res->h->data;
-
-                                       if (strcmp(f->func->imp, "*") == 0 && 
ares->type.type->scale == SCALE_FIX) {
-                                               sql_subtype *res = 
f->res->h->data;
-                                               sql_subtype *lt = ops->h->data;
-                                               sql_subtype *rt = 
ops->h->next->data;
+                               /* apply scale fixes if needed */
+                               if (f && f->func->fix_scale != SCALE_NONE && 
list_length(exps) == 2) {
+                                       sql_exp *l = exps->h->data;
+                                       sql_exp *r = exps->h->next->data;
+                                       sql_subtype *t1 = ops->h->data;
+                                       sql_subtype *t2 = ops->h->next->data;
 
-                                               res->digits = lt->digits;
-                                               res->scale = lt->scale + 
rt->scale;
-                                       }
-                               }
-                               /* fix scale of div function */
-                               if (f && f->func->fix_scale == SCALE_DIV && 
list_length(exps) == 2) {
-                                       sql_arg *ares = f->func->res->h->data;
-
-                                       if (strcmp(f->func->imp, "/") == 0 && 
ares->type.type->scale == SCALE_FIX) {
-                                       sql_subtype *res = f->res->h->data;
-                                               sql_subtype *lt = ops->h->data;
-                                               sql_subtype *rt = 
ops->h->next->data;
-
-                                               res->scale = lt->scale - 
rt->scale;
+                                       if (f->func->fix_scale == SCALE_DIV) {
+                                               if (!(exps->h->data = 
exp_scale_algebra(sql, f, NULL, l, r)))
+                                                       return NULL;
+                                       } else if (f->func->fix_scale == 
SCALE_MUL) {
+                                               exp_sum_scales(f, l, r);
+                                       } else if (f->func->fix_scale == 
DIGITS_ADD) {
+                                               sql_subtype *res = 
f->res->h->data;
+                                               if (t1->digits && t2->digits) {
+                                                       res->digits = 
t1->digits + t2->digits;
+                                                       if (res->digits < 
t1->digits || res->digits < t2->digits || res->digits >= (unsigned int) 
INT32_MAX)
+                                                               return 
sql_error(sql, -1, SQLSTATE(42000) "Output number of digits for %s%s%s is too 
large\n", tname ? tname : "", tname ? "." : "", cname);
+                                               } else {
+                                                       res->digits = 0;
+                                               }
                                        }
                                }
                        }
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -2839,6 +2839,50 @@ exp_flatten(mvc *sql, sql_exp *e)
        return NULL;
 }
 
+sql_exp *
+exp_scale_algebra(mvc *sql, sql_subfunc *f, sql_rel *rel, sql_exp *l, sql_exp 
*r)
+{
+       sql_subtype *lt = exp_subtype(l);
+       sql_subtype *rt = exp_subtype(r);
+
+       if (lt->type->scale == SCALE_FIX && rt->scale &&
+               strcmp(f->func->imp, "/") == 0) {
+               sql_subtype *res = f->res->h->data;
+               unsigned int scale, digits, digL, scaleL;
+               sql_subtype nlt;
+
+               /* scale fixing may require a larger type ! */
+               scaleL = (lt->scale < 3) ? 3 : lt->scale;
+               scale = scaleL;
+               scaleL += rt->scale;
+               digL = lt->digits + (scaleL - lt->scale);
+               digits = (digL > rt->digits) ? digL : rt->digits;
+
+               /* HACK alert: digits should be less than max */
+#ifdef HAVE_HGE
+               if (res->type->radix == 10 && digits > 39)
+                       digits = 39;
+               if (res->type->radix == 2 && digits > 128)
+                       digits = 128;
+#else
+               if (res->type->radix == 10 && digits > 19)
+                       digits = 19;
+               if (res->type->radix == 2 && digits > 64)
+                       digits = 64;
+#endif
+
+               sql_find_subtype(&nlt, lt->type->base.name, digL, scaleL);
+               if (nlt.digits < scaleL) {
+                   sql_error(sql, 01, SQLSTATE(42000) "Scale (%d) overflows 
type", scaleL);
+                       return NULL;
+               }
+               l = exp_check_type(sql, &nlt, rel, l, type_equal);
+
+               sql_find_subtype(res, lt->type->base.name, digits, scale);
+       }
+       return l;
+}
+
 void
 exp_sum_scales(sql_subfunc *f, sql_exp *l, sql_exp *r)
 {
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -193,6 +193,7 @@ extern int is_identity( sql_exp *e, sql_
 
 extern atom *exp_flatten(mvc *sql, sql_exp *e);
 
+extern sql_exp *exp_scale_algebra(mvc *sql, sql_subfunc *f, sql_rel *rel, 
sql_exp *l, sql_exp *r);
 extern void exp_sum_scales(sql_subfunc *f, sql_exp *l, sql_exp *r);
 
 extern int exp_aggr_is_count(sql_exp *e);
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
@@ -1369,50 +1369,6 @@ largest_numeric_type(sql_subtype *res, i
        return NULL;
 }
 
-static sql_exp *
-exp_scale_algebra(mvc *sql, sql_subfunc *f, sql_rel *rel, sql_exp *l, sql_exp 
*r)
-{
-       sql_subtype *lt = exp_subtype(l);
-       sql_subtype *rt = exp_subtype(r);
-
-       if (lt->type->scale == SCALE_FIX && rt->scale &&
-               strcmp(f->func->imp, "/") == 0) {
-               sql_subtype *res = f->res->h->data;
-               unsigned int scale, digits, digL, scaleL;
-               sql_subtype nlt;
-
-               /* scale fixing may require a larger type ! */
-               scaleL = (lt->scale < 3) ? 3 : lt->scale;
-               scale = scaleL;
-               scaleL += rt->scale;
-               digL = lt->digits + (scaleL - lt->scale);
-               digits = (digL > rt->digits) ? digL : rt->digits;
-
-               /* HACK alert: digits should be less than max */
-#ifdef HAVE_HGE
-               if (res->type->radix == 10 && digits > 39)
-                       digits = 39;
-               if (res->type->radix == 2 && digits > 128)
-                       digits = 128;
-#else
-               if (res->type->radix == 10 && digits > 19)
-                       digits = 19;
-               if (res->type->radix == 2 && digits > 64)
-                       digits = 64;
-#endif
-
-               sql_find_subtype(&nlt, lt->type->base.name, digL, scaleL);
-               if (nlt.digits < scaleL) {
-                   sql_error(sql, 01, SQLSTATE(42000) "Scale (%d) overflows 
type", scaleL);
-                       return NULL;
-               }
-               l = exp_check_type( sql, &nlt, rel, l, type_equal);
-
-               sql_find_subtype(res, lt->type->base.name, digits, scale);
-       }
-       return l;
-}
-
 int
 rel_convert_types(mvc *sql, sql_rel *ll, sql_rel *rr, sql_exp **L, sql_exp 
**R, int scale_fixing, check_type tpe)
 {
diff --git a/sql/test/SQLancer/Tests/sqlancer19.SQL.py 
b/sql/test/SQLancer/Tests/sqlancer19.SQL.py
--- a/sql/test/SQLancer/Tests/sqlancer19.SQL.py
+++ b/sql/test/SQLancer/Tests/sqlancer19.SQL.py
@@ -16,14 +16,19 @@ with SQLTestCase() as cli:
     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 "t2" ("c0" TINYINT NOT NULL,"c2" DATE);
+    INSERT INTO "t2" VALUES (-7, NULL),(0, NULL),(-11, DATE '1970-01-01'),(8, 
DATE '1970-01-01'),(5, DATE '1970-01-01'),(1, DATE '1970-01-01'),
+    (0, NULL),(1, NULL),(7, NULL),(5, 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 "rt2" ("c0" TINYINT NOT NULL,"c2" DATE) ON 
'mapi:monetdb://localhost:%s/%s/sys/t2';
     CREATE REMOTE TABLE "rt3" ("c0" BIGINT,"c1" INTERVAL MONTH) ON 
'mapi:monetdb://localhost:%s/%s/sys/t3';
-    COMMIT;""" % (port, db, port, db)).assertSucceeded()
+    COMMIT;""" % (port, db, port, db, port, db)).assertSucceeded()
 
     cli.execute("START TRANSACTION;")
     cli.execute('SELECT json."integer"(JSON \'1\') FROM 
rt3;').assertSucceeded().assertDataResultMatch([(1,),(1,),(1,),(1,),(1,),(1,)])
@@ -44,13 +49,17 @@ with SQLTestCase() as cli:
         .assertSucceeded().assertDataResultMatch([])
     cli.execute('SELECT 1 FROM (SELECT TIME \'01:00:00\' FROM rt1) va(vc1) 
WHERE greatest(va.vc1, TIME \'01:01:01\') <= TIME \'01:01:02\';') \
         
.assertSucceeded().assertDataResultMatch([(1,),(1,),(1,),(1,),(1,),(1,)])
+    cli.execute('SELECT 3 > (rt2.c0 ^ CAST(2 AS TINYINT)) * rt2.c0 FROM rt2;') 
\
+        
.assertSucceeded().assertDataResultMatch([(False,),(True,),(False,),(False,),(False,),(False,),(True,),(False,),(False,),(False,)])
     cli.execute("ROLLBACK;")
 
     cli.execute("""
     START TRANSACTION;
     DROP TABLE rt1;
+    DROP TABLE rt2;
     DROP TABLE rt3;
     DROP TABLE t0;
     DROP TABLE t1;
+    DROP TABLE t2;
     DROP TABLE t3;
     COMMIT;""").assertSucceeded()
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to