1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 #ifndef ZORBA_COMPILER_FLWOR_EXPR_H
19 #define ZORBA_COMPILER_FLWOR_EXPR_H
20 
21 #include "common/shared_types.h"
22 
23 #include "compiler/expression/expr_base.h"
24 #include "compiler/expression/var_expr.h"
25 #include "compiler/expression/expr_utils.h"
26 
27 namespace zorba
28 {
29 
30 class ExprManager;
31 
32 class order_modifier;
33 class flwor_clause;
34 class for_clause;
35 class let_clause;
36 class window_clause;
37 class flwor_wincond;
38 class orderby_clause;
39 class materialize_clause;
40 class group_clause;
41 class flwor_expr;
42 
43 /***************************************************************************//**
44 
45 ********************************************************************************/
46 class flwor_clause
47 {
48   friend class flwor_expr;
49   friend class ExprIterator;
50   friend class ExprManager;
51 
52 public:
53   typedef std::vector<std::pair<expr*, var_expr*> > rebind_list_t;
54 
55   typedef enum
56   {
57     for_clause,
58     let_clause,
59     window_clause,
60     group_clause,
61     order_clause,
62     count_clause,
63     where_clause,
64     materialize_clause
65   } ClauseKind;
66 
67 protected:
68   static_context          * theContext;
69   QueryLoc                  theLocation;
70 
71   ClauseKind                theKind;
72   flwor_expr              * theFlworExpr;
73 
74   CompilerCB        * const theCCB;
75 
76 protected:
flwor_clause(static_context * sctx,CompilerCB * ccb,const QueryLoc & loc,ClauseKind kind)77   flwor_clause(
78       static_context* sctx,
79       CompilerCB* ccb,
80       const QueryLoc& loc,
81       ClauseKind kind)
82     :
83     theContext(sctx),
84     theLocation(loc),
85     theKind(kind),
86     theFlworExpr(NULL),
87     theCCB(ccb)
88   {
89   }
90 
91 public:
92   virtual ~flwor_clause();
93 
get_loc()94   const QueryLoc& get_loc() const { return theLocation; }
95 
get_kind()96   ClauseKind get_kind() const { return theKind; }
97 
get_flwor_expr()98   flwor_expr* get_flwor_expr() const { return theFlworExpr; }
99 
get_expr()100   virtual expr* get_expr() const { return NULL; }
101 
set_expr(expr * v)102   virtual void set_expr(expr* v) { }
103 
get_pos_var()104   virtual var_expr* get_pos_var() const { return NULL; }
105 
get_score_var()106   virtual var_expr* get_score_var() const { return NULL; }
107 
108   virtual flwor_clause* clone(expr::substitution_t& substitution) const = 0;
109 };
110 
111 
112 /***************************************************************************//**
113 
114   ForClause ::= "outer"? "for" "$" VarName TypeDeclaration? PositionalVar?
115                 "in" DomainExpr
116 
117   LetClause ::= "let" "$" VarName TypeDeclaration? ":=" DomainExpr
118 
119   WindowClause ::= "for" (TumblingWindowClause | SlidingWindowClause)
120 
121   TumblingWindowClause ::= "tumbling" "window"
122                            "$" VarName TypeDeclaration? "in" DomainExpr
123                            WindowStartCondition
124                            WindowEndCondition?
125 
126   SlidingWindowClause ::= "sliding" "window"
127                           "$" VarName TypeDeclaration? "in" DomainExpr
128                           WindowStartCondition
129                           WindowEndCondition
130 
131   DomainExpr ::= ExprSingle
132 
133   PositionalVar ::= "at" "$" VarName
134 
135   TypeDeclaration ::= "as" SequenceType
136 
137 ********************************************************************************/
138 class forletwin_clause : public flwor_clause
139 {
140   friend class flwor_expr;
141   friend class ExprManager;
142   friend class ExprIterator;
143 
144 protected:
145   var_expr   * theVarExpr;
146   expr       * theDomainExpr;
147 
148 protected:
149   forletwin_clause(
150         static_context* sctx,
151         CompilerCB* ccb,
152         const QueryLoc& loc,
153         ClauseKind kind,
154         var_expr* varExpr,
155         expr* domainExpr);
156 
157 public:
158   ~forletwin_clause();
159 
160   void set_expr(expr* v);
161 
get_expr()162   expr* get_expr() const { return theDomainExpr; }
163 
get_var()164   var_expr* get_var() const { return theVarExpr; }
165 
166   void set_var(var_expr* v);
167 };
168 
169 
170 /***************************************************************************//**
171 
172 ********************************************************************************/
173 class for_clause : public forletwin_clause
174 {
175   friend class flwor_expr;
176   friend class ExprManager;
177   friend class ExprIterator;
178 
179 protected:
180   var_expr    * thePosVarExpr;
181   var_expr    * theScoreVarExpr;
182   bool          theAllowingEmpty;
183 
184 protected:
185   for_clause(
186         static_context* sctx,
187         CompilerCB* ccb,
188         const QueryLoc& loc,
189         var_expr* varExpr,
190         expr* domainExpr,
191         var_expr* posVarExpr = NULL,
192         var_expr* scoreVarExpr = NULL,
193         bool isOuter = false);
194 
195 public:
196   ~for_clause();
197 
is_allowing_empty()198   bool is_allowing_empty() const { return theAllowingEmpty; }
199 
set_allowing_empty(bool allowing_empty)200   void set_allowing_empty(bool allowing_empty) { theAllowingEmpty = allowing_empty; }
201 
202   var_expr* get_pos_var() const;
203 
204   var_expr* get_score_var() const;
205 
206   void set_pos_var(var_expr* v);
207 
208   void set_score_var(var_expr* v);
209 
210   flwor_clause* clone(expr::substitution_t& substitution) const;
211 
212   std::ostream& put(std::ostream&) const;
213 };
214 
215 
216 /***************************************************************************//**
217   theScoreVarExpr :
218   theLazyEval     : Whether the window var can be materilized lazily or not.
219 ********************************************************************************/
220 class let_clause : public forletwin_clause
221 {
222   friend class flwor_expr;
223   friend class ExprManager;
224   friend class ExprIterator;
225 
226 protected:
227   var_expr  * theScoreVarExpr;
228   bool        theLazyEval;
229 
230 protected:
231   let_clause(
232         static_context* sctx,
233         CompilerCB* ccb,
234         const QueryLoc& loc,
235         var_expr* varExpr,
236         expr* domainExpr,
237         bool lazy = false);
238 
239 public:
240   ~let_clause();
241 
242   var_expr* get_score_var() const;
243 
244   void set_score_var(var_expr* v);
245 
setLazyEval(bool v)246   void setLazyEval(bool v) { theLazyEval = v; }
247 
lazyEval()248   bool lazyEval() const { return theLazyEval; }
249 
250   flwor_clause* clone(expr::substitution_t& substitution) const;
251 
252   std::ostream& put(std::ostream&) const;
253 };
254 
255 
256 /***************************************************************************//**
257   theWindowKind   :
258   theWinStartCond :
259   theWinStopCond  :
260   theLazyEval     : Whether the window var can be materilized lazily or not.
261 ********************************************************************************/
262 class window_clause : public forletwin_clause
263 {
264   friend class flwor_expr;
265   friend class ExprManager;
266   friend class ExprIterator;
267 
268 public:
269   typedef enum { tumbling_window, sliding_window } window_t;
270 
271 protected:
272   window_t         theWindowKind;
273   flwor_wincond  * theWinStartCond;
274   flwor_wincond  * theWinStopCond;
275   bool             theLazyEval;
276 
277 protected:
278   window_clause(
279         static_context* sctx,
280         CompilerCB* ccb,
281         const QueryLoc& loc,
282         window_t winKind,
283         var_expr* varExpr,
284         expr* domainExpr,
285         flwor_wincond* winStart,
286         flwor_wincond* winStop,
287         bool lazy = false);
288 
289 public:
290   ~window_clause();
291 
get_winkind()292   window_t get_winkind() const { return theWindowKind; }
293 
get_win_start()294   flwor_wincond* get_win_start() const { return theWinStartCond; }
295 
get_win_stop()296   flwor_wincond* get_win_stop() const { return theWinStopCond; }
297 
298   void set_win_start(flwor_wincond* cond);
299 
300   void set_win_stop(flwor_wincond* cond);
301 
setLazyEval(bool v)302   void setLazyEval(bool v) { theLazyEval = v; }
303 
lazyEval()304   bool lazyEval() const { return theLazyEval; }
305 
306   flwor_clause* clone(expr::substitution_t& substitution) const;
307 
308   std::ostream& put(std::ostream&) const;
309 };
310 
311 
312 /***************************************************************************//**
313 
314   Class flwor_wincond represents a start/stop condition of a window clause.
315 
316   - Syntax:
317 
318   WindowStartCondition ::= "start" WindowVars "when" ExprSingle
319 
320   WindowEndCondition ::= "only"? "end" WindowVars "when" ExprSingle
321 
322   WindowVars ::= ("$" CurrentItem)?
323                  PositionalVar?
324                  ("previous" "$" PreviousItem)?
325                  ("next" "$" NextItem)?
326 
327   - Data Members:
328 
329   theIsOnly    : The "only" flag, if this is an end condition
330   theInputVars : The var_exprs for the 4 condition vars that iterate over the
331                  window domain expr and whose values are used to compute the
332                  condition expr during each iteration. These vars are visible
333                  only during the evaluation of the condition expr.
334   theOutputVars: When the condition expr evaluates to true, the current values
335                  of theInputVars are copied to theOutputVars. So, theOutputVars
336                  describe the starting/ending point of an established window
337                  and they are visible to the rest of the query (i.e., they
338                  become columns in the output stream produced by the window
339                  clause).
340   theCondExpr  : The start/end condition expr.
341 ********************************************************************************/
342 class flwor_wincond
343 {
344   friend class flwor_expr;
345   friend class ExprManager;
346   friend class ExprIterator;
347 
348 public:
349   struct vars
350   {
351     var_expr* posvar;
352     var_expr* curr;
353     var_expr* prev;
354     var_expr* next;
355 
356     vars();
357     ~vars();
358     void set_flwor_clause(flwor_clause* c);
359 
360     void clone(ExprManager* mgr, vars& cloneVars, expr::substitution_t& subst) const;
361 
362     std::ostream& put(std::ostream&) const;
363   };
364 
365 protected:
366   bool         theIsOnly;
367   vars         theInputVars;
368   vars         theOutputVars;
369   expr       * theCondExpr;
370 
371   CompilerCB * const theCCB;
372 
373 protected:
374   flwor_wincond(
375       CompilerCB* ccb,
376       static_context* sctx,
377       bool isOnly,
378       const vars& in_vars,
379       const vars& out_vars,
380       expr* cond);
381 
382 public:
383   ~flwor_wincond();
384 
get_cond()385   expr* get_cond() const { return theCondExpr; }
386 
set_cond(expr * cond)387   void set_cond(expr* cond) { theCondExpr = cond; }
388 
is_only()389   bool is_only() const { return theIsOnly; }
390 
get_in_vars()391   const vars& get_in_vars() const { return theInputVars; }
392 
get_out_vars()393   const vars& get_out_vars() const { return theOutputVars; }
394 
395   void set_flwor_clause(flwor_clause *);
396 
397   flwor_wincond* clone(expr::substitution_t& substitution) const;
398 
399   std::ostream& put(std::ostream&) const;
400 };
401 
402 
403 /***************************************************************************//**
404   - Syntax:
405 
406   GroupByClause ::= "group" "by" GroupingSpecList
407 
408   GroupSpecList ::= GroupingSpec ("," GroupingSpec)*
409 
410   GroupSpec ::= "$" VarName (TypeDeclaration? ":=" ExprSingle)?
411                 ("collation" URILiteral)?
412 
413   - Data Members:
414 
415   theGroupVars    : For each grouping var X, theGroupVars contains a pair of
416                     exprs: the 1st element of the pair is a reference to X in
417                     the groupby's input tuple stream, and the 2nd element is
418                     a var_expr representing the variable gX that the groupby
419                     produces for X in its output tuple stream.
420   theNonGroupVars : For each non-grouping var Y, theGroupVars contains a pair of
421                     exprs: the 1st element of the pair is a reference to Y in
422                     the groupby's input tuple stream, and the 2nd element is
423                     a var_expr representing the variable gY that the groupby
424                     produces for Y in its output tuple stream. For each tuple
425                     T produced by the groupby, gY is the concatenation of all
426                     the Y values in the input tuples that were grouped into T.
427   theCollations   : The collations to use when comparing values for grouping.
428 ********************************************************************************/
429 class group_clause : public flwor_clause
430 {
431   friend class flwor_expr;
432   friend class ExprManager;
433   friend class ExprIterator;
434 
435 protected:
436   rebind_list_t            theGroupVars;
437   rebind_list_t            theNonGroupVars;
438   std::vector<std::string> theCollations;
439 
440   group_clause(
441       static_context* sctx,
442       CompilerCB* ccb,
443       const QueryLoc& loc,
444       const rebind_list_t& gvars,
445       rebind_list_t ngvars,
446       const std::vector<std::string>& collations);
447 
448 public:
449   ~group_clause();
450 
get_collations()451   const std::vector<std::string>& get_collations() const { return theCollations; }
452 
getNumGroupingVars()453   csize getNumGroupingVars() const { return theGroupVars.size(); }
454 
getNumNonGroupingVars()455   csize getNumNonGroupingVars() const { return theNonGroupVars.size(); }
456 
get_grouping_vars()457   const rebind_list_t& get_grouping_vars() const { return theGroupVars; }
458 
get_nongrouping_vars()459   const rebind_list_t& get_nongrouping_vars() const { return theNonGroupVars; }
460 
set_grouping_vars(rebind_list_t & v)461   void set_grouping_vars(rebind_list_t& v) { theGroupVars = v; }
462 
set_nongrouping_ars(rebind_list_t & v)463   void set_nongrouping_ars(rebind_list_t& v) { theNonGroupVars = v; }
464 
removeNonGroupingVar(rebind_list_t::iterator ite)465   void removeNonGroupingVar(rebind_list_t::iterator ite) { theNonGroupVars.erase(ite); }
466 
beginGroupVars()467   rebind_list_t::iterator beginGroupVars() { return theGroupVars.begin(); }
468 
beginGroupVars()469   rebind_list_t::const_iterator beginGroupVars() const { return theGroupVars.begin(); }
470 
endGroupVars()471   rebind_list_t::iterator endGroupVars() { return theGroupVars.end(); }
472 
endGroupVars()473   rebind_list_t::const_iterator endGroupVars() const { return theGroupVars.end(); }
474 
beginNonGroupVars()475   rebind_list_t::iterator beginNonGroupVars() { return theNonGroupVars.begin(); }
476 
beginNonGroupVars()477   rebind_list_t::const_iterator beginNonGroupVars() const { return theNonGroupVars.begin(); }
478 
endNonGroupVars()479   rebind_list_t::iterator endNonGroupVars() { return theNonGroupVars.end(); }
480 
endNonGroupVars()481   rebind_list_t::const_iterator endNonGroupVars() const { return theNonGroupVars.end(); }
482 
483   expr* get_input_for_group_var(const var_expr* var);
484 
485   expr* get_input_for_nongroup_var(const var_expr* var);
486 
487   flwor_clause* clone(expr::substitution_t& substitution) const;
488 
489   std::ostream& put(std::ostream&) const;
490 };
491 
492 
493 
494 /***************************************************************************//**
495 
496   OrderByClause ::= (("order" "by") | ("stable" "order" "by")) OrderSpecList
497 
498   OrderSpecList ::= OrderSpec ("," OrderSpec)*
499 
500   OrderSpec ::= ExprSingle OrderModifier
501 
502   OrderModifier ::= ("ascending" | "descending")?
503                     ("empty" ("greatest" | "least"))?
504                     ("collation" URILiteral)?
505 
506 ********************************************************************************/
507 class orderby_clause : public flwor_clause
508 {
509   friend class ExprIterator;
510   friend class ExprManager;
511   friend class flwor_expr;
512 
513 protected:
514 
515   bool                        theStableOrder;
516   std::vector<OrderModifier>  theModifiers;
517   std::vector<expr*>          theOrderingExprs;
518 
519 protected:
520   orderby_clause(
521       static_context* sctx,
522       CompilerCB* ccb,
523       const QueryLoc& loc,
524       bool stable,
525       const std::vector<OrderModifier>& modifiers,
526       const std::vector<expr*>& orderingExprs);
527 
528 public:
is_stable()529   bool is_stable() const { return theStableOrder; }
530 
get_modifiers()531   const std::vector<OrderModifier>& get_modifiers() const { return theModifiers; }
532 
get_column_exprs()533   const std::vector<expr*>& get_column_exprs() const { return theOrderingExprs; }
534 
begin()535   std::vector<expr*>::iterator begin() { return theOrderingExprs.begin(); }
536 
end()537   std::vector<expr*>::iterator end() { return theOrderingExprs.end(); }
538 
begin()539   std::vector<expr*>::const_iterator begin() const
540   {
541     return theOrderingExprs.begin();
542   }
543 
end()544   std::vector<expr*>::const_iterator end() const
545   {
546     return theOrderingExprs.end();
547   }
548 
num_columns()549   csize num_columns() const { return theOrderingExprs.size(); }
550 
get_column_expr(csize i)551   expr* get_column_expr(csize i) const { return theOrderingExprs[i]; }
552 
set_column_expr(csize i,expr * e)553   void set_column_expr(csize i, expr* e) { theOrderingExprs[i] = e; }
554 
555   flwor_clause* clone(expr::substitution_t& substitution) const;
556 
557   std::ostream& put(std::ostream&) const;
558 };
559 
560 
561 /***************************************************************************//**
562   Used to meterialize the tuple stream at the location where the clause
563   appears at. It is needed to implement sequential flwor exprs. Materialize
564   clauses are created and inserted in the flwor expr during codegen.
565 ********************************************************************************/
566 class materialize_clause : public flwor_clause
567 {
568   friend class ExprIterator;
569   friend class ExprManager;
570   friend class flwor_expr;
571 
572   materialize_clause(static_context* sctx, CompilerCB* ccb, const QueryLoc& loc);
573 
574 public:
575   flwor_clause* clone(expr::substitution_t& substitution) const;
576 
577   std::ostream& put(std::ostream&) const;
578 };
579 
580 
581 
582 /***************************************************************************//**
583   CountClause ::= "count" "$" VarName
584 ********************************************************************************/
585 class count_clause : public flwor_clause
586 {
587   friend class ExprIterator;
588   friend class ExprManager;
589 
590 protected:
591   var_expr * theVarExpr;
592 
593   count_clause(static_context* sctx, CompilerCB* ccb, const QueryLoc& loc, var_expr* var);
594 
595 public:
596   ~count_clause();
597 
get_var()598   var_expr* get_var() const { return theVarExpr; }
599 
600   flwor_clause* clone(expr::substitution_t& substitution) const;
601 };
602 
603 
604 /***************************************************************************//**
605    WhereClause ::= ExprSingle
606 ********************************************************************************/
607 class where_clause : public flwor_clause
608 {
609   friend class ExprIterator;
610   friend class ExprManager;
611   friend class flwor_expr;
612 
613   expr * theWhereExpr;
614 
615   where_clause(static_context* sctx, CompilerCB* ccb, const QueryLoc& loc, expr* where);
616 
617 public:
get_expr()618   expr* get_expr() const { return theWhereExpr; }
619 
620   void set_expr(expr* where);
621 
622   flwor_clause* clone(expr::substitution_t& substitution) const;
623 };
624 
625 
626 /***************************************************************************//**
627 
628   - For the Generalized FLWOR:
629 
630   FLWORExpr ::= InitialClause IntermediateClause* ReturnClause
631 
632   InitialClause ::= ForClause | LetClause | WindowClause
633 
634   IntermediateClause ::= InitialClause |
635                          WhereClause |
636                          GroupByClause |
637                          OrderByClause |
638                          CountClause
639 
640   - For the traditional FLWOR:
641 
642   FLWORExpr ::= InitialClause FLWORClauseList? ReturnClause
643 
644   InitialClause ::= ForClause | LetClause
645 
646   FLWORClauseList ::= (ForClause | LetClause)*
647                       WhereCluase?
648                       GroupByClause?
649                       OrderByClause?
650 
651 ********************************************************************************/
652 class flwor_expr : public expr
653 {
654   friend class ExprIterator;
655   friend class expr;
656   friend class ExprManager;
657 
658 public:
659   typedef std::vector<flwor_clause*> clause_list_t;
660 
661 protected:
662   bool            theIsGeneral;
663   bool            theHasSequentialClauses;
664   clause_list_t   theClauses;
665   expr          * theReturnExpr;
666 
667 protected:
668   flwor_expr(CompilerCB* ccb, static_context* sctx, const QueryLoc& loc, bool general);
669 
670 public:
is_general()671   bool is_general() const { return theIsGeneral; }
672 
set_general(bool v)673   void set_general(bool v) { theIsGeneral = true; }
674 
get_return_expr()675   expr* get_return_expr() const { return theReturnExpr; }
676 
set_return_expr(expr * e)677   void set_return_expr(expr* e)
678   {
679     theReturnExpr = e;
680     compute_scripting_kind();
681   }
682 
has_sequential_clauses()683   bool has_sequential_clauses() const { return theHasSequentialClauses; }
684 
685   void compute_scripting_kind();
686 
num_clauses()687   csize num_clauses() const { return theClauses.size(); }
688 
689   void add_clause(flwor_clause* c, bool computeScriptingKind = true);
690 
691   void add_clause(csize pos, flwor_clause* c);
692 
693   void add_where(expr* e);
694 
695   void remove_clause(csize pos);
696 
697   flwor_clause* get_clause(csize i) const;
698 
clause_begin()699   clause_list_t::const_iterator clause_begin() const { return theClauses.begin(); }
700 
clause_end()701   clause_list_t::const_iterator clause_end() const { return theClauses.end(); }
702 
703   long defines_variable(const var_expr* v) const;
704 
705   void get_vars_defined(std::vector<var_expr*>& varExprs) const;
706 
707   expr* cloneImpl(substitution_t& substitution) const;
708 
709   // The following 5 methods are for the simple flwor only. They should be
710   // removed eventually.
711   expr* get_where() const;
712   void set_where(expr* e);
713   void remove_where_clause();
714   group_clause* get_group_clause() const;
715   orderby_clause* get_order_clause() const;
716   csize num_forlet_clauses();
717 
718   void accept(expr_visitor&);
719 
720   std::ostream& put(std::ostream&) const;
721 };
722 
723 
724 
725 }  // namespace zorba
726 
727 #endif
728 
729 /*
730  * Local variables:
731  * mode: c++
732  * End:
733  */
734 /* vim:set et sw=2 ts=2: */
735