Changeset: d54e331f8b06 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/d54e331f8b06
Modified Files:
sql/server/rel_select.c
sql/test/SQLancer/Tests/sqlancer08.test
Branch: Aug2024
Log Message:
Optimize precision and scale when casting to decimal.
diffs (71 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
@@ -4043,6 +4043,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)
{
@@ -4055,6 +4057,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);
@@ -4065,10 +4068,34 @@ 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_CHAR || et->type->eclass == EC_DEC)
+ tpe = sql_bind_subtype(sql->sa, "decimal", et->digits,
et->scale);
+ else if (et->type->eclass == EC_STRING) {
+ 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/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
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]