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