Changeset: 1c4f0555e35c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/1c4f0555e35c
Modified Files:
        sql/server/rel_basetable.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_select.c
        sql/server/rel_statistics.c
Branch: cleanup_types
Log Message:

try to use smallest output possible for sum


diffs (141 lines):

diff --git a/sql/server/rel_basetable.c b/sql/server/rel_basetable.c
--- a/sql/server/rel_basetable.c
+++ b/sql/server/rel_basetable.c
@@ -17,6 +17,7 @@
 #include "rel_basetable.h"
 #include "rel_remote.h"
 #include "rel_statistics.h"
+#include "rel_rewriter.h"
 #include "sql_privileges.h"
 
 #define USED_LEN(nr) ((nr+31)/32)
@@ -106,10 +107,13 @@ rel_basetable(mvc *sql, sql_table *t, co
        sql_rel *rel = rel_create(sa);
        int nrcols = ol_length(t->columns), end = nrcols + 1 + 
ol_length(t->idxs);
        rel_base_t *ba = (rel_base_t*)sa_zalloc(sa, sizeof(rel_base_t) + 
sizeof(int)*USED_LEN(end));
+       sqlstore *store = sql->session->tr->store;
 
        if(!rel || !ba)
                return NULL;
 
+       if (isTable(t) && t->s && !isDeclaredTable(t)) /* count active rows 
only */
+               set_count_prop(sql->sa, rel, 
(BUN)store->storage_api.count_col(sql->session->tr, 
ol_first_node(t->columns)->data, 10));
        assert(atname);
        if (strcmp(atname, t->base.name) != 0)
                ba->name = sa_strdup(sa, atname);
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
@@ -13,6 +13,7 @@
 #include "monetdb_config.h"
 #include "sql_relation.h"
 #include "sql_semantic.h"
+#include "sql_decimal.h"
 #include "rel_exp.h"
 #include "rel_rel.h"
 #include "rel_basetable.h"
@@ -3113,6 +3114,43 @@ exps_inout(sql_subfunc *f, list *exps)
                res->digits = digits;
 }
 
+/* for aggregates we can reduce the result types size based on real 
digits/bits used number of known input rows */
+void
+exps_largest_int(sql_subfunc *f, list *exps, lng cnt)
+{
+       if (!f->func->res || cnt == 0)
+               return;
+       sql_subtype *res = f->res->h->data;
+       if (res->type->eclass != EC_DEC && res->type->eclass != EC_NUM)
+               return;
+       bool is_decimal = (res->type->eclass == EC_DEC);
+       unsigned int digits = 0, scale = 0, mdigits = is_decimal ? 
decimal_digits(cnt) : number_bits(cnt);
+       sql_type *largesttype = NULL;
+       for(node *n = exps->h; n; n = n->next) {
+               sql_subtype *t = exp_subtype(n->data);
+
+               if (!t)
+                       continue;
+
+               largesttype = t->type;
+               if (is_decimal && t->type->eclass == EC_NUM) {
+                       unsigned int d = bits2digits(t->digits);
+                       digits = d>digits?d:digits;
+               } else if (digits < t->digits)
+                       digits = t->digits;
+               if (scale < t->scale)
+                       scale = t->scale;
+               break;
+       }
+       digits += mdigits;
+       if (largesttype && digits <= largesttype->digits)
+               sql_init_subtype(res, largesttype, digits, scale);
+       else if (is_decimal)
+               sql_find_subtype(res, res->type->base.name, digits, scale);
+       else
+               sql_find_numeric(res, 1, digits);
+}
+
 #define is_addition(fname) (strcmp(fname, "sql_add") == 0)
 #define is_subtraction(fname) (strcmp(fname, "sql_sub") == 0)
 void
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
@@ -210,6 +210,7 @@ extern void exps_sum_scales(sql_subfunc 
 extern sql_exp *exps_scale_algebra(mvc *sql, sql_subfunc *f, sql_rel *rel, 
list *exps);
 extern void exps_digits_add(sql_subfunc *f, list *exps);
 extern void exps_inout(sql_subfunc *f, list *exps);
+extern void exps_largest_int(sql_subfunc *f, list *exps, lng cnt);
 
 extern int exp_aggr_is_count(sql_exp *e);
 extern list *check_distinct_exp_names(mvc *sql, list *exps);
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
@@ -416,6 +416,23 @@ exp_fix_scale(mvc *sql, sql_subtype *ct,
        return e;
 }
 
+static lng
+rel_get_count(sql_rel *rel)
+{
+       if (!rel)
+               return 0;
+       prop *p = NULL;
+       if (rel->p && (p = find_prop(rel->p, PROP_COUNT)) != NULL)
+               return p->value.lval;
+       else if(rel->l) {
+               if (is_select(rel->op) || is_project(rel->op))
+                       return rel_get_count(rel->l);
+       }
+       return 0;
+}
+
+#define is_sum_aggr(f) (f->type == F_AGGR && strcmp(f->base.name, "sum") == 0)
+
 list *
 check_arguments_and_find_largest_any_type(mvc *sql, sql_rel *rel, list *exps, 
sql_subfunc *sf, int maybe_zero_or_one, bool internal)
 {
@@ -507,7 +524,9 @@ check_arguments_and_find_largest_any_typ
                exps_digits_add(sf, nexps);
        } else if (sf->func->fix_scale == INOUT) {
                exps_inout(sf, nexps);
-       }
+       } else if (is_sum_aggr(sf->func))
+               exps_largest_int(sf, nexps, rel_get_count(rel));
+
        /* dirty hack */
        if (sf->func->type != F_PROC && sf->func->type != F_UNION && 
sf->func->type != F_LOADER && res) {
                if (res->type->eclass == EC_ANY && atp)
diff --git a/sql/server/rel_statistics.c b/sql/server/rel_statistics.c
--- a/sql/server/rel_statistics.c
+++ b/sql/server/rel_statistics.c
@@ -270,6 +270,8 @@ sql_column_get_statistics(mvc *sql, sql_
        }
        if (digits)
                et->digits = digits;
+       if (et->type->eclass == EC_DEC && et->digits <= et->scale)
+               et->digits = et->scale + 1;
 }
 
 static void
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to