Changeset: e712467717fe for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=e712467717fe
Modified Files:
        sql/backends/monet5/sql_gencode.c
        sql/benchmarks/tpch/LOCKED/Tests/01-22.stable.out
        sql/benchmarks/tpch/Tests/01-22.stable.out
        sql/server/rel_bin.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/sql_parser.y
        sql/server/sql_psm.c
Branch: Aug2011
Log Message:

Merge with Apr2011 branch.


diffs (truncated from 458 to 300 lines):

diff --git a/sql/benchmarks/tpch/LOCKED/Tests/01-22.stable.out 
b/sql/benchmarks/tpch/LOCKED/Tests/01-22.stable.out
--- a/sql/benchmarks/tpch/LOCKED/Tests/01-22.stable.out
+++ b/sql/benchmarks/tpch/LOCKED/Tests/01-22.stable.out
@@ -480,7 +480,8 @@
 % promo_revenue # name
 % decimal # type
 % 21 # length
-[ 15.4865      ]
+[ 15.48        ]
+#select * from optimizer_stats() stats;
 % .stats,      .stats # table_name
 % rewrite,     count # name
 % clob,        int # type
diff --git a/sql/benchmarks/tpch/LOCKED/Tests/14.stable.out 
b/sql/benchmarks/tpch/LOCKED/Tests/14.stable.out
--- a/sql/benchmarks/tpch/LOCKED/Tests/14.stable.out
+++ b/sql/benchmarks/tpch/LOCKED/Tests/14.stable.out
@@ -23,7 +23,8 @@
 % promo_revenue # name
 % decimal # type
 % 21 # length
-[ 15.4865      ]
+[ 15.48        ]
+#select * from optimizer_stats() stats;
 % .stats,      .stats # table_name
 % rewrite,     count # name
 % clob,        int # type
diff --git a/sql/benchmarks/tpch/Tests/01-22.stable.out 
b/sql/benchmarks/tpch/Tests/01-22.stable.out
--- a/sql/benchmarks/tpch/Tests/01-22.stable.out
+++ b/sql/benchmarks/tpch/Tests/01-22.stable.out
@@ -480,7 +480,8 @@
 % promo_revenue # name
 % decimal # type
 % 21 # length
-[ 15.4865      ]
+[ 15.48        ]
+#select * from optimizer_stats() stats;
 % .stats,      .stats # table_name
 % rewrite,     count # name
 % clob,        int # type
diff --git a/sql/benchmarks/tpch/Tests/14.stable.out 
b/sql/benchmarks/tpch/Tests/14.stable.out
--- a/sql/benchmarks/tpch/Tests/14.stable.out
+++ b/sql/benchmarks/tpch/Tests/14.stable.out
@@ -23,7 +23,8 @@
 % promo_revenue # name
 % decimal # type
 % 21 # length
-[ 15.4865      ]
+[ 15.48        ]
+#select * from optimizer_stats() stats;
 % .stats,      .stats # table_name
 % rewrite,     count # name
 % clob,        int # type
diff --git a/sql/rel.txt b/sql/rel.txt
--- a/sql/rel.txt
+++ b/sql/rel.txt
@@ -102,8 +102,11 @@
                        cmp_notlike = 6,
                        cmp_like = 7,
                        cmp_all = 8,            cross product
-                       cmp_or = 9,             or handling 
-                       cmp_in = 10,            in list handling                
+
+                       cmp_or = 9,             or handling  
+                                               ->l/r are both lists
+
+                       cmp_in = 10,            in list handling 
                        cmp_notin = 11          not in list handling
 
                                                cmp_in/cmp_notin
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
@@ -230,6 +230,21 @@
        return e;
 }
 
+atom *
+exp_value(sql_exp *e, atom **args, int maxarg)
+{
+       if (!e || e->type != e_atom)
+               return NULL; 
+       if (e->l) {        /* literal */
+               return e->l;
+       } else if (e->r) { /* param (ie not set) */
+               return NULL; 
+       } else if (e->flag < maxarg) {
+               return args[e->flag]; 
+       }
+       return NULL; 
+}
+
 sql_exp * 
 exp_param(sql_allocator *sa, char *name, sql_subtype *tpe, int frame) 
 {
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
@@ -56,6 +56,7 @@
 extern sql_exp * exp_atom_ptr(sql_allocator *sa, void *s);
 extern sql_exp * exp_atom_ref(sql_allocator *sa, int i, sql_subtype *tpe);
 extern sql_exp * exp_param(sql_allocator *sa, char *name, sql_subtype *tpe, 
int frame);
+extern atom * exp_value(sql_exp *e, atom **args, int maxarg);
 extern sql_exp * exp_values(sql_allocator *sa, list *exps);
 
 extern sql_exp * exp_column(sql_allocator *sa, char *rname, char *name, 
sql_subtype *t, int card, int has_nils, int intern);
diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c
--- a/sql/server/rel_optimizer.c
+++ b/sql/server/rel_optimizer.c
@@ -4321,6 +4321,159 @@
        return rel;
 }
 
+/* 
+ * Casting decimal values on both sides of a compare expression is expensive,
+ * both in preformance (cpu cost) and memory requirements (need for large 
+ * types). 
+ */
+
+static int
+reduce_scale(atom *a)
+{
+       if (a->data.vtype == TYPE_lng) {
+               lng v = a->data.val.lval;
+               int i = 0;
+
+               while( (v/10)*10 == v ) {
+                       i++;
+                       v /= 10;
+               }
+               a->data.val.lval = v;
+               return i;
+       }
+       if (a->data.vtype == TYPE_int) {
+               int v = a->data.val.ival;
+               int i = 0;
+
+               while( (v/10)*10 == v ) {
+                       i++;
+                       v /= 10;
+               }
+               a->data.val.lval = v;
+               return i;
+       }
+       if (a->data.vtype == TYPE_sht) {
+               sht v = a->data.val.shval;
+               int i = 0;
+
+               while( (v/10)*10 == v ) {
+                       i++;
+                       v /= 10;
+               }
+               a->data.val.lval = v;
+               return i;
+       }
+       return 0;
+}
+
+static sql_rel *
+rel_project_reduce_casts(int *changes, mvc *sql, sql_rel *rel) 
+{
+       if (is_project(rel->op) && list_length(rel->exps)) {
+               list *exps = rel->exps;
+               node *n;
+
+               for (n=exps->h; n; n = n->next) {
+                       sql_exp *e = n->data;
+
+                       if (e && e->type == e_func) {
+                               sql_subfunc *f = e->f;
+
+                               if (!f->func->s && !strcmp(f->func->base.name, 
"sql_mul") && f->res.scale > 0) {
+                                       list *args = e->l;
+                                       sql_exp *h = args->h->data;
+                                       sql_exp *t = args->t->data;
+                                       atom *a;
+
+                                       if ((is_atom(h->type) && (a = 
exp_value(h, sql->args, sql->argc)) != NULL) ||
+                                           (is_atom(t->type) && (a = 
exp_value(t, sql->args, sql->argc)) != NULL)) {
+                                               int rs = reduce_scale(a);
+
+                                               f->res.scale -= rs; 
+                                               (*changes)++;
+                                       }
+                               }
+                       }
+               }
+       }
+       return rel;
+}
+
+static sql_rel *
+rel_reduce_casts(int *changes, mvc *sql, sql_rel *rel) 
+{
+       *changes = 0; 
+
+       (void)sql;
+       if ((is_join(rel->op) || is_semi(rel->op) || is_select(rel->op)) && 
+                       rel->exps && list_length(rel->exps)) {
+               list *exps = rel->exps;
+               node *n;
+
+               for (n=exps->h; n; n = n->next) {
+                       sql_exp *e = n->data;
+                       sql_exp *le = e->l;
+                       sql_exp *re = e->r;
+       
+                       /* handle the and's in the or lists */
+                       if (e->type != e_cmp || 
+                          (e->flag != cmp_lt && e->flag != cmp_gt)) 
+                               continue;
+                       /* rewrite e if left or right is cast */
+                       if (le->type == e_convert || re->type == e_convert) {
+                               sql_rel *l = rel->l, *r = rel->r;
+
+                               /* if convert on left then find
+                                * mul or div on right which increased
+                                * scale!
+                                *
+                                * TODO handle select case
+                                */
+                               (void)l;
+                               if (le->type == e_convert && re->type == 
e_column && r && is_project(r->op)) {
+                                       sql_exp *nre = rel_find_exp(r, re);
+                                       sql_subtype *tt = exp_totype(le);
+                                       sql_subtype *ft = exp_fromtype(le);
+
+                                       if (nre && nre->type == e_func) {
+                                               sql_subfunc *f = nre->f;
+
+                                               if (!f->func->s && 
!strcmp(f->func->base.name, "sql_mul")) {
+                                                       list *args = nre->l;
+                                                       sql_exp *ce = 
args->t->data;
+                                                       sql_subtype *fst = 
exp_subtype(args->h->data);
+                                                       atom *a;
+
+                                                       if (fst->scale == 
ft->scale &&
+                                                          (a = exp_value(ce, 
sql->args, sql->argc)) != NULL) {
+                                                               lng v = 1;
+                                                               /* multiply 
with smallest value, then scale and (round) */
+                                                               int scale = 
tt->scale - ft->scale;
+                                                               int rs = 
reduce_scale(a);
+
+                                                               scale -= rs;
+
+                                                               args = 
new_exp_list(sql->sa);
+                                                               while(scale > 
0) {
+                                                                       scale--;
+                                                                       v *= 10;
+                                                               }
+                                                               append(args, 
re);
+                                                               append(args, 
exp_atom_lng(sql->sa, v));
+                                                               f = 
find_func(sql, "scale_down", args);
+                                                               nre = 
exp_op(sql->sa, args, f);
+                                                               e = 
exp_compare(sql->sa, le->l, nre, e->flag);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       n->data = e;    
+               }
+       }
+       return rel;
+}
+
 static int
 is_identity( sql_exp *e, sql_rel *r)
 {
@@ -4620,8 +4773,12 @@
 
        if (gp.cnt[op_join] || 
            gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full] || 
-           gp.cnt[op_select]) 
+           gp.cnt[op_semi] || gp.cnt[op_anti] ||
+           gp.cnt[op_select]) {
                rel = rewrite(sql, rel, &rel_find_range, &changes);
+               rel = rel_project_reduce_casts(&changes, sql, rel);
+               rel = rewrite(sql, rel, &rel_reduce_casts, &changes);
+       }
 
        if (gp.cnt[op_union]) {
                rel = rewrite(sql, rel, &rel_merge_union, &changes); 
diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -515,7 +515,8 @@
 %left <operation> '='
 %left <operation> '&' '|' '^' LEFT_SHIFT RIGHT_SHIFT
 %left <operation> '+' '-'
-%left <operation> '*' '/' '%' 
+%left <operation> '*'
+%left <operation> '/' '%' 
 %left <operation> SUBSTRING CONCATSTRING POSITION
 %right UMINUS
 
@@ -3812,7 +3813,7 @@
                  }
                }
  |  INTNUM
-               { char *s = strip_extra_zeros(sa_strdup(SA, $1));
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to