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

Reply via email to