Changeset: a0e687e83898 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=a0e687e83898
Modified Files:
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_select.c
        sql/test/miscellaneous/Tests/simple_plans.sql
        sql/test/miscellaneous/Tests/simple_plans.stable.out
Branch: Jun2020
Log Message:

Performance fix, when attempting to add an order by column expression, test 
first if it exists on the list of projections. If so, return a reference to the 
matched projection


diffs (121 lines):

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
@@ -1311,6 +1311,19 @@ exp_match_exp( sql_exp *e1, sql_exp *e2)
        return 0;
 }
 
+sql_exp *
+exps_any_match(list *l, sql_exp *e)
+{
+       if (!l)
+               return NULL;
+       for (node *n = l->h; n ; n = n->next) {
+               sql_exp *ne = (sql_exp *) n->data;
+               if (exp_match_exp(ne, e))
+                       return ne;
+       }
+       return NULL;
+}
+
 static int
 exps_are_joins( list *l )
 {
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
@@ -131,6 +131,7 @@ extern int exp_refers( sql_exp *p, sql_e
 extern int exp_match( sql_exp *e1, sql_exp *e2);
 extern sql_exp* exps_find_exp( list *l, sql_exp *e);
 extern int exp_match_exp( sql_exp *e1, sql_exp *e2);
+extern sql_exp* exps_any_match(list *l, sql_exp *e);
 /* match just the column (cmp equality) expressions */
 extern int exp_match_col_exps( sql_exp *e, list *l);
 extern int exps_match_col_exps( sql_exp *e1, sql_exp *e2);
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
@@ -4471,7 +4471,7 @@ rel_order_by_column_exp(sql_query *query
 {
        mvc *sql = query->sql;
        sql_rel *r = *R, *p = NULL;
-       sql_exp *e = NULL;
+       sql_exp *e = NULL, *found = NULL;
        exp_kind ek = {type_value, card_column, FALSE};
 
        if (!r)
@@ -4489,15 +4489,19 @@ rel_order_by_column_exp(sql_query *query
        else if (r)
                p->l = r;
        if (e && p) {
-               e = rel_project_add_exp(sql, p, e);
-               for (node *n = p->exps->h ; n ; n = n->next) {
-                       sql_exp *ee = n->data;
-
-                       if (ee->card > r->card) {
-                               if (exp_name(ee))
-                                       return sql_error(sql, ERR_GROUPBY, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in query results 
without an aggregate function", exp_name(ee));
-                               else
-                                       return sql_error(sql, ERR_GROUPBY, 
SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query results 
without an aggregate function");
+               if (is_project(p->op) && (found = exps_any_match(p->exps, e))) 
{ /* if one of the projections matches, return a reference to it */
+                       e = exp_ref(sql, found);
+               } else {
+                       e = rel_project_add_exp(sql, p, e);
+                       for (node *n = p->exps->h ; n ; n = n->next) {
+                               sql_exp *ee = n->data;
+
+                               if (ee->card > r->card) {
+                                       if (exp_name(ee))
+                                               return sql_error(sql, 
ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column '%s' in 
query results without an aggregate function", exp_name(ee));
+                                       else
+                                               return sql_error(sql, 
ERR_GROUPBY, SQLSTATE(42000) "SELECT: cannot use non GROUP BY column in query 
results without an aggregate function");
+                               }
                        }
                }
                return e;
diff --git a/sql/test/miscellaneous/Tests/simple_plans.sql 
b/sql/test/miscellaneous/Tests/simple_plans.sql
--- a/sql/test/miscellaneous/Tests/simple_plans.sql
+++ b/sql/test/miscellaneous/Tests/simple_plans.sql
@@ -1,5 +1,10 @@
 start transaction;
 
+create table myy (col1 int, col2 int);
+insert into myy values (1, 1), (2, 0), (3,3), (4,2);
+select distinct col1 + col2 from myy order by col1 + col2;
+plan select distinct col1 + col2 from myy order by col1 + col2;
+
 create table myx (x uuid, y uuid);
 plan select * from myx where x in ('1aea00e5db6e0810b554fde31d961965') or y = 
'1aea00e5db6e0810b554fde31d961965';
 plan select * from myx where x in ('1aea00e5db6e0810b554fde31d961965') or y is 
null;
diff --git a/sql/test/miscellaneous/Tests/simple_plans.stable.out 
b/sql/test/miscellaneous/Tests/simple_plans.stable.out
--- a/sql/test/miscellaneous/Tests/simple_plans.stable.out
+++ b/sql/test/miscellaneous/Tests/simple_plans.stable.out
@@ -6,6 +6,28 @@ stdout of test 'simple_plans` in directo
 # 11:57:38 >  
 
 #start transaction;
+#create table myy (col1 int, col2 int);
+#insert into myy values (1, 1), (2, 0), (3,3), (4,2);
+[ 4    ]
+#select distinct col1 + col2 from myy order by col1 + col2;
+% sys.%2 # table_name
+% %2 # name
+% bigint # type
+% 1 # length
+[ 2    ]
+[ 6    ]
+#plan select distinct col1 + col2 from myy order by col1 + col2;
+% .plan # table_name
+% rel # name
+% clob # type
+% 110 # length
+project (
+| group by (
+| | project (
+| | | table(sys.myy) [ "myy"."col1", "myy"."col2" ] COUNT 
+| | ) [ sys.sql_add(bigint["myy"."col1"] as "myy"."col1", bigint["myy"."col2"] 
as "myy"."col2") as "%2"."%2" ]
+| ) [ "%2"."%2" ] [ "%2"."%2" ]
+) [ "%2"."%2" ] [ "%2"."%2" ASC ]
 #create table myx (x uuid, y uuid);
 #plan select * from myx where x in ('1aea00e5db6e0810b554fde31d961965') or y = 
'1aea00e5db6e0810b554fde31d961965';
 % .plan # table_name
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to