Changeset: 2ab72bc595c0 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2ab72bc595c0
Modified Files:
        sql/include/sql_relation.h
        sql/server/rel_exp.c
        sql/server/rel_graph.c
        sql/server/rel_graph.h
        sql/server/rel_select.c
        sql/server/sql_parser.h
        sql/server/sql_parser.y
        sql/server/sql_scan.c
Branch: graph1
Log Message:

Cheapest sum - Parser & semantic phase

* Untested


diffs (truncated from 317 to 300 lines):

diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -175,7 +175,7 @@ typedef enum operator_type {
 #define is_analytic(e) \
        (e->type == e_func && ((sql_subfunc*)e->f)->func->type == F_ANALYTIC)
 #define is_base(op) \
-       (op == op_basetable || op == op_table)
+       (op == op_basetable|| op == op_table)
 #define is_basetable(op) \
        (op == op_basetable)
 #define is_ddl(op) \
@@ -295,6 +295,7 @@ typedef struct {
        list *src;
        list *dst;
        sql_rel *edges;
+       sql_exp *cost;
 } graph_join;
 
 #endif /* SQL_RELATION_H */
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
@@ -149,6 +149,7 @@ exp_graph_join(sql_allocator *sa, list *
        g->src = efrom;
        g->dst = eto;
        g->edges = graph;
+       g->cost = NULL;
        e->flag = cmp_filter_graph;
 
        return e;
diff --git a/sql/server/rel_graph.c b/sql/server/rel_graph.c
--- a/sql/server/rel_graph.c
+++ b/sql/server/rel_graph.c
@@ -100,3 +100,127 @@ sql_rel* rel_graph_reaches(mvc *sql, sql
 
        return result;
 }
+
+
+/*****************************************************************************
+ *                                                                           *
+ * CHEAPEST SUM, semantic phase                                              *
+ *                                                                           *
+ *****************************************************************************/
+
+static bool error_reported(mvc* sql){ return (sql->session->status < 0); }
+
+
+static sql_exp* bindg_ret(mvc *sql, sql_exp* bind1, sql_exp* bind2){
+       if (error_reported(sql)){ // an error already occurred
+               return NULL;
+       } else if(bind1 && bind2){
+               return sql_error(sql, ERR_AMBIGUOUS, "Ambiguous expression for 
CHEAPEST SUM: %s, %s", exp_name(bind1), exp_name(bind2));
+       } else if(bind1){
+               return bind1;
+       } else {
+               return bind2; // either if it has a value or it is null */
+       }
+}
+
+static sql_exp* bindg_exp(mvc *sql, sql_exp *exp, symbol *sym){
+       graph_join *g;
+       sql_exp* e;
+       exp_kind exp_kind_value = {type_value, card_column, TRUE};
+
+       assert(exp && "Expected an expression");
+
+       if(exp->type != e_cmp || get_cmp(exp) != cmp_filter_graph){
+               // this is not a graph join, move along
+               return NULL;
+       }
+
+       g = exp->f;
+
+       // try to bind the expression
+       e = rel_value_exp(sql, &(g->edges), sym, sql_sel, exp_kind_value);
+       if(!e){ return NULL; }
+
+       // an expression has already been bound
+       if(g->cost){
+               return sql_error(sql, 02, "TODO: At the moment you cannot bind 
multiple CHEAPEST SUM expression against the same join");
+       }
+
+       // found it!
+       g->cost = exp_label(sql->sa, e, ++sql->label);
+       return g->cost;
+}
+
+
+static sql_exp* bindg_exps(mvc *sql, list *exps, symbol *sym){
+       sql_exp *result = NULL;
+
+       // edge case
+       if(!exps || error_reported(sql)) return NULL;
+
+       for(node* n = exps->h; n; n = n->next){
+               sql_exp *bound = bindg_exp(sql, n->data, sym);
+               result = bindg_ret(sql, result, bound);
+               if(error_reported(sql)) return NULL; // ERROR! => stop 
processing
+       }
+
+       return result;
+}
+
+static sql_exp* bindg_rel(mvc *sql, sql_rel* relation, symbol *sym){
+       // edge case
+       if(!relation || error_reported(sql)) return NULL;
+
+       switch(relation->op){
+       case op_join:
+       case op_left:
+       case op_right:
+       case op_full:
+       case op_semi: {
+               sql_exp *exp1 = NULL, *exp2 = NULL, *exp3 = NULL, *ret = NULL;
+
+               exp1 = bindg_rel(sql, relation->l, sym);
+               exp2 = bindg_rel(sql, relation->r, sym);
+               ret = bindg_ret(sql, exp1, exp2);
+               exp3 = bindg_exps(sql, relation->exps, sym);
+               return bindg_ret(sql, ret, exp3);
+       } break;
+       case op_select: {
+               sql_exp* exp1 = bindg_exps(sql, relation->exps, sym);
+               sql_exp* exp2 = bindg_rel(sql, relation->l, sym);
+               return bindg_ret(sql, exp1, exp2);
+       } break;
+       case op_groupby:
+               // move up the tree
+               return bindg_rel(sql, relation->l, sym);
+       default:
+               return NULL;
+       }
+}
+
+
+sql_exp* rel_graph_cheapest_sum(mvc *sql, sql_rel **rel, symbol *sym, int 
context){
+       sql_exp* exp_bound = NULL;
+       sql_exp* result = NULL;
+
+       // Check the context is the SELECT clause
+       if(context != sql_sel){
+               sql_error(sql, 02, "CHEAPEST SUM is only allowed inside the 
SELECT clause");
+               return NULL;
+       }
+
+       // Check whether an argument has been specified
+       if(!sym->data.sym){
+               // TODO this should be already handled by the parser (i.e. it's 
not part of the language)
+               sql_error(sql, 02, "Empty argument for CHEAPEST SUM");
+               return NULL;
+       }
+
+       // Find the relation where the sub the expression binds to
+       exp_bound = bindg_rel(sql, *rel, sym);
+       if(!exp_bound){ return NULL; }
+
+       // Create the new column
+       result = exp_column(sql->sa, NULL, exp_bound->name, 
exp_subtype(exp_bound), (*rel)->card, /* has_nil = */ FALSE, /* is_intern = */ 
FALSE);
+       return result;
+}
diff --git a/sql/server/rel_graph.h b/sql/server/rel_graph.h
--- a/sql/server/rel_graph.h
+++ b/sql/server/rel_graph.h
@@ -13,5 +13,6 @@
 #include "sql_semantic.h"
 
 sql_rel* rel_graph_reaches(mvc *sql, sql_rel *rel, symbol *sq, int context);
+sql_exp* rel_graph_cheapest_sum(mvc *sql, sql_rel **rel, symbol *sq, int 
context);
 
 #endif /* _REL_GRAPH_H_ */
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
@@ -4415,6 +4415,8 @@ rel_value_exp2(mvc *sql, sql_rel **rel, 
        case SQL_XMLPI:
        case SQL_XMLTEXT:
                return rel_xml(sql, rel, se, f, ek);
+       case SQL_GRAPH_CHEAPEST_SUM:
+               return rel_graph_cheapest_sum(sql, rel, se, f);
        default:
                return rel_logical_value_exp(sql, rel, se, f);
        }
diff --git a/sql/server/sql_parser.h b/sql/server/sql_parser.h
--- a/sql/server/sql_parser.h
+++ b/sql/server/sql_parser.h
@@ -174,6 +174,7 @@ typedef enum tokens {
        SQL_XMLVALIDATE,
        SQL_XMLNAMESPACES,
        SQL_GRAPH_REACHES,
+       SQL_GRAPH_CHEAPEST_SUM,
 } tokens;
 
 typedef enum jt {
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
@@ -7,7 +7,7 @@
  */
 
 %{
-// #define YYDEBUG 1
+#define YYDEBUG 1
 #include "monetdb_config.h"
 #include <sql_mem.h>
 #include "sql_parser.h"
@@ -300,6 +300,7 @@ int yydebug=1;
        graph_reaches_exp
        graph_reaches_column_def
        graph_reaches_edges_table
+       graph_cheapest_sum
 
 %type <type>
        data_type
@@ -336,6 +337,7 @@ int yydebug=1;
        XML_namespace_prefix
        XML_PI_target
        function_body
+       aggr
 
 %type <l>
        passwd_schema
@@ -511,7 +513,7 @@ int yydebug=1;
 
 /* sql prefixes to avoid name clashes on various architectures */
 %token <sval>
-       IDENT aTYPE ALIAS AGGR AGGR2 RANK sqlINT OIDNUM HEXADECIMAL INTNUM 
APPROXNUM 
+       IDENT aTYPE ALIAS AGGR SUM AGGR2 RANK sqlINT OIDNUM HEXADECIMAL INTNUM 
APPROXNUM 
        USING 
        GLOBAL CAST CONVERT
        CHARACTER VARYING LARGE OBJECT VARCHAR CLOB sqlTEXT BINARY sqlBLOB
@@ -558,7 +560,7 @@ int yydebug=1;
 %token FILTER
 
 /* GRAPH tokens */
-%token REACHES EDGE
+%token CHEAPEST REACHES EDGE
 
 /* operators */
 %left UNION EXCEPT INTERSECT CORRESPONDING UNIONJOIN
@@ -3308,6 +3310,7 @@ predicate:
  |  filter_exp
  |  scalar_exp
  |  graph_reaches_exp
+ |  graph_cheapest_sum
  ;
 
 pred_exp:
@@ -3769,6 +3772,9 @@ graph_reaches_edges_table:
                          append_symbol(l, $2);
                          $$ = _symbol_create_list(SQL_NAME, l); }
 
+graph_cheapest_sum:
+       CHEAPEST SUM '(' scalar_exp ')' { $$ = _symbol_create_symbol( 
SQL_GRAPH_CHEAPEST_SUM, $4 ); }
+
 /*
 <window function> ::= <window function type> OVER <window name or 
specification>
 
@@ -4119,9 +4125,13 @@ qrank:
                          append_string(L(), $1), $3);}
  ;
 
+aggr: AGGR 
+ | SUM { $$ = sa_strdup(SA, "sum"); }
+ ;
+
 qaggr:
-       AGGR            { $$ = append_string(L(), $1); }
- |      ident '.' AGGR { $$ = append_string(
+       aggr            { $$ = append_string(L(), $1); }
+ |      ident '.' aggr { $$ = append_string(
                          append_string(L(), $1), $3);}
  ;
 
@@ -5138,7 +5148,7 @@ restricted_ident:
     IDENT      { $$ = $1; }
  |  aTYPE      { $$ = $1; }
  |  ALIAS      { $$ = $1; }
- |  AGGR       { $$ = $1; }    /* without '(' */
+ |  aggr       { $$ = $1; }    /* without '(' */
  |  AGGR2      { $$ = $1; }    /* without '(' */
  |  RANK       { $$ = $1; }    /* without '(' */
  ;
@@ -5148,7 +5158,7 @@ ident:
  |  aTYPE      { $$ = $1; }
  |  FILTER_FUNC        { $$ = $1; }
  |  ALIAS      { $$ = $1; }
- |  AGGR       { $$ = $1; }    /* without '(' */
+ |  aggr       { $$ = $1; }    /* without '(' */
  |  AGGR2      { $$ = $1; }    /* without '(' */
  |  RANK       { $$ = $1; }    /* without '(' */
  |  non_reserved_word
diff --git a/sql/server/sql_scan.c b/sql/server/sql_scan.c
--- a/sql/server/sql_scan.c
+++ b/sql/server/sql_scan.c
@@ -101,7 +101,7 @@ scanner_init_keywords(void)
        keywords_insert("AVG", AGGR);
        keywords_insert("MIN", AGGR);
        keywords_insert("MAX", AGGR);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to