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