Changeset: 7cb35bed76d8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/7cb35bed76d8
Modified Files:
        sql/server/rel_select.c
        testing/Mtest.py.in
Branch: default
Log Message:

Merge with Aug2024 branch.


diffs (111 lines):

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
@@ -4009,6 +4009,8 @@ rel_case_exp(sql_query *query, sql_rel *
        }
 }
 
+#define E_ATOM_STRING(e) ((atom*)(e)->l)->data.val.sval
+
 static sql_exp *
 rel_cast(sql_query *query, sql_rel **rel, symbol *se, int f)
 {
@@ -4021,6 +4023,7 @@ rel_cast(sql_query *query, sql_rel **rel
 
        if (!e)
                return NULL;
+
        /* strings may need to be truncated */
        if (EC_VARCHAR(tpe->type->eclass) && tpe->digits > 0) {
                sql_subtype *et = exp_subtype(e);
@@ -4031,10 +4034,37 @@ rel_cast(sql_query *query, sql_rel **rel
                                e = exp_binop(sql->sa, e, exp_atom_int(sql->sa, 
tpe->digits), c);
                }
        }
+
+       if (e->type == e_atom && tpe->type->eclass == EC_DEC) {
+               sql_subtype *et = exp_subtype(e);
+               if (et->type->eclass == EC_NUM) {
+                       unsigned int min_precision = atom_num_digits(e->l);
+                       if (min_precision > tpe->digits)
+                               return sql_error(sql, 02, SQLSTATE(42000) 
"Precision (%d) should be at least (%d)", tpe->digits, min_precision);
+                       tpe = sql_bind_subtype(sql->sa, "decimal", 
min_precision, et->scale);
+               } else if (EC_VARCHAR(et->type->eclass)) {
+                       char *s = E_ATOM_STRING(e);
+                       unsigned int min_precision = 0, min_scale = 0;
+                       bool dot_seen = false;
+                       for (size_t i = 0; i < strlen(s); i++) {
+                               if (isdigit(s[i])) {
+                                       min_precision++;
+                                       if (dot_seen)
+                                               min_scale++;
+                               } else if (s[i] == '.') {
+                                       dot_seen = true;
+                               }
+                       }
+                       tpe = sql_bind_subtype(sql->sa, "decimal", 
min_precision, min_scale);
+               }
+       }
+
        if (e)
                e = exp_check_type(sql, tpe, rel ? *rel : NULL, e, type_cast);
+
        if (e && e->type == e_convert)
                exp_label(sql->sa, e, ++sql->label);
+
        return e;
 }
 
diff --git a/sql/server/rel_statistics_functions.c 
b/sql/server/rel_statistics_functions.c
--- a/sql/server/rel_statistics_functions.c
+++ b/sql/server/rel_statistics_functions.c
@@ -604,7 +604,7 @@ sql_day_propagate_statistics(mvc *sql, s
        set_minmax_property(sql, e, PROP_MAX, atom_int(sql->sa, 
sql_bind_localtype(localtype), nmax));
        set_minmax_property(sql, e, PROP_MIN, atom_int(sql->sa, 
sql_bind_localtype(localtype), nmin));
        prop *p = e->p = prop_create(sql->sa, PROP_NUNIQUES, e->p);
-       p->value.dval = nmax - nmin + 1;
+       p->value.dval = (dbl) (nmax - nmin + 1);
 }
 
 static void
diff --git a/sql/test/SQLancer/Tests/sqlancer08.test 
b/sql/test/SQLancer/Tests/sqlancer08.test
--- a/sql/test/SQLancer/Tests/sqlancer08.test
+++ b/sql/test/SQLancer/Tests/sqlancer08.test
@@ -170,10 +170,10 @@ 0
 statement ok
 ROLLBACK
 
-statement error 42000!Decimal (0.2.3) doesn't have format (10.2)
+statement error 42000!Decimal (0.2.3) doesn't have format (3.2)
 select cast('0.2.3' as decimal(10,2))
 
-statement error 42000!Decimal (+0..2) doesn't have format (10.2)
+statement error 42000!Decimal (+0..2) doesn't have format (2.1)
 select cast('+0..2' as decimal(10,2))
 
 statement ok
diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in
--- a/testing/Mtest.py.in
+++ b/testing/Mtest.py.in
@@ -3614,11 +3614,21 @@ def main(argv) :
         parser.add_argument('--no-html', action='store_false', 
dest='produce_html', help='do not produce HTML files')
     else:
         parser.add_argument('--produce-html', action='store_true', 
dest='produce_html', help='produce HTML files')
+    parser.add_argument('--loglevel', action='store', help='log level')
 
     parser.add_argument('tests', nargs='*', help='The positional arguments are 
either a list of one or more directories to be tested, or a single directory 
followed by a list of tests within that directory.')
     opts = parser.parse_args()
     args = opts.tests
 
+    if opts.loglevel:
+        import logging
+        try:
+            level = getattr(logging, opts.loglevel.upper())
+        except:
+            print(f'unknown log level {opts.loglevel}', file=sys.stderr)
+            sys.exit(1)
+        logging.basicConfig(level=level)
+
     recursive = opts.recursive
     global testweb
     testweb = False
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to