Changeset: 01309573072e for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=01309573072e
Modified Files:
sql/server/rel_select.c
sql/server/sql_parser.y
sql/server/sql_symbol.c
sql/server/sql_symbol.h
Branch: graph0
Log Message:
PARSER: allow multiple sequences of the UNNEST operator
diffs (155 lines):
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
@@ -5367,33 +5367,37 @@ rel_unionjoinquery(mvc *sql, sql_rel *re
static sql_rel *
rel_unnest_query(mvc* sql, sql_rel* rel, symbol* q){
dnode* head = q->data.lval->h;
- sql_rel* lhs = NULL;
- sql_exp* rhs = NULL;
- list* attributes = NULL;
- const char* attributes_tbl = NULL;
symbol* symbol_table_alias = NULL;
- // bind the table and the column
- lhs = table_ref(sql, rel, head->data.sym, 0);
- if(!lhs){
+ // bind the table
+ rel = table_ref(sql, rel, head->data.sym, 0);
+ if(!rel){
return NULL;
}
- rhs = rel_column_ref(sql, &lhs, head->next->data.sym, sql_from);
- if(!rhs){
- return NULL;
- }
- if(rhs->tpe.type->eclass != EC_NESTED_TABLE){
- //(void) sql_error(sql, 02, "relational query without result");
- return sql_error(sql, 02, "The attribute %s is not a nested
table", exp_name(rhs));
- }
-
- rel = rel_unnest(sql->sa, lhs, rhs);
-
- // rename the attributes according to the table name of the nested
column
- attributes = rel_unnest_attributes(rel);
- attributes_tbl = exp_relname(rhs);
- for (node* n = attributes->h; n; n = n->next){
- exp_setname(sql->sa, n->data, attributes_tbl, NULL);
+
+ // bind the nested table attributes
+ // we have a list for the general case T UNNEST T.x UNNEST T.y ...
+ // however typically there is only one entry in the list
+ for(dnode* nst = head->next->data.lval->h; nst; nst = nst->next){
+ sql_exp* rhs = rel_column_ref(sql, &rel, nst->data.sym,
sql_from);
+ list* attributes = NULL;
+ const char* attributes_tbl = NULL;
+
+ if(!rhs){
+ return NULL;
+ }
+
+ if(rhs->tpe.type->eclass != EC_NESTED_TABLE)
+ return sql_error(sql, 02, "The attribute %s is not a
nested table", exp_name(rhs));
+
+ rel = rel_unnest(sql->sa, rel, rhs);
+
+ // rename the attributes according to the table name of the
nested column
+ attributes = rel_unnest_attributes(rel);
+ attributes_tbl = exp_relname(rhs);
+ for (node* n = attributes->h; n; n = n->next){
+ exp_setname(sql->sa, n->data, attributes_tbl, NULL);
+ }
}
// table expression alias, i.e. table_exp UNNEST attr AS newName (
newColumns )
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
@@ -41,6 +41,7 @@
#define append_symbol(l,d) dlist_append_symbol( SA, l, d)
#define append_string(l,d) dlist_append_string( SA, l, d)
#define append_type(l,d) dlist_append_type( SA, l, d)
+#define prepend_symbol(l, d) dlist_prepend_symbol( SA, l, d)
#define _atom_string(t, v) atom_string(SA, t, v)
@@ -426,6 +427,7 @@ int yydebug=1;
window_frame_extent
window_frame_between
routine_designator
+ nested_attributes
%type <i_val>
any_all_some
@@ -2961,6 +2963,13 @@ join_spec:
{ $$ = _symbol_create_list( SQL_USING, $2); }
;
+nested_attributes:
+ ident
+ { $$ = append_symbol(L(), _symbol_create_list(SQL_COLUMN,
append_string(L(), $1))); }
+ | ident UNNEST nested_attributes
+ { $$ = prepend_symbol($3, _symbol_create_list(SQL_COLUMN,
append_string(L(), $1))); }
+ ;
+
/*
<query expression> ::= [ <with clause> ] <query expression body>
@@ -3179,11 +3188,11 @@ table_ref:
append_symbol($1->data.lval, $2);
}
}
- | subquery_with_orderby UNNEST ident opt_table_name
+ | subquery_with_orderby UNNEST nested_attributes opt_table_name
{
{ dlist *l = L();
append_symbol(l, $1);
- append_symbol(l, _symbol_create_list(SQL_COLUMN, append_string(L(),
$3)));
+ append_list(l, $3);
append_symbol(l, $4);
$$ = _symbol_create_list( SQL_UNNEST, l); }
}
diff --git a/sql/server/sql_symbol.c b/sql/server/sql_symbol.c
--- a/sql/server/sql_symbol.c
+++ b/sql/server/sql_symbol.c
@@ -263,6 +263,28 @@ dlist_append_type(sql_allocator *sa, dli
return dlist_append_default(l, n);
}
+static dlist *
+dlist_prepend_default(dlist *l, dnode *n)
+{
+ n->next = l->h;
+ l->h = n;
+ if(l->cnt == 0){ l->t = n; }
+ l->cnt++;
+
+ return l;
+}
+
+dlist *
+dlist_prepend_symbol(sql_allocator* sa, dlist* l, struct symbol *data)
+{
+ dnode *n = dnode_create_symbol(sa, data);
+
+ if (!n)
+ return NULL;
+ return dlist_prepend_default(l, n);
+}
+
+
symbol *
newSelectNode(sql_allocator *sa, int distinct, struct dlist *selection, struct
dlist *into, symbol *from, symbol *where, symbol *groupby, symbol *having,
symbol *orderby, symbol *name, symbol *limit, symbol *offset, symbol *sample)
{
diff --git a/sql/server/sql_symbol.h b/sql/server/sql_symbol.h
--- a/sql/server/sql_symbol.h
+++ b/sql/server/sql_symbol.h
@@ -52,6 +52,8 @@ extern dlist *dlist_append_lng(sql_alloc
extern dlist *dlist_append_symbol(sql_allocator *sa, dlist *l, struct symbol
*data);
extern dlist *dlist_append_type(sql_allocator *sa, dlist *l, struct
sql_subtype *data);
+extern dlist *dlist_prepend_symbol(sql_allocator* sa, dlist* l, struct symbol
*data);
+
typedef struct symbol {
int token;
symtype type;
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list