Changeset: 44a68315023f for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=44a68315023f
Modified Files:
sql/include/sql_catalog.h
sql/server/rel_select.c
sql/server/sql_semantic.c
sql/server/sql_semantic.h
sql/test/BugTracker-2012/Tests/case_evaluated_too_early.Bug-3186.stable.out
sql/test/BugTracker-2017/Tests/case.Bug-6386.stable.out
sql/test/BugTracker/Tests/groupby_with_alias.SF-1520575.stable.out.int128
sql/test/Tests/coalesce.stable.out
Branch: default
Log Message:
implement (part) of the result datatype specification (pages 505-507) of the
2011 standard.
Currently only used for case/coalesce/nullif cases
diffs (250 lines):
diff --git a/sql/include/sql_catalog.h b/sql/include/sql_catalog.h
--- a/sql/include/sql_catalog.h
+++ b/sql/include/sql_catalog.h
@@ -303,6 +303,8 @@ typedef enum sql_class {
#define EC_VARCHAR(e) (e==EC_CHAR||e==EC_STRING)
#define EC_INTERVAL(e) (e==EC_MONTH||e==EC_SEC)
#define EC_NUMBER(e)
(e==EC_POS||e==EC_NUM||EC_INTERVAL(e)||e==EC_DEC||e==EC_FLT)
+#define EC_EXACTNUM(e) (e==EC_NUM||e==EC_DEC)
+#define EC_APPNUM(e) (e==EC_FLT)
#define EC_COMPUTE(e) (e==EC_NUM||e==EC_FLT)
#define EC_BOOLEAN(e) (e==EC_BIT||e==EC_NUM||e==EC_FLT)
#define EC_TEMP_TZ(e) (e==EC_TIME_TZ||e==EC_TIMESTAMP_TZ)
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
@@ -3703,7 +3703,7 @@ rel_case(sql_query *query, sql_rel **rel
append(conds, cond);
tpe = exp_subtype(cond);
if (tpe && condtype) {
- supertype(&ctype, condtype, tpe);
+ result_datatype(&ctype, condtype, tpe);
condtype = &ctype;
} else if (tpe) {
condtype = tpe;
@@ -3714,7 +3714,7 @@ rel_case(sql_query *query, sql_rel **rel
append(results, result);
tpe = exp_subtype(result);
if (tpe && restype) {
- supertype(&rtype, restype, tpe);
+ result_datatype(&rtype, restype, tpe);
restype = &rtype;
} else if (tpe) {
restype = tpe;
@@ -3726,7 +3726,7 @@ rel_case(sql_query *query, sql_rel **rel
tpe = exp_subtype(res);
if (tpe && restype) {
- supertype(&rtype, restype, tpe);
+ result_datatype(&rtype, restype, tpe);
restype = &rtype;
} else if (tpe) {
restype = tpe;
@@ -3780,27 +3780,6 @@ rel_case(sql_query *query, sql_rel **rel
return res;
}
-#if 0
-static sql_exp *
-do_complex_case(sql_query *query, node *n, str func, sql_subtype *restype)
-{
- sql_exp *l = n->data;
-
- if (!(l = exp_check_type(query->sql, restype, NULL, l, type_equal)))
- return NULL;
-
- n = n->next;
- sql_exp *r = n->data;
- if (n->next)
- r = do_complex_case(query, n, func, restype);
- else
- r = exp_check_type(query->sql, restype, NULL, r, type_equal);
- if (!r)
- return NULL;
- return rel_binop_(query->sql, NULL, l, r, NULL, func, card_value);
-}
-#endif
-
static sql_exp *
rel_complex_case(sql_query *query, sql_rel **rel, dlist *case_args, int f, str
func)
{
@@ -3817,7 +3796,7 @@ rel_complex_case(sql_query *query, sql_r
/* all arguments should have the same type */
sql_subtype *tpe = exp_subtype(a);
if (tpe && restype) {
- supertype(&rtype, restype, tpe);
+ result_datatype(&rtype, restype, tpe);
restype = &rtype;
} else if (tpe) {
restype = tpe;
@@ -3835,7 +3814,6 @@ rel_complex_case(sql_query *query, sql_r
return NULL;
append(nargs, result);
}
- //return do_complex_case(query, args->h, func, restype);
list *types = append(append(sa_list(query->sql->sa), restype), restype);
sql_subfunc *fnc = find_func(query->sql, NULL, func,
list_length(types), F_FUNC, NULL);
return exp_op(query->sql->sa, nargs, fnc);
diff --git a/sql/server/sql_semantic.c b/sql/server/sql_semantic.c
--- a/sql/server/sql_semantic.c
+++ b/sql/server/sql_semantic.c
@@ -170,6 +170,79 @@ set_type_param(mvc *sql, sql_subtype *ty
return 0;
}
+/*
+ * Find the result_datatype for certain combinations of values
+ * (like case expressions or coumns in a result of a query expression).
+ * See standaard pages 505-507 Result of data type combinations */
+sql_subtype *
+result_datatype(sql_subtype *super, sql_subtype *l, sql_subtype *r)
+{
+ int lclass = l->type->eclass, rclass = r->type->eclass;
+ int lc=0, rc=0;
+
+ /* case a strings */
+ if (EC_VARCHAR(lclass) || EC_VARCHAR(rclass)) {
+ char *tpe = "varchar";
+ int digits = 0;
+ if (!EC_VARCHAR(lclass)) {
+ tpe = r->type->sqlname;
+ digits = (!l->digits)?0:r->digits;
+ } else if (!EC_VARCHAR(rclass)) {
+ tpe = l->type->sqlname;
+ digits = (!r->digits)?0:l->digits;
+ } else { /* both */
+ tpe = (l->type->base.id >
r->type->base.id)?l->type->sqlname:r->type->sqlname;
+ digits =
(!l->digits||!r->digits)?0:sql_max(l->digits, r->digits);
+ }
+ sql_find_subtype(super, tpe, digits, 0);
+ /* case b blob */
+ } else if ((lc=strcmp(l->type->sqlname, "blob")) == 0 ||
(rc=strcmp(r->type->sqlname, "blob")) == 0) {
+ if (!lc)
+ *super = *l;
+ else
+ *super = *r;
+ /* case c all exact numeric */
+ } else if (EC_EXACTNUM(lclass) && EC_EXACTNUM(rclass)) {
+ char *tpe = (l->type->base.id >
r->type->base.id)?l->type->sqlname:r->type->sqlname;
+ unsigned int digits = sql_max(l->digits, r->digits);
+ int scale = sql_max(l->scale, r->scale);
+ if (l->type->radix == 10 || r->type->radix == 10) {
+ digits = 0;
+ /* change to radix 10 */
+ if (l->type->radix == 2)
+ digits = bits2digits(l->type->digits);
+ if (l->type->radix == 2)
+ digits = bits2digits(r->type->digits);
+ if (l->type->radix != 10) {
+ digits = sql_max(digits, r->digits);
+ scale = r->scale;
+ } else if (r->type->radix != 10) {
+ digits = sql_max(digits, l->digits);
+ scale = l->scale;
+ }
+ }
+ sql_find_subtype(super, tpe, digits, scale);
+ /* case d approximate numeric */
+ } else if (EC_APPNUM(lclass) || EC_APPNUM(rclass)) {
+ if (!EC_APPNUM(lclass)) {
+ *super = *r;
+ } else if (!EC_APPNUM(rclass)) {
+ *super = *l;
+ } else { /* both */
+ char *tpe = (l->type->base.id >
r->type->base.id)?l->type->sqlname:r->type->sqlname;
+ int digits = sql_max(l->digits, r->digits); /*
bits precision */
+ sql_find_subtype(super, tpe, digits, 0);
+ }
+ /* now its getting serious, ie e any 'case e' datetime data type */
+ /* 'case f' interval types */
+ /* 'case g' boolean */
+ /* 'case h-l' compounds like row (tuple), etc */
+ } else {
+ return supertype(super, l, r);
+ }
+ return super;
+}
+
sql_subtype *
supertype(sql_subtype *super, sql_subtype *r, sql_subtype *i)
{
diff --git a/sql/server/sql_semantic.h b/sql/server/sql_semantic.h
--- a/sql/server/sql_semantic.h
+++ b/sql/server/sql_semantic.h
@@ -28,6 +28,7 @@ extern char *qname_schema_object(dlist *
extern char *qname_catalog(dlist *qname);
#define qname_module(qname) qname_schema(qname)
+extern sql_subtype *result_datatype(sql_subtype *super, sql_subtype *l,
sql_subtype *r);
extern sql_subtype *supertype(sql_subtype *super, sql_subtype *r, sql_subtype
*i);
typedef enum {
diff --git
a/sql/test/BugTracker-2012/Tests/case_evaluated_too_early.Bug-3186.stable.out
b/sql/test/BugTracker-2012/Tests/case_evaluated_too_early.Bug-3186.stable.out
---
a/sql/test/BugTracker-2012/Tests/case_evaluated_too_early.Bug-3186.stable.out
+++
b/sql/test/BugTracker-2012/Tests/case_evaluated_too_early.Bug-3186.stable.out
@@ -33,7 +33,7 @@ stdout of test 'case_evaluated_too_early
% .%3 # table_name
% %3 # name
% decimal # type
-% 4 # length
+% 3 # length
[ -10 ]
# 17:10:20 >
diff --git a/sql/test/BugTracker-2017/Tests/case.Bug-6386.stable.out
b/sql/test/BugTracker-2017/Tests/case.Bug-6386.stable.out
--- a/sql/test/BugTracker-2017/Tests/case.Bug-6386.stable.out
+++ b/sql/test/BugTracker-2017/Tests/case.Bug-6386.stable.out
@@ -27,7 +27,7 @@ stdout of test 'case.Bug-6386` in direct
% . # table_name
% t1 # name
% decimal # type
-% 18 # length
+% 40 # length
[ 1.0000000000000 ]
[ 60.3281000000000 ]
[ 0.0000000000000 ]
diff --git
a/sql/test/BugTracker/Tests/groupby_with_alias.SF-1520575.stable.out.int128
b/sql/test/BugTracker/Tests/groupby_with_alias.SF-1520575.stable.out.int128
--- a/sql/test/BugTracker/Tests/groupby_with_alias.SF-1520575.stable.out.int128
+++ b/sql/test/BugTracker/Tests/groupby_with_alias.SF-1520575.stable.out.int128
@@ -35,6 +35,7 @@ stdout of test 'groupby_with_alias.SF-15
% bug_alias, %1 # name
% varchar, hugeint # type
% 0, 1 # length
+#ROLLBACK;
# 11:54:20 >
# 11:54:20 > Done.
diff --git a/sql/test/Tests/coalesce.stable.out
b/sql/test/Tests/coalesce.stable.out
--- a/sql/test/Tests/coalesce.stable.out
+++ b/sql/test/Tests/coalesce.stable.out
@@ -80,8 +80,8 @@ stdout of test 'coalesce` in directory '
#select id, coalesce(name, age, 'unknown') from coalescetest;
% sys.coalescetest, .%1 # table_name
% id, %1 # name
-% int, char # type
-% 1, 10 # length
+% int, varchar # type
+% 1, 7 # length
[ 1, "a" ]
[ 2, "26" ]
[ 3, "c" ]
@@ -103,6 +103,19 @@ stdout of test 'coalesce` in directory '
% int, varchar, int # type
% 1, 0, 2 # length
[ 2, NULL, 26 ]
+#insert into coalescetest(id,name) values (3,'hello this is a test');
+[ 1 ]
+#select id, coalesce(name, age, 'unknown') from coalescetest; --the output
type should be char(20)
+% sys.coalescetest, .%1 # table_name
+% id, %1 # name
+% int, varchar # type
+% 1, 20 # length
+[ 1, "a" ]
+[ 2, "26" ]
+[ 3, "c" ]
+[ 4, "unknown" ]
+[ 3, "hello this is a test" ]
+#drop table coalescetest;
# 15:56:24 >
# 15:56:24 > Done.
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list