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 #include "stdafx.h"
17
18 #include <iostream>
19 #include <list>
20 #include <stack>
21 #include <vector>
22
23 #include <zorba/config.h>
24 #include <zorba/diagnostic_list.h>
25 #include "diagnostics/assert.h"
26
27 #include "util/hashmap32.h"
28 #include "util/stl_util.h"
29 #include "util/tracer.h"
30
31 #include "system/globalenv.h"
32 #include "system/properties.h"
33
34 #include "compiler/api/compilercb.h"
35 #include "compiler/codegen/plan_visitor.h"
36 #include "compiler/expression/expr.h"
37 #include "compiler/expression/expr_visitor.h"
38 #include "compiler/expression/flwor_expr.h"
39 #include "compiler/expression/fo_expr.h"
40 #include "compiler/expression/script_exprs.h"
41 #include "compiler/expression/json_exprs.h"
42 #include "compiler/expression/update_exprs.h"
43 #ifndef ZORBA_NO_FULL_TEXT
44 #include "compiler/expression/ft_expr.h"
45 #include "compiler/expression/ftnode.h"
46 #include "compiler/expression/ftnode_visitor.h"
47 #endif /* ZORBA_NO_FULL_TEXT */
48 #include "compiler/expression/function_item_expr.h"
49 #include "compiler/expression/path_expr.h"
50 #include "compiler/expression/var_expr.h"
51 #include "compiler/parser/parse_constants.h"
52
53 #include "context/namespace_context.h"
54 #include "context/static_context.h"
55 #include "context/static_context_consts.h"
56 #include "context/dynamic_context.h"
57
58 #include "runtime/visitors/printer_visitor_api.h"
59 #include "runtime/visitors/iterprinter.h"
60 #include "runtime/sequences/SequencesImpl.h"
61 #include "runtime/sequences/sequences.h"
62 #include "runtime/core/sequencetypes.h"
63 #include "runtime/core/item_iterator.h"
64 #include "runtime/core/var_iterators.h"
65 #include "runtime/core/constructors.h"
66 #include "runtime/json/json_constructors.h"
67 #include "runtime/core/apply_updates.h"
68 #include "runtime/core/path_iterators.h"
69 #include "runtime/core/nodeid_iterators.h"
70 #include "runtime/core/flwor_iterator.h"
71 #include "runtime/core/trycatch.h"
72 #include "runtime/errors_and_diagnostics/other_diagnostics.h"
73 #include "runtime/core/gflwor/common.h"
74 #include "runtime/core/gflwor/groupby_iterator.h"
75 #include "runtime/core/gflwor/tuplestream_iterator.h"
76 #include "runtime/core/gflwor/for_iterator.h"
77 #include "runtime/core/gflwor/outerfor_iterator.h"
78 #include "runtime/core/gflwor/let_iterator.h"
79 #include "runtime/core/gflwor/window_iterator.h"
80 #include "runtime/core/gflwor/where_iterator.h"
81 #include "runtime/core/gflwor/count_iterator.h"
82 #include "runtime/core/gflwor/tuplesource_iterator.h"
83 #include "runtime/core/gflwor/orderby_iterator.h"
84 #include "runtime/full_text/full_text.h"
85 #include "runtime/schema/schema.h"
86 #include "runtime/scripting/scripting.h"
87 #include "runtime/util/flowctl_exception.h"
88 #include "runtime/update/update.h"
89 #include "runtime/indexing/index_ddl.h"
90 #ifdef ZORBA_WITH_DEBUGGER
91 #include "runtime/debug/debug_iterator.h"
92 #endif
93 #include "runtime/eval/eval.h"
94 #include "runtime/function_item/function_item.h"
95 #include "runtime/function_item/function_item_iter.h"
96 #include "runtime/function_item/dynamic_fncall_iterator.h"
97 #include "runtime/misc/materialize.h"
98
99 #ifdef ZORBA_WITH_DEBUGGER
100 #include "debugger/debugger_commons.h"
101 #endif
102
103 #include "functions/function.h"
104 #include "functions/udf.h"
105 #include "functions/library.h"
106
107 #include "types/typeops.h"
108
109 #include "store/api/store.h"
110 #include "store/api/item.h"
111 #include "store/api/item_factory.h"
112 #include "store/api/iterator.h"
113
114
115 //#define XQUF_STATIC_TYPING_STRICT 1
116 #define XQUF_STATIC_TYPING_SAFE 1
117
118 #define QLOCDECL const QueryLoc& qloc = v.get_loc(); (void) qloc
119
120 #define SCTXDECL static_context* sctx = v.get_sctx(); (void)sctx;
121
122 #ifndef NDEBUG
123
124 #define CODEGEN_TRACE(msg) \
125 QLOCDECL; \
126 SCTXDECL; \
127 if (Properties::instance()->traceCodegen()) \
128 { \
129 std::cout << (msg) << TRACE << ", stk size " << itstack.size() \
130 << std::endl << std::endl; \
131 v.put(std::cout); \
132 std::cout << "StackTop:" << std::endl; \
133 print_stack(); \
134 }
135
136 #define CODEGEN_TRACE_IN(msg) \
137 CODEGEN_TRACE(std::string(++theDepth, ' ') + msg)
138
139 #define CODEGEN_TRACE_OUT(msg) \
140 CODEGEN_TRACE(std::string(theDepth--, ' ') + msg)
141
142 #else
143 #define CODEGEN_TRACE(msg) QLOCDECL; SCTXDECL;
144 #define CODEGEN_TRACE_IN(msg) CODEGEN_TRACE(msg)
145 #define CODEGEN_TRACE_OUT(msg) CODEGEN_TRACE(msg)
146 #endif
147
148
149 namespace zorba
150 {
151
152 class plan_visitor;
153
154
155 typedef rchandle<ForVarIterator> ForVarIter_t;
156 typedef rchandle<LetVarIterator> LetVarIter_t;
157
158
159 #define ITEM_FACTORY (GENV.getStore().getItemFactory())
160
161 namespace plan_visitor_ns
162 {
163
pop_stack(std::stack<T> & stk)164 template <typename T> T pop_stack(std::stack<T> &stk)
165 {
166 assert (! stk.empty ());
167 T x = stk.top ();
168 stk.pop ();
169 return x;
170 }
171
peek_stack(std::stack<T> & stk)172 template<class T> T& peek_stack(std::stack<T> &stk)
173 {
174 ZORBA_ASSERT (! stk.empty ());
175 return stk.top ();
176 }
177
178 } // namespace plan_visitor_ns
179
180
181 template <typename V>
182 struct vector_destroyer
183 {
operator ()zorba::vector_destroyer184 void operator()(const struct hash64map<std::vector<V> *>::entry& entry)
185 {
186 delete (const_cast<struct hash64map<std::vector<V> *>::entry&>(entry)).val;
187 }
188 };
189
190
191 /*******************************************************************************
192
193 ********************************************************************************/
194 class VarRebind : public SimpleRCObject
195 {
196 public:
197 PlanIter_t theInputVar;
198 std::vector<PlanIter_t> theOutputVarRefs;
199 };
200
201
202 typedef rchandle<VarRebind> VarRebind_t;
203
204
205 /*******************************************************************************
206 A FlworClauseVarMap is created for each flwor clause that defines variables.
207 If M is such a clause, then for each variable Vi defined by M, theVarExprs[i]
208 and theVarRebinds[i] contain an entry for Vi. theVarExprs[i] contains the
209 var_expr representing the Vi definition.
210 ********************************************************************************/
211 class FlworClauseVarMap : public SimpleRCObject
212 {
213 public:
214 bool theIsGeneral;
215 const flwor_clause * theClause;
216
217 std::vector<var_expr*> theVarExprs;
218 std::vector<VarRebind_t> theVarRebinds;
219
220 public:
FlworClauseVarMap(const flwor_clause * cl,bool general)221 FlworClauseVarMap(const flwor_clause* cl, bool general)
222 :
223 theIsGeneral(general),
224 theClause(cl)
225 {
226 }
227
~FlworClauseVarMap()228 ~FlworClauseVarMap() { }
229
find_var(const var_expr * var) const230 long find_var(const var_expr* var) const
231 {
232 csize numVars = theVarExprs.size();
233 for (csize i = 0; i < numVars; ++i)
234 {
235 if (theVarExprs[i] == var)
236 return i;
237 }
238
239 return -1;
240 }
241 };
242
243
244 typedef rchandle<FlworClauseVarMap> FlworClauseVarMap_t;
245
246
247 /******************************************************************************
248
249 ******************************************************************************/
250
251 #ifndef ZORBA_NO_FULL_TEXT
252
253 class plan_ftnode_visitor : public ftnode_visitor
254 {
255 public:
256 typedef std::vector<PlanIter_t> PlanIter_list_t;
257
plan_ftnode_visitor(plan_visitor * v)258 plan_ftnode_visitor( plan_visitor* v ) : plan_visitor_( v ) { }
259
260 expr_visitor* get_expr_visitor();
261
get_sub_iters()262 PlanIter_list_t& get_sub_iters() { return sub_iters_; }
263
264 protected:
265 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftand );
266 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftextension_selection );
267 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftmild_not );
268 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftor );
269 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftprimary_with_options );
270 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftrange );
271 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftselection );
272 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftunary_not );
273 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftweight );
274 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwords );
275 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwords_times );
276
277 // FTPosFilters
278 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftcontent_filter );
279 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftdistance_filter );
280 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftorder_filter );
281 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftscope_filter );
282 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwindow_filter );
283
284 // FTMatchOptions
285 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftcase_option );
286 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftdiacritics_option );
287 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftextension_option );
288 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftlanguage_option );
289 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftmatch_options );
290 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftstem_option );
291 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftstop_word_option );
292 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftstop_words );
293 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftthesaurus_id );
294 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftthesaurus_option );
295 DECL_FTNODE_VISITOR_VISIT_MEM_FNS( ftwild_card_option );
296
297 private:
298 plan_visitor * plan_visitor_;
299 PlanIter_list_t sub_iters_;
300 };
301
302 #endif /* ZORBA_NO_FULL_TEXT */
303
304
305 /******************************************************************************
306
307 *******************************************************************************/
308 class plan_visitor : public expr_visitor
309 {
310 #ifndef ZORBA_NO_FULL_TEXT
311 friend class plan_ftnode_visitor;
312 #endif /* ZORBA_NO_FULL_TEXT */
313
314 typedef enum
315 {
316 ELEMENT_CONTENT = 0,
317 ATTRIBUTE_CONTENT,
318 TEXT_CONTENT,
319 UPDATE_CONTEXT
320 } EnclosedExprContext;
321
322 protected:
323 static std::vector<PlanIter_t> no_var_iters;
324
325 protected:
326 uint32_t theDepth;
327
328 std::stack<PlanIter_t> itstack;
329
330 std::stack<expr*> theConstructorsStack;
331 std::stack<EnclosedExprContext> theEnclosedContextStack;
332 std::stack<bool> theCopyNodesStack;
333
334 ulong theNextDynamicVarId;
335
336 hash64map<std::vector<LetVarIter_t> *> * arg_var_iter_map;
337 hash64map<std::vector<LetVarIter_t> *> catchvar_iter_map;
338 hash64map<std::vector<ForVarIter_t> *> copy_var_iter_map;
339
340 std::vector<FlworClauseVarMap_t> theClauseStack;
341
342 CompilerCB * theCCB;
343
344 #ifdef ZORBA_WITH_DEBUGGER
345 std::stack<DebugIterator*> theDebuggerStack;
346 #endif
347
348 #ifndef ZORBA_NO_FULL_TEXT
349 plan_ftnode_visitor * plan_ftnode_visitor_;
350 #endif /* ZORBA_NO_FULL_TEXT */
351
352 public:
353
plan_visitor(CompilerCB * ccb,ulong nextDynamicVarId,hash64map<std::vector<LetVarIter_t> * > * arg_var_map=NULL)354 plan_visitor(
355 CompilerCB* ccb,
356 ulong nextDynamicVarId,
357 hash64map<std::vector<LetVarIter_t>*>* arg_var_map = NULL)
358 :
359 theDepth(0),
360 theNextDynamicVarId(nextDynamicVarId),
361 arg_var_iter_map(arg_var_map),
362 theCCB(ccb)
363 {
364 #ifndef ZORBA_NO_FULL_TEXT
365 plan_ftnode_visitor_ = new plan_ftnode_visitor( this );
366 #endif /* ZORBA_NO_FULL_TEXT */
367 }
368
369
~plan_visitor()370 ~plan_visitor()
371 {
372 for_each(
373 catchvar_iter_map.begin(),
374 catchvar_iter_map.end(),
375 vector_destroyer<LetVarIter_t>()
376 );
377 for_each(
378 copy_var_iter_map.begin(),
379 copy_var_iter_map.end(),
380 vector_destroyer<ForVarIter_t>()
381 );
382 #ifndef ZORBA_NO_FULL_TEXT
383 delete plan_ftnode_visitor_;
384 #endif /* ZORBA_NO_FULL_TEXT */
385 }
386
387
getNextDynamicVarId() const388 ulong getNextDynamicVarId() const
389 {
390 return theNextDynamicVarId;
391 }
392
393
394 #ifndef ZORBA_NO_FULL_TEXT
get_ftnode_visitor()395 ftnode_visitor* get_ftnode_visitor()
396 {
397 return plan_ftnode_visitor_;
398 }
399 #endif /* ZORBA_NO_FULL_TEXT */
400
401
pop_itstack()402 PlanIter_t pop_itstack()
403 {
404 return plan_visitor_ns::pop_stack(itstack);
405 }
406
407
push_itstack(PlanIterator * iter)408 void push_itstack(PlanIterator* iter)
409 {
410 itstack.push(iter);
411 }
412
413
print_stack()414 void print_stack()
415 {
416 if (itstack.empty())
417 {
418 std::cout << "EMPTY" << std::endl;
419 }
420 else
421 {
422 XMLIterPrinter vp(std::cout);
423 print_iter_plan(vp, plan_visitor_ns::peek_stack(itstack));
424 }
425 }
426
427
is_enclosed_expr(expr * e)428 bool is_enclosed_expr(expr* e)
429 {
430 fo_expr* foExpr = dynamic_cast<fo_expr*>(e);
431 if (foExpr != NULL &&
432 foExpr->get_func()->getKind() == FunctionConsts::OP_ENCLOSED_1)
433 return true;
434
435 return false;
436 }
437
438
begin_visit(expr & v)439 bool begin_visit(expr& v)
440 {
441 CODEGEN_TRACE_IN("");
442 return true;
443 }
444
end_visit(expr & v)445 void end_visit(expr& v)
446 {
447 CODEGEN_TRACE_OUT("");
448 }
449
450
451 /***************************************************************************//**
452
453 ********************************************************************************/
begin_visit(function_item_expr & v)454 bool begin_visit(function_item_expr& v)
455 {
456 CODEGEN_TRACE_IN("");
457 return true;
458 }
459
end_visit(function_item_expr & v)460 void end_visit(function_item_expr& v)
461 {
462 CODEGEN_TRACE_OUT("");
463 store::Item_t lQName = v.get_qname();
464 store::Item_t lFItem;
465
466 bool isInline = (lQName == 0);
467
468 if (!isInline)
469 {
470 // literal function item
471 lFItem = new FunctionItem(theCCB, sctx, &v);
472 }
473 else
474 {
475 // inline function
476 std::vector<PlanIter_t> lVariableValues;
477 size_t lSize = v.get_vars().size();
478 for (size_t i = 0; i < lSize; ++i)
479 {
480 lVariableValues.push_back(pop_itstack());
481 }
482 lFItem = new FunctionItem(theCCB, sctx, &v, lVariableValues);
483 }
484
485 push_itstack(new SingletonIterator (sctx, qloc, lFItem));
486 }
487
488
489 /***************************************************************************//**
490
491 ********************************************************************************/
begin_visit(dynamic_function_invocation_expr & v)492 bool begin_visit(dynamic_function_invocation_expr& v)
493 {
494 CODEGEN_TRACE_IN("");
495 return true;
496 }
497
end_visit(dynamic_function_invocation_expr & v)498 void end_visit(dynamic_function_invocation_expr& v)
499 {
500 CODEGEN_TRACE_OUT("");
501
502 ulong numArgs = (ulong)v.get_args().size() + 1;
503
504 std::vector<PlanIter_t> argIters(numArgs);
505
506 for (size_t i = 1; i < numArgs; ++i)
507 {
508 argIters[i] = pop_itstack();
509 }
510
511 argIters[0] = pop_itstack();
512
513 push_itstack(new DynamicFnCallIterator(sctx, qloc, argIters));
514 }
515
516
517 /***************************************************************************//**
518
519 ********************************************************************************/
begin_visit(function_trace_expr & v)520 bool begin_visit(function_trace_expr& v)
521 {
522 CODEGEN_TRACE_IN("");
523 return true;
524 }
525
end_visit(function_trace_expr & v)526 void end_visit(function_trace_expr& v)
527 {
528 CODEGEN_TRACE_OUT("");
529 std::vector<PlanIter_t> argv;
530 argv.push_back(pop_itstack());
531 std::auto_ptr<FunctionTraceIterator> lDummyIter(
532 new FunctionTraceIterator(sctx, qloc, argv));
533 lDummyIter->setFunctionName(v.getFunctionName());
534 lDummyIter->setFunctionArity(v.getFunctionArity());
535 lDummyIter->setFunctionLocation(v.getFunctionLocation());
536 lDummyIter->setFunctionCallLocation(v.getFunctionCallLocation());
537 push_itstack(lDummyIter.release());
538 }
539
begin_visit(wrapper_expr & v)540 bool begin_visit(wrapper_expr& v)
541 {
542 CODEGEN_TRACE_IN("");
543 return true;
544 }
545
end_visit(wrapper_expr & v)546 void end_visit(wrapper_expr& v)
547 {
548 CODEGEN_TRACE_OUT("");
549 PlanIter_t iter = pop_itstack();
550 iter->setLocation (v.get_loc());
551 push_itstack(iter);
552 }
553
554
555 /***************************************************************************//**
556
557 ********************************************************************************/
begin_visit(block_expr & v)558 bool begin_visit(block_expr& v)
559 {
560 CODEGEN_TRACE_IN("");
561 return true;
562 }
563
end_visit(block_expr & v)564 void end_visit(block_expr& v)
565 {
566 CODEGEN_TRACE_OUT("");
567
568 ulong numArgs = v.size();
569 checked_vector<PlanIter_t> args(numArgs);
570
571 for (ulong i = numArgs; i > 0; --i)
572 {
573 PlanIter_t arg = pop_itstack();
574 args[i-1] = arg;
575 }
576
577 push_itstack(new SequentialIterator(sctx, qloc, args));
578 }
579
580
581 /***************************************************************************//**
582
583 ********************************************************************************/
begin_visit(apply_expr & v)584 bool begin_visit(apply_expr& v)
585 {
586 CODEGEN_TRACE_IN("");
587 return true;
588 }
589
end_visit(apply_expr & v)590 void end_visit(apply_expr& v)
591 {
592 CODEGEN_TRACE_OUT("");
593
594 PlanIter_t arg = pop_itstack();
595
596 push_itstack(new ApplyIterator(sctx, qloc, v.discardsXDM(), arg));
597 }
598
599
600 /***************************************************************************//**
601
602 ********************************************************************************/
begin_visit(var_decl_expr & v)603 bool begin_visit(var_decl_expr& v)
604 {
605 CODEGEN_TRACE_IN("");
606
607 var_expr* varExpr = v.get_var_expr();
608 if (varExpr->get_unique_id() == 0)
609 varExpr->set_unique_id(theNextDynamicVarId++);
610
611 return true;
612 }
613
end_visit(var_decl_expr & v)614 void end_visit(var_decl_expr& v)
615 {
616 CODEGEN_TRACE_OUT("");
617
618 var_expr* varExpr = v.get_var_expr();
619 expr* initExpr = v.get_init_expr();
620
621 checked_vector<PlanIter_t> args;
622 bool singleItem = false;
623
624 if (initExpr != NULL)
625 {
626 args.push_back(pop_itstack());
627
628 xqtref_t exprType = initExpr->get_return_type();
629
630 if (exprType->get_quantifier() == TypeConstants::QUANT_ONE)
631 singleItem = true;
632 }
633
634 push_itstack(new CtxVarDeclareIterator(sctx,
635 qloc,
636 args,
637 varExpr->get_unique_id(),
638 varExpr->get_name(),
639 varExpr->is_external(),
640 singleItem));
641 }
642
643
644 /***************************************************************************//**
645
646 ********************************************************************************/
begin_visit(var_set_expr & v)647 bool begin_visit(var_set_expr& v)
648 {
649 CODEGEN_TRACE_IN("");
650 return true;
651 }
652
653
end_visit(var_set_expr & v)654 void end_visit(var_set_expr& v)
655 {
656 CODEGEN_TRACE_OUT("");
657
658 const var_expr* varExpr = v.get_var_expr();
659
660 xqtref_t exprType = v.get_expr()->get_return_type();
661
662 PlanIter_t exprIter = pop_itstack();
663
664 CtxVarAssignIterator* iter =
665 new CtxVarAssignIterator(sctx,
666 qloc,
667 varExpr->get_unique_id(),
668 varExpr->get_name(),
669 (varExpr->get_kind() == var_expr::local_var),
670 exprIter);
671
672 if (exprType->get_quantifier() == TypeConstants::QUANT_ONE)
673 iter->setSingleItem();
674
675 push_itstack(iter);
676 }
677
678
679 /*******************************************************************************
680 VarRef expr
681 ********************************************************************************/
682
begin_visit(var_expr & v)683 bool begin_visit(var_expr& v)
684 {
685 CODEGEN_TRACE_IN("");
686 return true;
687 }
688
689
end_visit(var_expr & v)690 void end_visit(var_expr& v)
691 {
692 CODEGEN_TRACE_OUT("");
693
694 general_var_codegen(v);
695 }
696
697
698 template<class Iter>
base_var_codegen(const var_expr & var,hash64map<std::vector<rchandle<Iter>> * > & varMap)699 PlanIter_t base_var_codegen(
700 const var_expr& var,
701 hash64map<std::vector<rchandle<Iter> > *>& varMap)
702 {
703 std::vector<rchandle<Iter> >* varRefs = NULL;
704 bool bound = varMap.get((uint64_t) &var, varRefs);
705 ZORBA_ASSERT(bound);
706
707 Iter* iter = new Iter(var.get_sctx(), var.get_loc(), var.get_name());
708
709 varRefs->push_back(iter);
710
711 return iter;
712 }
713
714
create_var_iter(const var_expr & var,bool forvar)715 PlanIter_t create_var_iter(const var_expr& var, bool forvar)
716 {
717 PlanIter_t iter;
718 if (forvar)
719 {
720 iter = new ForVarIterator(var.get_sctx(), var.get_loc(), var.get_name());
721 }
722 else
723 {
724 iter = new LetVarIterator(var.get_sctx(), var.get_loc(), var.get_name());
725 }
726 return iter;
727 }
728
729
general_var_codegen(const var_expr & var)730 void general_var_codegen(const var_expr& var)
731 {
732 const QueryLoc& qloc = var.get_loc();
733 static_context* sctx = var.get_sctx();
734
735 bool isForVar = false;
736
737 switch (var.get_kind())
738 {
739 case var_expr::for_var:
740 case var_expr::pos_var:
741 case var_expr::wincond_out_var:
742 case var_expr::wincond_out_pos_var:
743 case var_expr::groupby_var:
744 case var_expr::count_var:
745
746 case var_expr::wincond_in_var:
747 case var_expr::wincond_in_pos_var:
748 {
749 isForVar = true;
750 // fall through
751 }
752
753 case var_expr::let_var:
754 case var_expr::win_var:
755 case var_expr::non_groupby_var:
756 {
757 ZORBA_ASSERT(!theClauseStack.empty());
758
759 long stackSize = (long)theClauseStack.size();
760 long varPos;
761 VarRebind_t varRebind;
762 PlanIter_t varIter;
763
764 // Look for the inner-most clause C that knows about this variable. C is
765 // either the clause D_C that defines the var, or the inner-most orderby
766 // or materialize clause the comes after D_C and rebinds the var to its
767 // output.
768 long i = stackSize - 1;
769 while(true)
770 {
771 if ((varPos = theClauseStack[i]->find_var(&var)) >= 0)
772 break;
773
774 --i;
775 ZORBA_ASSERT(i >= 0);
776 }
777
778 // Create a var ref iter in the output of C.
779 varIter = create_var_iter(var, isForVar);
780
781 FlworClauseVarMap* clauseVarMap = theClauseStack[i];
782
783 flwor_expr* flworExpr = clauseVarMap->theClause->get_flwor_expr();
784
785 clauseVarMap->theVarRebinds[varPos]->theOutputVarRefs.push_back(varIter);
786
787 if (clauseVarMap->theIsGeneral || flworExpr->is_sequential())
788 {
789 // For each orderby or materialize clause O after C, bind the var iter
790 // created by the previous clause to the input of O, and then create a new
791 // var iter and put it to the output of O.
792 for (++i; i < stackSize; ++i)
793 {
794 clauseVarMap = theClauseStack[i];
795
796 ZORBA_ASSERT(clauseVarMap->find_var(&var) < 0);
797
798 if (flworExpr == clauseVarMap->theClause->get_flwor_expr() &&
799 ((clauseVarMap->theClause->get_kind() == flwor_clause::order_clause &&
800 flworExpr->is_general()) ||
801 clauseVarMap->theClause->get_kind() == flwor_clause::materialize_clause))
802 {
803 varRebind = new VarRebind;
804
805 clauseVarMap->theVarExprs.push_back(const_cast<var_expr*>(&var));
806 clauseVarMap->theVarRebinds.push_back(varRebind);
807
808 varRebind->theInputVar = varIter;
809
810 varIter = create_var_iter(var, isForVar);
811
812 varRebind->theOutputVarRefs.push_back(varIter);
813 }
814 }
815 }
816
817 push_itstack(varIter);
818 break;
819 }
820
821 case var_expr::arg_var:
822 {
823 PlanIter_t iter = base_var_codegen(var, *arg_var_iter_map);
824 push_itstack(iter);
825 break;
826 }
827
828 case var_expr::catch_var:
829 {
830 PlanIter_t iter = base_var_codegen(var, catchvar_iter_map);
831 push_itstack(iter);
832 break;
833 }
834
835 case var_expr::copy_var:
836 {
837 PlanIter_t iter = base_var_codegen(var, copy_var_iter_map);
838 push_itstack(iter);
839 break;
840 }
841
842 case var_expr::prolog_var:
843 {
844 push_itstack(new CtxVarIterator(sctx,
845 qloc,
846 var.get_unique_id(),
847 var.get_name(),
848 false));
849 break;
850 }
851 case var_expr::local_var:
852 {
853 push_itstack(new CtxVarIterator(sctx,
854 qloc,
855 var.get_unique_id(),
856 var.get_name(),
857 true));
858 break;
859 }
860
861 case var_expr::unknown_var:
862 case var_expr::eval_var:
863 case var_expr::score_var:
864 {
865 ZORBA_ASSERT(false);
866 break;
867 }
868 }
869 }
870
871
872 /*******************************************************************************
873 FLWOR expr
874 ********************************************************************************/
begin_visit(flwor_expr & v)875 bool begin_visit(flwor_expr& v)
876 {
877 CODEGEN_TRACE_IN("");
878
879 bool isGeneral = v.is_general();
880
881 csize numClauses = v.num_clauses();
882
883 if (v.is_sequential())
884 {
885 if (!isGeneral)
886 {
887 if (v.has_sequential_clauses())
888 {
889 csize numForClauses = 0;
890
891 for (csize i = 0; i < numClauses; ++i)
892 {
893 const flwor_clause* c = v.get_clause(i);
894
895 if (c->get_kind() == flwor_clause::for_clause)
896 {
897 ++numForClauses;
898
899 if (c->get_expr()->is_sequential())
900 {
901 // TODO: do not convert to general flwor if the whole flwor consists
902 // of a single FOR followed by RETURN.
903 isGeneral = true;
904 v.set_general(true);
905 break;
906 }
907 }
908 else if (c->get_kind() == flwor_clause::let_clause)
909 {
910 if (c->get_expr()->is_sequential())
911 {
912 if (numForClauses > 0)
913 {
914 isGeneral = true;
915 v.set_general(true);
916 break;
917 }
918 }
919 }
920 else
921 {
922 break;
923 }
924 }
925 }
926
927 // Note: a materialize clause may exist already in case plan serialization
928 // is on (see comment in materialize_clause::clone)
929 if (!isGeneral &&
930 v.get_return_expr()->is_sequential() &&
931 v.get_clause(numClauses-1)->get_kind() != flwor_clause::materialize_clause &&
932 (v.get_order_clause() != NULL || v.get_group_clause() == NULL))
933 {
934 materialize_clause* mat =
935 theCCB->theEM->create_materialize_clause(v.get_sctx(),
936 v.get_return_expr()->get_loc());
937
938 v.add_clause(mat);
939 ++numClauses;
940 }
941 } // !isGeneral
942
943 if (isGeneral)
944 {
945 std::vector<OrderModifier> modifiers;
946 std::vector<expr*> orderingExprs;
947
948 csize numForClauses = 0;
949 csize i = 0;
950
951 while (i < numClauses)
952 {
953 const flwor_clause* c = v.get_clause(i);
954
955 flwor_clause::ClauseKind k = c->get_kind();
956
957 switch (k)
958 {
959 case flwor_clause::for_clause:
960 case flwor_clause::let_clause:
961 case flwor_clause::window_clause:
962 {
963 if (k == flwor_clause::for_clause || k == flwor_clause::window_clause)
964 {
965 xqtref_t domainType = c->get_expr()->get_return_type();
966 if (domainType->get_quantifier() != TypeConstants::QUANT_ONE)
967 ++numForClauses;
968 }
969
970 if (c->get_expr()->is_sequential())
971 {
972 if (k == flwor_clause::for_clause ||
973 k == flwor_clause::window_clause ||
974 numForClauses > 0)
975 {
976 theCCB->theXQueryDiagnostics->add_warning(
977 NEW_XQUERY_WARNING(zwarn::ZWST0004_AMBIGUOUS_SEQUENTIAL_FLWOR,
978 WARN_LOC(c->get_loc())));
979
980 if (i > 0 &&
981 v.get_clause(i-1)->get_kind() != flwor_clause::order_clause &&
982 v.get_clause(i-1)->get_kind() != flwor_clause::group_clause)
983 {
984 orderby_clause* mat =
985 theCCB->theEM->create_orderby_clause(v.get_sctx(),
986 c->get_loc(),
987 true,
988 modifiers,
989 orderingExprs);
990
991 v.add_clause(i, mat);
992 ++i;
993 ++numClauses;
994 }
995
996 if (i == numClauses -1 ||
997 (i < numClauses - 1 &&
998 v.get_clause(i+1)->get_kind() != flwor_clause::group_clause))
999 {
1000 orderby_clause* mat =
1001 theCCB->theEM->create_orderby_clause(v.get_sctx(),
1002 c->get_loc(),
1003 true,
1004 modifiers,
1005 orderingExprs);
1006
1007 v.add_clause(i+1, mat);
1008 ++numClauses;
1009 }
1010 }
1011 }
1012
1013 break;
1014 }
1015 case flwor_clause::where_clause:
1016 case flwor_clause::group_clause:
1017 case flwor_clause::order_clause:
1018 case flwor_clause::count_clause:
1019 {
1020 break;
1021 }
1022 default:
1023 ZORBA_ASSERT(false);
1024 }
1025
1026 ++i;
1027 }
1028
1029 const flwor_clause* lastClause = v.get_clause(v.num_clauses()-1);
1030
1031 if (v.get_return_expr()->is_sequential() &&
1032 lastClause->get_kind() != flwor_clause::order_clause &&
1033 lastClause->get_kind() != flwor_clause::group_clause)
1034 {
1035 orderby_clause* mat =
1036 theCCB->theEM->create_orderby_clause(v.get_sctx(),
1037 v.get_return_expr()->get_loc(),
1038 true,
1039 modifiers,
1040 orderingExprs);
1041
1042 v.add_clause(mat);
1043 ++numClauses;
1044 }
1045 }
1046 }
1047
1048 for (csize i = 0; i < numClauses; ++i)
1049 {
1050 const flwor_clause* c = v.get_clause(i);
1051
1052 switch (c->get_kind())
1053 {
1054
1055 case flwor_clause::for_clause:
1056 {
1057 visit_flwor_clause(c, isGeneral);
1058
1059 const for_clause* fc = reinterpret_cast<const for_clause*>(c);
1060 fc->get_expr()->accept(*this);
1061 break;
1062 }
1063
1064 case flwor_clause::let_clause:
1065 {
1066 visit_flwor_clause(c, isGeneral);
1067
1068 const for_clause* fc = reinterpret_cast<const for_clause*>(c);
1069 fc->get_expr()->accept(*this);
1070 break;
1071 }
1072
1073 case flwor_clause::window_clause:
1074 {
1075 visit_flwor_clause(c, isGeneral);
1076
1077 const window_clause* wc = reinterpret_cast<const window_clause*>(c);
1078
1079 flwor_wincond* startCond = wc->get_win_start();
1080 flwor_wincond* stopCond = wc->get_win_stop();
1081
1082 if (startCond)
1083 startCond->get_cond()->accept(*this);
1084
1085 if (stopCond)
1086 stopCond->get_cond()->accept(*this);
1087
1088 wc->get_expr()->accept(*this);
1089
1090 break;
1091 }
1092
1093 case flwor_clause::group_clause:
1094 {
1095 const group_clause* gc = reinterpret_cast<const group_clause*>(c);
1096
1097 const flwor_clause::rebind_list_t& gvars = gc->get_grouping_vars();
1098 const flwor_clause::rebind_list_t& ngvars = gc->get_nongrouping_vars();
1099
1100 for (ulong i = 0; i < gvars.size(); ++i)
1101 {
1102 gvars[i].first->accept(*this);
1103 }
1104
1105 for (ulong i = 0; i < ngvars.size(); ++i)
1106 {
1107 ngvars[i].first->accept(*this);
1108 }
1109
1110 visit_flwor_clause(c, isGeneral);
1111
1112 break;
1113 }
1114
1115 case flwor_clause::order_clause:
1116 {
1117 const orderby_clause* oc = reinterpret_cast<const orderby_clause*>(c);
1118
1119 ulong numCols = oc->num_columns();
1120 for (ulong i = 0; i < numCols; ++i)
1121 {
1122 oc->get_column_expr(i)->accept(*this);
1123 }
1124
1125 visit_flwor_clause(c, isGeneral);
1126
1127 break;
1128 }
1129
1130 case flwor_clause::materialize_clause:
1131 {
1132 visit_flwor_clause(c, isGeneral);
1133
1134 break;
1135 }
1136
1137 case flwor_clause::count_clause:
1138 {
1139 visit_flwor_clause(c, isGeneral);
1140 break;
1141 }
1142
1143 case flwor_clause::where_clause:
1144 {
1145 const where_clause* wc = reinterpret_cast<const where_clause*>(c);
1146 wc->get_expr()->accept(*this);
1147 break;
1148 }
1149 default:
1150 ZORBA_ASSERT(false);
1151 }
1152 }
1153
1154 v.get_return_expr()->accept(*this);
1155
1156 // Do not visit the children of this flwor expr; this was done already by
1157 // this method
1158 return false;
1159 }
1160
1161
end_visit(flwor_expr & v)1162 void end_visit(flwor_expr& v)
1163 {
1164 CODEGEN_TRACE_OUT("");
1165
1166 if (!v.is_general())
1167 {
1168 flwor_codegen(v);
1169 }
1170 else
1171 {
1172 PlanIter_t ret = pop_itstack();
1173
1174 PlanIter_t gflwor = gflwor_codegen(v, v.num_clauses() - 1);
1175
1176 push_itstack(new flwor::TupleStreamIterator(sctx, qloc, gflwor, ret, false));
1177 }
1178 }
1179
1180
visit_flwor_clause(const flwor_clause * c,bool general)1181 void visit_flwor_clause(const flwor_clause* c, bool general)
1182 {
1183 if (c->get_kind() == flwor_clause::where_clause)
1184 return;
1185
1186 FlworClauseVarMap_t clauseVarMap = new FlworClauseVarMap(c, general);
1187
1188 switch (c->get_kind())
1189 {
1190 case flwor_clause::for_clause:
1191 {
1192 const for_clause* fc = static_cast<const for_clause *>(c);
1193
1194 VarRebind_t varRebind = new VarRebind;
1195 clauseVarMap->theVarExprs.push_back(fc->get_var());
1196 clauseVarMap->theVarRebinds.push_back(varRebind);
1197
1198 if (fc->get_pos_var() != NULL)
1199 {
1200 varRebind = new VarRebind;
1201 clauseVarMap->theVarExprs.push_back(fc->get_pos_var());
1202 clauseVarMap->theVarRebinds.push_back(varRebind);
1203 }
1204
1205 break;
1206 }
1207
1208 case flwor_clause::let_clause:
1209 {
1210 const let_clause* lc = static_cast<const let_clause *>(c);
1211
1212 VarRebind_t varRebind = new VarRebind;
1213 clauseVarMap->theVarExprs.push_back(lc->get_var());
1214 clauseVarMap->theVarRebinds.push_back(varRebind);
1215
1216 break;
1217 }
1218
1219 case flwor_clause::window_clause:
1220 {
1221 const window_clause* wc = static_cast<const window_clause *>(c);
1222
1223 VarRebind_t varRebind = new VarRebind;
1224 clauseVarMap->theVarExprs.push_back(wc->get_var());
1225 clauseVarMap->theVarRebinds.push_back(varRebind);
1226
1227 init_wincond_var_maps(wc->get_win_stop(), clauseVarMap);
1228 init_wincond_var_maps(wc->get_win_start(), clauseVarMap);
1229
1230 break;
1231 }
1232
1233 case flwor_clause::group_clause:
1234 {
1235 const group_clause* gbc = static_cast<const group_clause *>(c);
1236 const group_clause::rebind_list_t& grouping_vars = gbc->get_grouping_vars();
1237 const group_clause::rebind_list_t& nongrouping_vars = gbc->get_nongrouping_vars();
1238
1239 for (unsigned i = 0; i < grouping_vars.size(); ++i)
1240 {
1241 VarRebind_t varRebind = new VarRebind;
1242 clauseVarMap->theVarExprs.push_back(grouping_vars[i].second);
1243 clauseVarMap->theVarRebinds.push_back(varRebind);
1244 }
1245
1246 for (unsigned i = 0; i < nongrouping_vars.size(); ++i)
1247 {
1248 VarRebind_t varRebind = new VarRebind;
1249 clauseVarMap->theVarExprs.push_back(nongrouping_vars[i].second);
1250 clauseVarMap->theVarRebinds.push_back(varRebind);
1251 }
1252
1253 break;
1254 }
1255
1256 case flwor_clause::order_clause:
1257 case flwor_clause::materialize_clause:
1258 {
1259 break;
1260 }
1261
1262 case flwor_clause::count_clause:
1263 {
1264 const count_clause* cl = static_cast<const count_clause *>(c);
1265
1266 VarRebind_t varRebind = new VarRebind;
1267 clauseVarMap->theVarExprs.push_back(cl->get_var());
1268 clauseVarMap->theVarRebinds.push_back(varRebind);
1269
1270 break;
1271 }
1272
1273 default:
1274 ZORBA_ASSERT(false);
1275 }
1276
1277 if (clauseVarMap != NULL)
1278 theClauseStack.push_back(clauseVarMap);
1279 }
1280
1281
init_wincond_var_maps(const flwor_wincond * cond,FlworClauseVarMap * clauseVarMap)1282 void init_wincond_var_maps(
1283 const flwor_wincond* cond,
1284 FlworClauseVarMap* clauseVarMap)
1285 {
1286 if (cond == NULL)
1287 return;
1288
1289 const flwor_wincond::vars& inVars = cond->get_in_vars();
1290 const flwor_wincond::vars& outVars = cond->get_out_vars();
1291
1292 if (inVars.posvar != NULL)
1293 {
1294 VarRebind_t varRebind = new VarRebind;
1295 clauseVarMap->theVarExprs.push_back(inVars.posvar);
1296 clauseVarMap->theVarRebinds.push_back(varRebind);
1297 }
1298
1299 if (inVars.curr != NULL)
1300 {
1301 VarRebind_t varRebind = new VarRebind;
1302 clauseVarMap->theVarExprs.push_back(inVars.curr);
1303 clauseVarMap->theVarRebinds.push_back(varRebind);
1304 }
1305
1306 if (inVars.prev != NULL)
1307 {
1308 VarRebind_t varRebind = new VarRebind;
1309 clauseVarMap->theVarExprs.push_back(inVars.prev);
1310 clauseVarMap->theVarRebinds.push_back(varRebind);
1311 }
1312
1313 if (inVars.next != NULL)
1314 {
1315 VarRebind_t varRebind = new VarRebind;
1316 clauseVarMap->theVarExprs.push_back(inVars.next);
1317 clauseVarMap->theVarRebinds.push_back(varRebind);
1318 }
1319
1320 if (outVars.posvar != NULL)
1321 {
1322 VarRebind_t varRebind = new VarRebind;
1323 clauseVarMap->theVarExprs.push_back(outVars.posvar);
1324 clauseVarMap->theVarRebinds.push_back(varRebind);
1325 }
1326
1327 if (outVars.curr != NULL)
1328 {
1329 VarRebind_t varRebind = new VarRebind;
1330 clauseVarMap->theVarExprs.push_back(outVars.curr);
1331 clauseVarMap->theVarRebinds.push_back(varRebind);
1332 }
1333
1334 if (outVars.prev != NULL)
1335 {
1336 VarRebind_t varRebind = new VarRebind;
1337 clauseVarMap->theVarExprs.push_back(outVars.prev);
1338 clauseVarMap->theVarRebinds.push_back(varRebind);
1339 }
1340
1341 if (outVars.next != NULL)
1342 {
1343 VarRebind_t varRebind = new VarRebind;
1344 clauseVarMap->theVarExprs.push_back(outVars.next);
1345 clauseVarMap->theVarRebinds.push_back(varRebind);
1346 }
1347 }
1348
1349
1350 struct wincond_var_iters
1351 {
1352 std::vector<PlanIter_t> * inPos;
1353 std::vector<PlanIter_t> * inCurr;
1354 std::vector<PlanIter_t> * inPrev;
1355 std::vector<PlanIter_t> * inNext;
1356
1357 std::vector<PlanIter_t> * outPos;
1358 std::vector<PlanIter_t> * outCurr;
1359 std::vector<PlanIter_t> * outPrev;
1360 std::vector<PlanIter_t> * outNext;
1361
wincond_var_iterszorba::plan_visitor::wincond_var_iters1362 wincond_var_iters(
1363 const flwor_wincond* cond,
1364 FlworClauseVarMap* clauseVarMap,
1365 ulong& varPos)
1366 {
1367 const flwor_wincond::vars& inVars = cond->get_in_vars();
1368 const flwor_wincond::vars& outVars = cond->get_out_vars();
1369
1370 inPos = ((inVars.posvar != NULL) ?
1371 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1372 &plan_visitor::no_var_iters);
1373
1374 inCurr = (inVars.curr != NULL ?
1375 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1376 &plan_visitor::no_var_iters);
1377
1378 inPrev = (inVars.prev != NULL ?
1379 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1380 &plan_visitor::no_var_iters);
1381
1382 inNext = (inVars.next != NULL ?
1383 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1384 &plan_visitor::no_var_iters);
1385
1386 outPos = (outVars.posvar != NULL ?
1387 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1388 &plan_visitor::no_var_iters);
1389
1390 outCurr = (outVars.curr != NULL ?
1391 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1392 &plan_visitor::no_var_iters);
1393
1394 outPrev = (outVars.prev != NULL ?
1395 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1396 &plan_visitor::no_var_iters);
1397
1398 outNext = (outVars.next != NULL ?
1399 &clauseVarMap->theVarRebinds[varPos++]->theOutputVarRefs :
1400 &plan_visitor::no_var_iters);
1401 }
1402 };
1403
1404
nativeColumnSort(expr * colExpr)1405 bool nativeColumnSort(expr* colExpr)
1406 {
1407 const QueryLoc& loc = colExpr->get_loc();
1408 TypeManager* tm = colExpr->get_type_manager();
1409 RootTypeManager& rtm = GENV_TYPESYSTEM;
1410
1411 xqtref_t colType = colExpr->get_return_type();
1412
1413 if (colType->type_kind() == XQType::NODE_TYPE_KIND)
1414 {
1415 colType = static_cast<const NodeXQType*>(colType.getp())->get_content_type();
1416 }
1417
1418 if (colType != NULL &&
1419 TypeOps::is_subtype(tm, *colType, *rtm.ANY_ATOMIC_TYPE_STAR, loc) &&
1420 !TypeOps::is_equal(tm,
1421 *TypeOps::prime_type(tm, *colType),
1422 *rtm.ANY_ATOMIC_TYPE_ONE,
1423 loc))
1424 {
1425 return true;
1426 }
1427
1428 return false;
1429 }
1430
1431
gflwor_codegen(flwor_expr & flworExpr,int currentClause)1432 PlanIter_t gflwor_codegen(flwor_expr& flworExpr, int currentClause)
1433 {
1434 #define PREV_ITER gflwor_codegen(flworExpr, currentClause - 1)
1435
1436 const QueryLoc& qloc = flworExpr.get_loc();
1437
1438 static_context* sctx = flworExpr.get_sctx();
1439
1440 if (currentClause < 0)
1441 {
1442 return new flwor::TupleSourceIterator(sctx, qloc);
1443 }
1444
1445 const flwor_clause& c = *(flworExpr.get_clause(currentClause));
1446
1447 FlworClauseVarMap_t clauseVarMap;
1448
1449 if (c.get_kind() != flwor_clause::where_clause)
1450 {
1451 ZORBA_ASSERT(!theClauseStack.empty());
1452 ulong stackSize = (ulong)theClauseStack.size();
1453
1454 clauseVarMap = theClauseStack[stackSize-1];
1455 theClauseStack.resize(stackSize - 1);
1456
1457 ZORBA_ASSERT(clauseVarMap->theClause == &c);
1458 }
1459
1460 //
1461 // WHERE
1462 //
1463 if (c.get_kind() == flwor_clause::where_clause)
1464 {
1465 PlanIter_t where = pop_itstack();
1466 PlanIter_t input = PREV_ITER;
1467 return new flwor::WhereIterator(sctx, c.get_loc(), input, where);
1468 }
1469
1470 //
1471 // FOR
1472 //
1473 else if (c.get_kind() == flwor_clause::for_clause)
1474 {
1475 const for_clause* fc = static_cast<const for_clause *>(&c);
1476
1477 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() >= 1);
1478
1479 var_expr* var = fc->get_var();
1480
1481 PlanIter_t domainIter = pop_itstack();
1482
1483 std::vector<PlanIter_t>& varRefs = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1484 std::vector<PlanIter_t>* posVarRefs = &no_var_iters;
1485
1486 if (fc->get_pos_var())
1487 {
1488 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 2);
1489
1490 posVarRefs = &clauseVarMap->theVarRebinds[1]->theOutputVarRefs;
1491 }
1492
1493 if (fc->is_allowing_empty())
1494 return new flwor::OuterForIterator(sctx, var->get_loc(), var->get_name(),
1495 PREV_ITER, domainIter, varRefs,*posVarRefs);
1496 else
1497 return new flwor::ForIterator(sctx, var->get_loc(), var->get_name(),
1498 PREV_ITER, domainIter, varRefs, *posVarRefs);
1499 }
1500
1501 //
1502 // LET
1503 //
1504 else if (c.get_kind() == flwor_clause::let_clause)
1505 {
1506 const let_clause* lc = static_cast<const let_clause *>(&c);
1507
1508 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1509
1510 var_expr* var = lc->get_var();
1511
1512 PlanIter_t domainIter = pop_itstack();
1513
1514 std::vector<PlanIter_t>& varRefs = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1515
1516 return new flwor::LetIterator(sctx,
1517 var->get_loc(),
1518 var->get_name(),
1519 PREV_ITER,
1520 domainIter,
1521 varRefs,
1522 lc->lazyEval(),
1523 true); // materilize
1524 }
1525
1526 //
1527 // WINDOW
1528 //
1529 else if (c.get_kind() == flwor_clause::window_clause)
1530 {
1531 const window_clause* wc = static_cast<const window_clause *>(&c);
1532
1533 var_expr* var = wc->get_var();
1534 PlanIter_t domainIter = pop_itstack();
1535
1536 std::vector<PlanIter_t>& varRefs = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1537
1538 std::auto_ptr<flwor::StartClause> start_clause;
1539 std::auto_ptr<flwor::EndClause> end_clause;
1540 const flwor_wincond* cond;
1541 ulong varPos = 1;
1542
1543 if (NULL == (cond = wc->get_win_stop()))
1544 {
1545 end_clause.reset(new flwor::EndClause);
1546 }
1547 else
1548 {
1549 wincond_var_iters wcv(cond, clauseVarMap, varPos);
1550
1551 flwor::WindowVars wvars(*wcv.inCurr, *wcv.inPrev, *wcv.inNext, *wcv.inPos,
1552 *wcv.outCurr, *wcv.outPrev, *wcv.outNext, *wcv.outPos);
1553
1554 end_clause.reset(new flwor::EndClause(pop_itstack(), wvars, cond->is_only()));
1555 }
1556
1557 if (NULL != (cond = wc->get_win_start()))
1558 {
1559 wincond_var_iters wcv(cond, clauseVarMap, varPos);
1560
1561 flwor::WindowVars wvars(*wcv.inCurr, *wcv.inPrev, *wcv.inNext, *wcv.inPos,
1562 *wcv.outCurr, *wcv.outPrev, *wcv.outNext, *wcv.outPos);
1563
1564 start_clause.reset(new flwor::StartClause(pop_itstack(), wvars));
1565 }
1566
1567 return new flwor::WindowIterator(sctx,
1568 var->get_loc(),
1569 wc->get_winkind() == window_clause::tumbling_window ? flwor::WindowIterator::TUMBLING : flwor::WindowIterator::SLIDING,
1570 PREV_ITER,
1571 domainIter,
1572 var->get_name(),
1573 varRefs,
1574 *start_clause,
1575 *end_clause,
1576 wc->lazyEval());
1577 }
1578
1579 //
1580 // COUNT
1581 //
1582 else if (c.get_kind() == flwor_clause::count_clause)
1583 {
1584 var_expr* var = static_cast<const count_clause *>(&c)->get_var();
1585
1586 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1587
1588 std::vector<PlanIter_t>& var_iters = clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1589
1590 return new flwor::CountIterator(sctx,
1591 var->get_loc(),
1592 var->get_name(),
1593 PREV_ITER,
1594 var_iters);
1595 }
1596
1597 //
1598 // ORDERBY
1599 //
1600 else if (c.get_kind() == flwor_clause::order_clause)
1601 {
1602 ulong numVars = (ulong)clauseVarMap->theVarRebinds.size();
1603 ulong numForVars = 0;
1604 ulong numLetVars = 0;
1605
1606 std::vector<ForVarIter_t> inputForVars(numVars);
1607 std::vector<LetVarIter_t> inputLetVars(numVars);
1608 std::vector<std::vector<PlanIter_t> > outputForVarsRefs(numVars);
1609 std::vector<std::vector<PlanIter_t> > outputLetVarsRefs(numVars);
1610
1611 for (ulong i = 0; i < numVars; ++i)
1612 {
1613 VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp();
1614
1615 ForVarIterator* forIter = dynamic_cast<ForVarIterator*>
1616 (varRebind->theInputVar.getp());
1617
1618 if (forIter != NULL)
1619 {
1620 inputForVars[numForVars] = forIter;
1621
1622 outputForVarsRefs[numForVars] = varRebind->theOutputVarRefs;
1623 ++numForVars;
1624 }
1625 else
1626 {
1627 LetVarIterator* letIter = dynamic_cast<LetVarIterator*>
1628 (varRebind->theInputVar.getp());
1629 ZORBA_ASSERT(letIter != NULL);
1630
1631 inputLetVars[numLetVars] = letIter;
1632
1633 outputLetVarsRefs[numLetVars] = varRebind->theOutputVarRefs;
1634 ++numLetVars;
1635 }
1636 }
1637
1638 inputForVars.resize(numForVars);
1639 outputForVarsRefs.resize(numForVars);
1640 inputLetVars.resize(numLetVars);
1641 outputLetVarsRefs.resize(numLetVars);
1642
1643 const orderby_clause* obc = static_cast<const orderby_clause *>(&c);
1644 ulong numColumns = obc->num_columns();
1645 const std::vector<OrderModifier>& modifiers = obc->get_modifiers();
1646
1647 std::vector<flwor::OrderSpec> orderSpecs(numColumns);
1648
1649 for (long i = numColumns - 1; i >= 0; --i)
1650 {
1651 bool emptyLeast = modifiers[i].theEmptyLeast;
1652 bool descending = !modifiers[i].theAscending;
1653
1654 orderSpecs[i] = flwor::OrderSpec(pop_itstack(),
1655 emptyLeast,
1656 descending,
1657 nativeColumnSort(obc->get_column_expr(i)),
1658 modifiers[i].theCollation);
1659 }
1660
1661 return new flwor::OrderByIterator(sctx,
1662 c.get_loc(),
1663 obc->is_stable(),
1664 orderSpecs,
1665 PREV_ITER,
1666 inputForVars,
1667 inputLetVars,
1668 outputForVarsRefs,
1669 outputLetVarsRefs);
1670 }
1671
1672 //
1673 // GROUPBY
1674 //
1675 else if (c.get_kind() == flwor_clause::group_clause)
1676 {
1677 std::vector<flwor::GroupingSpec> gspecs;
1678 std::vector<flwor::NonGroupingSpec> ngspecs;
1679
1680 generate_groupby(clauseVarMap, gspecs, ngspecs);
1681
1682 return new flwor::GroupByIterator(sctx, c.get_loc(), PREV_ITER, gspecs, ngspecs);
1683 }
1684
1685 ZORBA_ASSERT (false);
1686 return NULL;
1687 #undef PREV_ITER
1688 }
1689
1690
flwor_codegen(const flwor_expr & flworExpr)1691 void flwor_codegen(const flwor_expr& flworExpr)
1692 {
1693 flwor::FLWORIterator* flworIter;
1694 PlanIter_t returnIter;
1695 std::auto_ptr<flwor::OrderByClause> orderClause(NULL);
1696 std::auto_ptr<flwor::GroupByClause> groupClause(NULL);
1697 std::auto_ptr<flwor::MaterializeClause> materializeClause(NULL);
1698 PlanIter_t whereIter;
1699 std::vector<flwor::ForLetClause> forletClauses;
1700
1701 csize numClauses = flworExpr.num_clauses();
1702
1703 returnIter = pop_itstack();
1704
1705 for (int it = numClauses - 1; it >= 0; --it)
1706 {
1707 const flwor_clause& c = *flworExpr.get_clause(it);
1708
1709 FlworClauseVarMap_t clauseVarMap;
1710
1711 if (c.get_kind() != flwor_clause::where_clause)
1712 {
1713 ZORBA_ASSERT(!theClauseStack.empty());
1714 csize stackSize = theClauseStack.size();
1715
1716 clauseVarMap = theClauseStack[stackSize-1];
1717 theClauseStack.resize(stackSize - 1);
1718
1719 ZORBA_ASSERT(clauseVarMap->theClause == &c);
1720 }
1721
1722 switch (c.get_kind())
1723 {
1724 //
1725 // MATERIALIZE
1726 //
1727 case flwor_clause::materialize_clause:
1728 {
1729 ulong numVars = (ulong)clauseVarMap->theVarRebinds.size();
1730 ulong numForVars = 0;
1731 ulong numLetVars = 0;
1732
1733 std::vector<ForVarIter_t> inputForVars(numVars);
1734 std::vector<LetVarIter_t> inputLetVars(numVars);
1735 std::vector<std::vector<PlanIter_t> > outputForVarsRefs(numVars);
1736 std::vector<std::vector<PlanIter_t> > outputLetVarsRefs(numVars);
1737
1738 for (ulong i = 0; i < numVars; ++i)
1739 {
1740 VarRebind* varRebind = clauseVarMap->theVarRebinds[i];
1741
1742 ForVarIterator* forIter = dynamic_cast<ForVarIterator*>
1743 (varRebind->theInputVar.getp());
1744
1745 if (forIter != NULL)
1746 {
1747 inputForVars[numForVars] = forIter;
1748
1749 outputForVarsRefs[numForVars] = varRebind->theOutputVarRefs;
1750 ++numForVars;
1751 }
1752 else
1753 {
1754 LetVarIterator* letIter = dynamic_cast<LetVarIterator*>
1755 (varRebind->theInputVar.getp());
1756 ZORBA_ASSERT(letIter != NULL);
1757
1758 inputLetVars[numLetVars] = letIter;
1759
1760 outputLetVarsRefs[numLetVars] = varRebind->theOutputVarRefs;
1761 ++numLetVars;
1762 }
1763 }
1764
1765 inputForVars.resize(numForVars);
1766 outputForVarsRefs.resize(numForVars);
1767 inputLetVars.resize(numLetVars);
1768 outputLetVarsRefs.resize(numLetVars);
1769
1770 materializeClause.reset(new flwor::MaterializeClause(c.get_loc(),
1771 inputForVars,
1772 inputLetVars,
1773 outputForVarsRefs,
1774 outputLetVarsRefs));
1775
1776 break;
1777 }
1778
1779 //
1780 // ORDERBY
1781 //
1782 case flwor_clause::order_clause:
1783 {
1784 const orderby_clause* obc = static_cast<const orderby_clause*>(&c);
1785 unsigned numColumns = obc->num_columns();
1786 const std::vector<OrderModifier>& modifiers = obc->get_modifiers();
1787
1788 std::vector<flwor::OrderSpec> orderSpecs(numColumns);
1789
1790 for (int i = numColumns - 1; i >= 0; --i)
1791 {
1792 bool emptyLeast = modifiers[i].theEmptyLeast;
1793 bool descending = !modifiers[i].theAscending;
1794
1795 orderSpecs[i] = flwor::OrderSpec(pop_itstack(),
1796 emptyLeast,
1797 descending,
1798 nativeColumnSort(obc->get_column_expr(i)),
1799 modifiers[i].theCollation);
1800 }
1801
1802 orderClause.reset(new flwor::OrderByClause(obc->get_loc(),
1803 orderSpecs,
1804 obc->is_stable()));
1805 break;
1806 }
1807
1808 //
1809 // GROUPBY
1810 //
1811 case flwor_clause::group_clause:
1812 {
1813 std::vector<flwor::GroupingSpec> gspecs;
1814 std::vector<flwor::NonGroupingSpec> ngspecs;
1815
1816 generate_groupby(clauseVarMap, gspecs, ngspecs);
1817
1818 groupClause.reset(new flwor::GroupByClause(c.get_loc(), gspecs, ngspecs));
1819
1820 break;
1821 }
1822
1823 //
1824 // WHERE
1825 //
1826 case flwor_clause::where_clause:
1827 {
1828 whereIter = pop_itstack();
1829 break;
1830 }
1831
1832 //
1833 // FOR
1834 //
1835 case flwor_clause::for_clause:
1836 {
1837 const for_clause* fc = static_cast<const for_clause *>(&c);
1838
1839 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() >= 1);
1840
1841 var_expr* var = fc->get_var();
1842
1843 PlanIter_t domainIter = pop_itstack();
1844
1845 std::vector<PlanIter_t>& varRefs =
1846 clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1847
1848 if (fc->get_pos_var())
1849 {
1850 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 2);
1851
1852 std::vector<PlanIter_t>& posVarRefs =
1853 clauseVarMap->theVarRebinds[1]->theOutputVarRefs;
1854
1855 forletClauses.push_back(flwor::ForLetClause(var->get_name(),
1856 varRefs,
1857 posVarRefs,
1858 domainIter));
1859 }
1860 else
1861 {
1862 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1863
1864 forletClauses.push_back(flwor::ForLetClause(var->get_name(),
1865 varRefs,
1866 domainIter));
1867 }
1868
1869 break;
1870 }
1871
1872 //
1873 // LET
1874 //
1875 case flwor_clause::let_clause:
1876 {
1877 const let_clause* lc = static_cast<const let_clause *>(&c);
1878
1879 ZORBA_ASSERT(clauseVarMap->theVarRebinds.size() == 1);
1880
1881 var_expr* var = lc->get_var();
1882
1883 PlanIter_t domainIter = pop_itstack();
1884
1885 std::vector<PlanIter_t>& varRefs =
1886 clauseVarMap->theVarRebinds[0]->theOutputVarRefs;
1887
1888 forletClauses.push_back(flwor::ForLetClause(var->get_name(),
1889 varRefs,
1890 domainIter,
1891 lc->lazyEval(),
1892 true)); // materialize
1893 break;
1894 }
1895
1896 default:
1897 {
1898 ZORBA_ASSERT(false);
1899 }
1900 }
1901 }
1902
1903 std::reverse(forletClauses.begin(), forletClauses.end());
1904
1905 flworIter = new flwor::FLWORIterator(flworExpr.get_sctx(),
1906 flworExpr.get_loc(),
1907 forletClauses,
1908 whereIter,
1909 groupClause.release(),
1910 orderClause.release(),
1911 materializeClause.release(),
1912 returnIter);
1913 push_itstack(flworIter);
1914 }
1915
1916
generate_groupby(const FlworClauseVarMap * clauseVarMap,std::vector<flwor::GroupingSpec> & gspecs,std::vector<flwor::NonGroupingSpec> & ngspecs)1917 void generate_groupby(
1918 const FlworClauseVarMap* clauseVarMap,
1919 std::vector<flwor::GroupingSpec>& gspecs,
1920 std::vector<flwor::NonGroupingSpec>& ngspecs)
1921 {
1922 const group_clause* gbc = static_cast<const group_clause*>(clauseVarMap->theClause);
1923
1924 const group_clause::rebind_list_t& gvars = gbc->get_grouping_vars();
1925 const group_clause::rebind_list_t& ngvars = gbc->get_nongrouping_vars();
1926
1927 const std::vector<std::string>& collations = gbc->get_collations();
1928
1929 long numVars = (long)(gvars.size() + ngvars.size());
1930 long numGroupVars = (long)gvars.size();
1931 long i = numVars - 1;
1932
1933 for (; i >= numGroupVars; --i)
1934 {
1935 VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp();
1936
1937 const std::vector<PlanIter_t>& varRefs = varRebind->theOutputVarRefs;
1938
1939 ngspecs.push_back(flwor::NonGroupingSpec(pop_itstack(), varRefs));
1940 }
1941
1942 for (; i >= 0; --i)
1943 {
1944 VarRebind* varRebind = clauseVarMap->theVarRebinds[i].getp();
1945
1946 const std::vector<PlanIter_t>& varRefs = varRebind->theOutputVarRefs;
1947
1948 bool fastComparison = nativeColumnSort(clauseVarMap->theVarExprs[i]);
1949
1950 gspecs.push_back(flwor::GroupingSpec(pop_itstack(),
1951 varRefs,
1952 collations[i],
1953 fastComparison));
1954 }
1955 }
1956
1957
1958 /*******************************************************************************
1959
1960 ********************************************************************************/
begin_visit(promote_expr & v)1961 bool begin_visit(promote_expr& v)
1962 {
1963 CODEGEN_TRACE_IN("");
1964 return true;
1965 }
1966
end_visit(promote_expr & v)1967 void end_visit(promote_expr& v)
1968 {
1969 CODEGEN_TRACE_OUT("");
1970 PlanIter_t child = pop_itstack();
1971 // TODO: Currently we use cast. Promotion may be more efficient.
1972 push_itstack(new PromoteIterator(sctx,
1973 qloc,
1974 child,
1975 v.get_target_type(),
1976 v.get_err(),
1977 v.get_qname()));
1978 }
1979
1980
1981 /***************************************************************************//**
1982
1983 ********************************************************************************/
begin_visit(trycatch_expr & v)1984 bool begin_visit(trycatch_expr& v)
1985 {
1986 CODEGEN_TRACE_IN("");
1987
1988 for(int i = v.clause_count() - 1; i >= 0; --i)
1989 {
1990 catch_clause* cc = const_cast<catch_clause*>(v[i]);
1991 catch_clause::var_map_t& vars = cc->get_vars();
1992
1993 for (catch_clause::var_map_t::const_iterator lIter = vars.begin();
1994 lIter != vars.end();
1995 ++lIter)
1996 {
1997 catchvar_iter_map.put((uint64_t)&*(lIter->second), new std::vector<LetVarIter_t>());
1998 }
1999 }
2000 return true;
2001 }
2002
end_visit(trycatch_expr & v)2003 void end_visit(trycatch_expr& v)
2004 {
2005 CODEGEN_TRACE_OUT("");
2006
2007 std::vector<LetVarIter_t> *vec = NULL;
2008 std::vector<TryCatchIterator::CatchClause> rev_ccs;
2009
2010 for(int i = v.clause_count() - 1; i >= 0; --i)
2011 {
2012 catch_clause* cc = const_cast<catch_clause*>(v[i]);
2013 TryCatchIterator::CatchClause rcc;
2014 rcc.node_names = cc->get_nametests();
2015 rcc.catch_expr = pop_itstack();
2016 catch_clause::var_map_t& vars = cc->get_vars();
2017
2018 for (catch_clause::var_map_t::const_iterator lIter = vars.begin();
2019 lIter != vars.end();
2020 ++lIter)
2021 {
2022 bool bound = catchvar_iter_map.get((uint64_t)&*(lIter->second), vec);
2023 ZORBA_ASSERT(bound);
2024 catch_clause::var_type var_type = (catch_clause::var_type)lIter->first;
2025
2026 switch (var_type)
2027 {
2028 case catch_clause::err_code:
2029 rcc.theVars[TryCatchIterator::CatchClause::err_code] = *vec;
2030 break;
2031 case catch_clause::err_desc:
2032 rcc.theVars[TryCatchIterator::CatchClause::err_desc] = *vec;
2033 break;
2034 case catch_clause::err_value:
2035 rcc.theVars[TryCatchIterator::CatchClause::err_value] = *vec;
2036 break;
2037 case catch_clause::err_module:
2038 rcc.theVars[TryCatchIterator::CatchClause::err_module] = *vec;
2039 break;
2040 case catch_clause::err_line_no:
2041 rcc.theVars[TryCatchIterator::CatchClause::err_line_no] = *vec;
2042 break;
2043 case catch_clause::err_column_no:
2044 rcc.theVars[TryCatchIterator::CatchClause::err_column_no] = *vec;
2045 break;
2046 case catch_clause::zerr_stack_trace:
2047 rcc.theVars[TryCatchIterator::CatchClause::zerr_stack_trace] = *vec;
2048 break;
2049 default:
2050 ZORBA_ASSERT(false);
2051 }
2052 }
2053
2054 rev_ccs.push_back(rcc);
2055 }
2056
2057 std::vector<TryCatchIterator::CatchClause> ccs(rev_ccs.rbegin(), rev_ccs.rend());
2058 PlanIter_t lChild = pop_itstack();
2059
2060 push_itstack(new TryCatchIterator(sctx, qloc, lChild, ccs));
2061 }
2062
2063
2064 /***************************************************************************//**
2065
2066 ********************************************************************************/
begin_visit(eval_expr & v)2067 bool begin_visit(eval_expr& v)
2068 {
2069 CODEGEN_TRACE_IN("");
2070 return true;
2071 }
2072
end_visit(eval_expr & v)2073 void end_visit(eval_expr& v)
2074 {
2075 CODEGEN_TRACE_OUT("");
2076
2077 csize numVars = v.num_vars();
2078
2079 checked_vector<PlanIter_t> args;
2080 args.reserve(numVars+1);
2081
2082 std::vector<int> isGlobalVar(numVars);
2083
2084 for (csize i = numVars; i > 0; --i)
2085 {
2086 isGlobalVar[i-1] = false;
2087
2088 expr* arg = v.get_arg_expr(i-1);
2089
2090 if (arg->get_expr_kind() == var_expr_kind)
2091 {
2092 var_expr* varArg = static_cast<var_expr*>(arg);
2093
2094 if (varArg->get_kind() == var_expr::prolog_var)
2095 isGlobalVar[i-1] = true;
2096 }
2097
2098 if (!isGlobalVar[i-1])
2099 {
2100 args.push_back(pop_itstack());
2101 }
2102 else
2103 {
2104 pop_itstack();
2105 }
2106 }
2107
2108 args.push_back(pop_itstack());
2109 reverse(args.begin(), args.end());
2110
2111 store::NsBindings localBindings;
2112 v.getNSCtx()->getAllBindings(localBindings);
2113
2114 push_itstack(new EvalIterator(sctx,
2115 qloc,
2116 args,
2117 v.get_var_names(),
2118 v.get_var_types(),
2119 isGlobalVar,
2120 v.get_inner_scripting_kind(),
2121 localBindings,
2122 v.getNodeCopy(),
2123 false));
2124 }
2125
2126 #ifdef ZORBA_WITH_DEBUGGER
begin_visit(debugger_expr & v)2127 bool begin_visit(debugger_expr& v)
2128 {
2129 CODEGEN_TRACE_IN("");
2130
2131 // already create the debugger iterator here
2132 // because it's used for connecting all debugger
2133 // iterators in the tree (see end_visit below)
2134 std::vector<PlanIter_t> aTmpVec;
2135 DebugIterator* lIterator = new DebugIterator(sctx, qloc, aTmpVec);
2136 lIterator->setVarDeclaration(v.isVarDeclaration());
2137 theDebuggerStack.push(lIterator);
2138 return true;
2139 }
2140
end_visit(debugger_expr & v)2141 void end_visit(debugger_expr& v)
2142 {
2143 CODEGEN_TRACE_OUT("");
2144
2145 // generate an eval iterator and populate it with the in-scope variables
2146
2147 std::vector<PlanIter_t> argvEvalIter;
2148
2149 csize numVars = v.var_count();
2150 std::vector<store::Item_t> varNames(numVars);
2151 std::vector<xqtref_t> varTypes(numVars);
2152 std::vector<int> isGlobalVar(numVars);
2153
2154 //create the eval iterator children
2155 for (csize i = 0; i < numVars; i++)
2156 {
2157 varNames[i] = v.get_var(i)->get_name();
2158 varTypes[i] = v.get_var(i)->get_type();
2159 isGlobalVar[i] = (v.get_var(i)->get_kind() == var_expr::prolog_var);
2160
2161 argvEvalIter.push_back(pop_itstack());
2162 }
2163
2164 argvEvalIter.push_back(new DebuggerSingletonIterator(sctx,
2165 qloc,
2166 theCCB->theDebuggerCommons));
2167
2168 // now reverse them (first the expression, then the variables)
2169 reverse(argvEvalIter.begin(), argvEvalIter.end());
2170
2171 // get the debugger iterator from the debugger stack
2172 std::auto_ptr<DebugIterator> lDebugIterator(theDebuggerStack.top());
2173 theDebuggerStack.pop();
2174
2175 // set the children of the debugger iterator
2176 // child 0: the iterator of the wrapped expression
2177 // child 1: the eval iterator
2178
2179 // child 0
2180 std::vector<PlanIter_t> argv;
2181 argv.push_back(pop_itstack());
2182
2183 // child 1
2184 store::NsBindings localBindings;
2185 if (v.getNSCtx())
2186 {
2187 v.getNSCtx()->getAllBindings(localBindings);
2188 }
2189
2190 argv.push_back(new EvalIterator(sctx,
2191 qloc,
2192 argvEvalIter,
2193 varNames,
2194 varTypes,
2195 isGlobalVar,
2196 SEQUENTIAL_FUNC_EXPR,
2197 localBindings,
2198 true,
2199 true));
2200
2201 lDebugIterator->setChildren(&argv);
2202 lDebugIterator->setVariables(varNames, varTypes);
2203
2204 // link all debugger iterators in the tree
2205 if (!theDebuggerStack.empty())
2206 {
2207 theDebuggerStack.top()->addChild(lDebugIterator.get());
2208 lDebugIterator->setParent(theDebuggerStack.top());
2209 }
2210
2211 push_itstack(lDebugIterator.release());
2212 }
2213 #endif
2214
2215
begin_visit(if_expr & v)2216 bool begin_visit(if_expr& v)
2217 {
2218 CODEGEN_TRACE_IN("");
2219 return true;
2220 }
2221
2222
end_visit(if_expr & v)2223 void end_visit(if_expr& v)
2224 {
2225 CODEGEN_TRACE_OUT("");
2226 PlanIter_t iterElse = pop_itstack();
2227 PlanIter_t iterThen = pop_itstack();
2228 PlanIter_t iterCond = pop_itstack();
2229
2230 PlanIter_t iterIfThenElse =
2231 new IfThenElseIterator(sctx, qloc, iterCond, iterThen, iterElse);
2232
2233 push_itstack(&*iterIfThenElse);
2234 }
2235
2236
begin_visit(exit_expr & v)2237 bool begin_visit(exit_expr& v)
2238 {
2239 CODEGEN_TRACE_IN("");
2240 return true;
2241 }
2242
end_visit(exit_expr & v)2243 void end_visit(exit_expr& v)
2244 {
2245 CODEGEN_TRACE_OUT("");
2246 push_itstack(new ExitIterator(sctx, qloc, pop_itstack()));
2247 }
2248
2249
begin_visit(exit_catcher_expr & v)2250 bool begin_visit(exit_catcher_expr& v)
2251 {
2252 CODEGEN_TRACE_IN("");
2253 return true;
2254 }
2255
end_visit(exit_catcher_expr & v)2256 void end_visit(exit_catcher_expr& v)
2257 {
2258 CODEGEN_TRACE_OUT("");
2259 push_itstack(new ExitCatcherIterator(sctx, qloc, pop_itstack()));
2260 }
2261
2262
begin_visit(flowctl_expr & v)2263 bool begin_visit(flowctl_expr& v)
2264 {
2265 CODEGEN_TRACE_IN("");
2266 return true;
2267 }
2268
end_visit(flowctl_expr & v)2269 void end_visit(flowctl_expr& v)
2270 {
2271 CODEGEN_TRACE_OUT("");
2272 enum FlowCtlException::action a;
2273 switch (v.get_action())
2274 {
2275 case flowctl_expr::BREAK:
2276 a = FlowCtlException::BREAK;
2277 break;
2278 case flowctl_expr::CONTINUE:
2279 a = FlowCtlException::CONTINUE;
2280 break;
2281 default:
2282 ZORBA_FATAL(false, "");
2283 }
2284
2285 push_itstack(new FlowCtlIterator(sctx, qloc, a));
2286 }
2287
2288
begin_visit(while_expr & v)2289 bool begin_visit(while_expr& v)
2290 {
2291 CODEGEN_TRACE_IN("");
2292 return true;
2293 }
2294
end_visit(while_expr & v)2295 void end_visit(while_expr& v)
2296 {
2297 CODEGEN_TRACE_OUT("");
2298 push_itstack(new LoopIterator (sctx, qloc, pop_itstack()));
2299 }
2300
2301
begin_visit(fo_expr & v)2302 bool begin_visit(fo_expr& v)
2303 {
2304 CODEGEN_TRACE_IN("");
2305
2306 const function* func = v.get_func();
2307 ZORBA_ASSERT(func != NULL);
2308
2309 // If the function is an enclosed expression, push it in the constructors
2310 // stack to "hide" the current constructor context, if any. This way, a new
2311 // constructor context can be started if a node constructor exists inside
2312 // the enclosed expr.
2313 if (is_enclosed_expr(&v))
2314 theConstructorsStack.push(&v);
2315
2316 return true;
2317 }
2318
2319
end_visit(fo_expr & v)2320 void end_visit(fo_expr& v)
2321 {
2322 CODEGEN_TRACE_OUT("");
2323
2324 function* func = v.get_func();
2325
2326 std::vector<PlanIter_t> argv;
2327
2328 argv.resize(v.num_args());
2329 generate(argv.rbegin(), argv.rend(), ztd::stack_to_generator(itstack));
2330
2331 const QueryLoc& loc = qloc;
2332
2333 if (v.is_sequential())
2334 {
2335 ulong numArgs = v.num_args();
2336 for (ulong i = 0; i < numArgs; ++i)
2337 {
2338 if (v.get_arg(i)->is_sequential())
2339 {
2340 argv[i] = new MaterializeIterator(sctx, v.get_arg(i)->get_loc(), argv[i]);
2341 }
2342 }
2343 }
2344
2345 if (func->validate_args(argv))
2346 {
2347 PlanIter_t iter = func->codegen(theCCB, sctx, loc, argv, v);
2348 ZORBA_ASSERT(iter != NULL);
2349 push_itstack(iter);
2350
2351 if (is_enclosed_expr(&v))
2352 {
2353 expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
2354 ZORBA_ASSERT(e == &v);
2355
2356 if (!theEnclosedContextStack.empty())
2357 {
2358 EnclosedExprContext ctx = theEnclosedContextStack.top();
2359
2360 if (ctx == ATTRIBUTE_CONTENT)
2361 dynamic_cast<EnclosedIterator*>(iter.getp())->setAttrContent();
2362 else if (ctx == TEXT_CONTENT)
2363 dynamic_cast<EnclosedIterator*>(iter.getp())->setTextContent();
2364 else if (ctx == UPDATE_CONTEXT)
2365 dynamic_cast<EnclosedIterator*>(iter.getp())->setInUpdateExpr();
2366 }
2367 }
2368 else if (func->isUdf())
2369 {
2370 // need to computeResultCaching here for iterprint to work
2371 user_function* udf = static_cast<user_function*>(func);
2372 udf->computeResultCaching(theCCB->theXQueryDiagnostics);
2373 }
2374 }
2375 else
2376 {
2377 throw XQUERY_EXCEPTION(err::XPST0017,
2378 ERROR_PARAMS(func->getName()->getStringValue(),
2379 ZED(FunctionUndeclared_3),
2380 argv.size()),
2381 ERROR_LOC(loc));
2382 }
2383 }
2384
2385
begin_visit(instanceof_expr & v)2386 bool begin_visit(instanceof_expr& v)
2387 {
2388 CODEGEN_TRACE_IN("");
2389 return true;
2390 }
2391
2392
end_visit(instanceof_expr & v)2393 void end_visit(instanceof_expr& v)
2394 {
2395 CODEGEN_TRACE_OUT("");
2396 PlanIter_t p = pop_itstack ();
2397 push_itstack (new InstanceOfIterator (sctx, qloc, p, v.get_target_type ()));
2398 }
2399
2400
begin_visit(treat_expr & v)2401 bool begin_visit(treat_expr& v)
2402 {
2403 CODEGEN_TRACE_IN("");
2404 return true;
2405 }
2406
2407
end_visit(treat_expr & v)2408 void end_visit(treat_expr& v)
2409 {
2410 CODEGEN_TRACE_OUT("");
2411 PlanIter_t arg;
2412 arg = pop_itstack();
2413 push_itstack(new TreatIterator(sctx, qloc, arg,
2414 v.get_target_type(),
2415 v.get_check_prime(),
2416 v.get_err(),
2417 v.get_qname()));
2418 }
2419
2420
begin_visit(castable_expr & v)2421 bool begin_visit(castable_expr& v)
2422 {
2423 CODEGEN_TRACE_IN("");
2424 return true;
2425 }
2426
2427
end_visit(castable_expr & v)2428 void end_visit(castable_expr& v)
2429 {
2430 CODEGEN_TRACE_OUT("");
2431 PlanIter_t lChild = pop_itstack();
2432 push_itstack(new CastableIterator(sctx, qloc, lChild, v.get_target_type()));
2433 }
2434
2435
begin_visit(cast_expr & v)2436 bool begin_visit(cast_expr& v)
2437 {
2438 CODEGEN_TRACE_IN("");
2439 return true;
2440 }
2441
2442
end_visit(cast_expr & v)2443 void end_visit(cast_expr& v)
2444 {
2445 CODEGEN_TRACE_OUT("");
2446 PlanIter_t lChild = pop_itstack();
2447 push_itstack(new CastIterator(sctx, qloc, lChild, v.get_target_type()));
2448 }
2449
2450
begin_visit(name_cast_expr & v)2451 bool begin_visit(name_cast_expr& v)
2452 {
2453 CODEGEN_TRACE_IN("");
2454
2455 RootTypeManager& rtm = GENV_TYPESYSTEM;
2456 TypeManager* tm = v.get_type_manager();
2457
2458 expr* targetExpr = v.get_input();
2459 xqtref_t targetType = targetExpr->get_return_type();
2460
2461 if (TypeOps::is_subtype(tm, *rtm.UNTYPED_ATOMIC_TYPE_ONE, *targetType, qloc) ||
2462 TypeOps::is_subtype(tm, *targetType, *rtm.UNTYPED_ATOMIC_TYPE_ONE, qloc) ||
2463 TypeOps::is_subtype(tm, *rtm.QNAME_TYPE_ONE, *targetType, qloc) ||
2464 TypeOps::is_subtype(tm, *targetType, *rtm.QNAME_TYPE_ONE, qloc) ||
2465 TypeOps::is_subtype(tm, *rtm.NCNAME_TYPE_ONE, *targetType, qloc) ||
2466 TypeOps::is_subtype(tm, *targetType, *rtm.NCNAME_TYPE_ONE, qloc) ||
2467 TypeOps::is_subtype(tm, *rtm.STRING_TYPE_ONE, *targetType, qloc) ||
2468 TypeOps::is_subtype(tm, *targetType, *rtm.STRING_TYPE_ONE, qloc))
2469 return true;
2470
2471 throw XQUERY_EXCEPTION(
2472 err::XPTY0004,
2473 ERROR_PARAMS( ZED( BadType_23o ), *targetType ),
2474 ERROR_LOC( qloc )
2475 );
2476 }
2477
end_visit(name_cast_expr & v)2478 void end_visit(name_cast_expr& v)
2479 {
2480 CODEGEN_TRACE_OUT("");
2481 PlanIter_t child = pop_itstack();
2482 push_itstack(new NameCastIterator(sctx,
2483 qloc,
2484 child,
2485 v.getNSCtx(),
2486 v.is_attr_name()));
2487 }
2488
2489
begin_visit(validate_expr & v)2490 bool begin_visit(validate_expr& v)
2491 {
2492 CODEGEN_TRACE_IN("");
2493 return true;
2494 }
2495
end_visit(validate_expr & v)2496 void end_visit(validate_expr& v)
2497 {
2498 CODEGEN_TRACE_OUT("");
2499
2500 #ifndef ZORBA_NO_XMLSCHEMA
2501 PlanIter_t lChild = pop_itstack();
2502 //store::Item_t typeName = v.get_type_name();
2503 //std::cout << "validate end-visit: type: " << typeName->getLocalName()->c_str() << " @ " << typeName->getNamespace()->c_str() << "\n"; cout.flush();
2504 push_itstack (new ValidateIterator(sctx,
2505 qloc,
2506 lChild,
2507 v.get_valmode(),
2508 v.get_typemgr(),
2509 const_cast<store::Item*>(v.get_type_name())));
2510 #else
2511 //no schema support
2512 throw XQUERY_EXCEPTION(err::XQST0009, ERROR_LOC(qloc));
2513 #endif
2514 }
2515
2516
begin_visit(extension_expr & v)2517 bool begin_visit(extension_expr& v) {
2518 CODEGEN_TRACE_IN("");
2519 return true;
2520 }
2521
end_visit(extension_expr & v)2522 void end_visit(extension_expr& v)
2523 {
2524 CODEGEN_TRACE_OUT("");
2525 }
2526
2527
2528 #ifdef PATH_ITERATOR
2529
2530 /*******************************************************************************
2531
2532 ********************************************************************************/
begin_visit(relpath_expr & v)2533 bool begin_visit(relpath_expr& v)
2534 {
2535 CODEGEN_TRACE_IN("");
2536
2537 //PlanIter_t input = pop_itstack();
2538 //ZORBA_ASSERT(input != NULL);
2539 //PlanIter_t pathIte(new PathIterator(qloc, input));
2540 //push_itstack(pathIte);
2541
2542 return true;
2543 }
2544
2545
end_visit(relpath_expr & v)2546 void end_visit(relpath_expr& v)
2547 {
2548 CODEGEN_TRACE_OUT("");
2549 }
2550
2551
2552 /*******************************************************************************
2553
2554 ********************************************************************************/
begin_visit(axis_step_expr & v)2555 bool begin_visit(axis_step_expr& v)
2556 {
2557 CODEGEN_TRACE_IN("");
2558
2559 store::ItemFactory& factory = *(GENV.getStore().getItemFactory());
2560 store::Item_t qname;
2561
2562 PlanIter_t& ite = plan_visitor_ns::peek_stack(itstack);
2563 PathIterator* pathIte = dynamic_cast<PathIterator*>(ite.getp());
2564
2565 if (pathIte == NULL)
2566 {
2567 PlanIter_t inputStep = pop_itstack();
2568 pathIte = new PathIterator(sctx, qloc, inputStep);
2569 push_itstack(pathIte);
2570 }
2571 //ZORBA_ASSERT(pathIte != NULL);
2572
2573 match_expr* testExpr = v.getTest();
2574
2575 NodePredicate* prd = new NodePredicate();
2576
2577 prd->setTestKind(testExpr->getTestKind());
2578
2579 if (testExpr->getTestKind() == match_name_test)
2580 {
2581 if (v.getAxis() == axis_kind_attribute)
2582 prd->setNodeKind(store::StoreConsts::attributeNode);
2583 else
2584 prd->setNodeKind(store::StoreConsts::elementNode);
2585
2586 match_wild_t wildKind = testExpr->getWildKind();
2587 prd->setWildKind(wildKind);
2588
2589 if (wildKind == match_no_wild)
2590 {
2591 prd->setQName(testExpr->getQName());
2592 }
2593 else if (wildKind == match_prefix_wild)
2594 {
2595 factory.createQName(qname, "", "*", testExpr->getWildName().c_str());
2596
2597 prd->setQName(qname);
2598 }
2599 else if (wildKind == match_name_wild)
2600 {
2601 prd->setQName(testExpr->getQName());
2602 }
2603 }
2604 else
2605 {
2606 prd->setDocTestKind(testExpr->getDocTestKind());
2607 prd->setNodeKind(testExpr->getNodeKind());
2608 prd->setQName(testExpr->getQName());
2609 store::Item* typeName = testExpr->getTypeName();
2610 if (typeName != NULL)
2611 {
2612 prd->setType(sctx->get_typemanager()->create_named_type(typeName,
2613 TypeConstants::QUANT_ONE,
2614 loc,
2615 XPTY0004));
2616 }
2617 prd->setNilledAllowed(testExpr->getNilledAllowed());
2618 }
2619
2620 pathIte->addStep(v.getAxis(), prd);
2621
2622 return true;
2623 }
2624
2625
end_visit(axis_step_expr & v)2626 void end_visit(axis_step_expr& v)
2627 {
2628 CODEGEN_TRACE_OUT("");
2629 }
2630
2631
begin_visit(match_expr & v)2632 bool begin_visit(match_expr& v)
2633 {
2634 CODEGEN_TRACE_IN("");
2635
2636 return true;
2637 }
2638
2639
end_visit(match_expr & v)2640 void end_visit(match_expr& v)
2641 {
2642 CODEGEN_TRACE_OUT("");
2643 }
2644
2645
2646 #else
2647
2648 /*******************************************************************************
2649
2650 ********************************************************************************/
begin_visit(relpath_expr & v)2651 bool begin_visit(relpath_expr& v)
2652 {
2653 CODEGEN_TRACE_IN("");
2654 // Done in axis itself
2655 return true;
2656 }
2657
2658
end_visit(relpath_expr & v)2659 void end_visit(relpath_expr& v)
2660 {
2661 CODEGEN_TRACE_OUT("");
2662 }
2663
2664
2665 /*******************************************************************************
2666
2667 ********************************************************************************/
begin_visit(axis_step_expr & v)2668 bool begin_visit(axis_step_expr& v)
2669 {
2670 CODEGEN_TRACE_IN("");
2671
2672 bool result = true;
2673
2674 PlanIter_t input = pop_itstack();
2675
2676 ZORBA_ASSERT(input != NULL);
2677
2678 PlanIter_t axisIte;
2679
2680 switch (v.getAxis())
2681 {
2682 case axis_kind_self:
2683 {
2684 axisIte = new SelfAxisIterator(sctx, qloc, input);
2685 break;
2686 }
2687 case axis_kind_child:
2688 {
2689 axisIte = new ChildAxisIterator(sctx, qloc, input);
2690 break;
2691 }
2692 case axis_kind_parent:
2693 {
2694 axisIte = new ParentAxisIterator(sctx, qloc, input);
2695 break;
2696 }
2697 case axis_kind_descendant:
2698 {
2699 axisIte = new DescendantAxisIterator(sctx, qloc, input);
2700 break;
2701 }
2702 case axis_kind_descendant_or_self:
2703 {
2704 axisIte = new DescendantSelfAxisIterator(sctx, qloc, input);
2705 break;
2706 }
2707 case axis_kind_ancestor:
2708 {
2709 if (v.use_reverse_order())
2710 axisIte = new AncestorReverseAxisIterator(sctx, qloc, input);
2711 else
2712 axisIte = new AncestorAxisIterator(sctx, qloc, input);
2713 break;
2714 }
2715 case axis_kind_ancestor_or_self:
2716 {
2717 if (v.use_reverse_order())
2718 axisIte = new AncestorSelfReverseAxisIterator(sctx, qloc, input);
2719 else
2720 axisIte = new AncestorSelfAxisIterator(sctx, qloc, input);
2721 break;
2722 }
2723 case axis_kind_following_sibling:
2724 {
2725 axisIte = new RSiblingAxisIterator(sctx, qloc, input);
2726 break;
2727 }
2728 case axis_kind_following:
2729 {
2730 axisIte = new FollowingAxisIterator(sctx, qloc, input);
2731 break;
2732 }
2733 case axis_kind_preceding_sibling:
2734 {
2735 if (v.use_reverse_order())
2736 axisIte = new LSiblingReverseAxisIterator(sctx, qloc, input);
2737 else
2738 axisIte = new LSiblingAxisIterator(sctx, qloc, input);
2739 break;
2740 }
2741 case axis_kind_preceding:
2742 {
2743 if (v.use_reverse_order())
2744 axisIte = new PrecedingReverseAxisIterator(sctx, qloc, input);
2745 else
2746 axisIte = new PrecedingAxisIterator(sctx, qloc, input);
2747 break;
2748 }
2749 case axis_kind_attribute:
2750 {
2751 if (v.getTest()->getTestKind() == match_name_test ||
2752 v.getTest()->getTestKind() == match_attr_test ||
2753 v.getTest()->getTestKind() == match_xs_attr_test ||
2754 v.getTest()->getTestKind() == match_anykind_test)
2755 {
2756 axisIte = new AttributeAxisIterator(sctx, qloc, input);
2757 }
2758 else
2759 {
2760 axisIte = new EmptyIterator(sctx, qloc);
2761 result = false;
2762 }
2763
2764 break;
2765 }
2766 default:
2767 ZORBA_ASSERT (false && "Unknown axis kind");
2768 }
2769
2770 push_itstack(axisIte);
2771
2772 return result;
2773 }
2774
2775
end_visit(axis_step_expr & v)2776 void end_visit(axis_step_expr& v)
2777 {
2778 CODEGEN_TRACE_OUT("");
2779 }
2780
2781
2782 /*******************************************************************************
2783
2784 ********************************************************************************/
begin_visit(match_expr & v)2785 bool begin_visit(match_expr& v)
2786 {
2787 CODEGEN_TRACE_IN ("");
2788
2789 PlanIter_t axisIte = pop_itstack();
2790 AxisIteratorHelper* axisItep = dynamic_cast<AxisIteratorHelper*>(axisIte.getp());
2791 ZORBA_ASSERT(axisItep != NULL);
2792
2793 store::Item_t qname;
2794
2795 store::ItemFactory& iFactory = *(GENV.getStore().getItemFactory());
2796
2797 if (v.getTestKind() == match_name_test)
2798 {
2799 match_wild_t wildKind = v.getWildKind();
2800
2801 axisItep->setTestKind(match_name_test);
2802
2803 if (dynamic_cast<AttributeAxisIterator*>(axisIte.getp()) != NULL)
2804 axisItep->setNodeKind(store::StoreConsts::attributeNode);
2805 else
2806 axisItep->setNodeKind(store::StoreConsts::elementNode);
2807
2808 axisItep->setWildKind(wildKind);
2809
2810 if (wildKind == match_no_wild)
2811 {
2812 axisItep->setQName(v.getQName());
2813 }
2814 else if (wildKind == match_prefix_wild)
2815 {
2816 iFactory.createQName(qname, "", "wildcard", v.getWildName().c_str());
2817
2818 axisItep->setQName(qname);
2819 }
2820 else if (wildKind == match_name_wild)
2821 {
2822 axisItep->setQName(v.getQName());
2823 }
2824 }
2825 else
2826 {
2827 axisItep->setTestKind(v.getTestKind());
2828 axisItep->setDocTestKind(v.getDocTestKind());
2829 axisItep->setNodeKind(v.getNodeKind());
2830 axisItep->setQName(v.getQName());
2831 store::Item* typeName = v.getTypeName();
2832 if (typeName != NULL)
2833 {
2834 axisItep->setType(sctx->get_typemanager()->
2835 create_named_type(typeName,
2836 TypeConstants::QUANT_ONE,
2837 qloc));
2838 }
2839 axisItep->setNilledAllowed(v.getNilledAllowed());
2840 }
2841
2842 push_itstack(axisIte);
2843 return true;
2844 }
2845
2846
end_visit(match_expr & v)2847 void end_visit(match_expr& v)
2848 {
2849 CODEGEN_TRACE_OUT("");
2850 }
2851
2852 #endif // PATH_ITER
2853
2854
2855 /*******************************************************************************
2856
2857 Node Constructors
2858
2859 ********************************************************************************/
2860
begin_visit(doc_expr & v)2861 bool begin_visit(doc_expr& v)
2862 {
2863 CODEGEN_TRACE_IN("");
2864
2865 theConstructorsStack.push(&v);
2866 theEnclosedContextStack.push(ELEMENT_CONTENT);
2867
2868 if (v.copyInputNodes())
2869 theCopyNodesStack.push(true);
2870
2871 return true;
2872 }
2873
2874
end_visit(doc_expr & v)2875 void end_visit(doc_expr& v)
2876 {
2877 CODEGEN_TRACE_OUT("");
2878
2879 PlanIter_t lContent = pop_itstack();
2880 PlanIter_t lDocIter = new DocumentIterator(sctx,
2881 qloc,
2882 lContent,
2883 !theCopyNodesStack.empty());
2884 push_itstack(lDocIter);
2885
2886 theEnclosedContextStack.pop();
2887 expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
2888 ZORBA_ASSERT(e == &v);
2889
2890 if (v.copyInputNodes())
2891 theCopyNodesStack.pop();
2892 }
2893
2894
begin_visit(elem_expr & v)2895 bool begin_visit(elem_expr& v)
2896 {
2897 CODEGEN_TRACE_IN("");
2898
2899 theConstructorsStack.push(&v);
2900 theEnclosedContextStack.push(ELEMENT_CONTENT);
2901
2902 if (v.copyInputNodes())
2903 theCopyNodesStack.push(true);
2904
2905 return true;
2906 }
2907
2908
end_visit(elem_expr & v)2909 void end_visit(elem_expr& v)
2910 {
2911 CODEGEN_TRACE_OUT("");
2912
2913 PlanIter_t lQNameIter = 0;
2914 PlanIter_t lContentIter = 0;
2915 PlanIter_t lAttrsIter = 0;
2916
2917 if ( v.getContent() != 0 )
2918 lContentIter = pop_itstack();
2919
2920 if ( v.getAttrs() != 0 )
2921 lAttrsIter = pop_itstack();
2922
2923 lQNameIter = pop_itstack();
2924
2925 bool isRoot = false;
2926 theEnclosedContextStack.pop();
2927 expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
2928 ZORBA_ASSERT(e == &v);
2929
2930 // Handling of the special case where the QName expression of a direct element
2931 // constructor has in itself a direct constructor. In that case the QName
2932 // expression should have isRoot set to true.
2933 elem_expr* top_elem_expr = NULL;
2934 if (!theConstructorsStack.empty())
2935 top_elem_expr = dynamic_cast<elem_expr*>(theConstructorsStack.top());
2936
2937 if (theConstructorsStack.empty() ||
2938 is_enclosed_expr(theConstructorsStack.top()) ||
2939 (top_elem_expr != NULL && top_elem_expr->getQNameExpr()->contains_expr(e)))
2940 {
2941 isRoot = true;
2942 }
2943
2944 PlanIter_t iter = new ElementIterator(sctx,
2945 qloc,
2946 lQNameIter,
2947 lAttrsIter,
2948 lContentIter,
2949 v.getNSCtx(),
2950 isRoot,
2951 !theCopyNodesStack.empty());
2952 push_itstack(iter);
2953
2954 if (v.copyInputNodes())
2955 theCopyNodesStack.pop();
2956 }
2957
2958
begin_visit(attr_expr & v)2959 bool begin_visit(attr_expr& v)
2960 {
2961 CODEGEN_TRACE_IN("");
2962
2963 theConstructorsStack.push(&v);
2964 theEnclosedContextStack.push(ATTRIBUTE_CONTENT);
2965
2966 return true;
2967 }
2968
2969
end_visit(attr_expr & v)2970 void end_visit(attr_expr& v)
2971 {
2972 CODEGEN_TRACE_OUT("");
2973
2974 PlanIter_t valueIter = 0;
2975
2976 if (v.getValueExpr() != 0)
2977 {
2978 valueIter = pop_itstack();
2979 }
2980 else
2981 {
2982 valueIter = new EmptyIterator(sctx, qloc);
2983 }
2984
2985 PlanIter_t qnameIter;
2986 store::Item_t qname;
2987 const const_expr* qnameExpr = dynamic_cast<const const_expr*>(v.getQNameExpr());
2988 if (qnameExpr != NULL)
2989 {
2990 qname = qnameExpr->get_val();
2991 (void)pop_itstack();
2992 }
2993 else
2994 {
2995 qnameIter = pop_itstack();
2996 }
2997
2998 bool isRoot = false;
2999 theEnclosedContextStack.pop();
3000 expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
3001 ZORBA_ASSERT(e = &v);
3002
3003 if (theConstructorsStack.empty() || is_enclosed_expr(theConstructorsStack.top()))
3004 {
3005 isRoot = true;
3006 }
3007
3008 PlanIter_t attrIter = new AttributeIterator(sctx,
3009 qloc,
3010 qname,
3011 qnameIter,
3012 valueIter,
3013 isRoot);
3014
3015 push_itstack(attrIter);
3016 }
3017
3018
begin_visit(text_expr & v)3019 bool begin_visit(text_expr& v)
3020 {
3021 CODEGEN_TRACE_IN ("");
3022
3023 theConstructorsStack.push(&v);
3024
3025 if (v.get_type() == text_expr::text_constructor)
3026 theEnclosedContextStack.push(TEXT_CONTENT);
3027 else
3028 theEnclosedContextStack.push(ATTRIBUTE_CONTENT);
3029
3030 return true;
3031 }
3032
3033
end_visit(text_expr & v)3034 void end_visit(text_expr& v)
3035 {
3036 CODEGEN_TRACE_OUT("");
3037
3038 PlanIter_t content = pop_itstack();
3039
3040 bool isRoot = false;
3041 theEnclosedContextStack.pop();
3042 expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
3043 ZORBA_ASSERT(e = &v);
3044
3045 if (theConstructorsStack.empty() || is_enclosed_expr(theConstructorsStack.top()))
3046 {
3047 isRoot = true;
3048 }
3049
3050 switch (v.get_type())
3051 {
3052 case text_expr::text_constructor:
3053 push_itstack(new TextIterator(sctx, qloc, content, isRoot));
3054 break;
3055
3056 case text_expr::comment_constructor:
3057 push_itstack(new CommentIterator(sctx, qloc, content, isRoot));
3058 break;
3059
3060 default:
3061 break;
3062 }
3063 }
3064
3065
begin_visit(pi_expr & v)3066 bool begin_visit(pi_expr& v)
3067 {
3068 CODEGEN_TRACE_IN("");
3069
3070 theConstructorsStack.push(&v);
3071 theEnclosedContextStack.push(ATTRIBUTE_CONTENT);
3072
3073 return true;
3074 }
3075
3076
end_visit(pi_expr & v)3077 void end_visit(pi_expr& v)
3078 {
3079 CODEGEN_TRACE_OUT("");
3080
3081 bool isRoot = false;
3082 theEnclosedContextStack.pop();
3083 expr* e = plan_visitor_ns::pop_stack(theConstructorsStack);
3084 ZORBA_ASSERT(e = &v);
3085 if (theConstructorsStack.empty() || is_enclosed_expr(theConstructorsStack.top()))
3086 {
3087 isRoot = true;
3088 }
3089
3090 PlanIter_t content = pop_itstack ();
3091 PlanIter_t target = pop_itstack ();
3092 push_itstack(new PiIterator(sctx, qloc, target, content, isRoot));
3093 }
3094
3095
3096 #ifdef ZORBA_WITH_JSON
3097
3098 /*******************************************************************************
3099
3100 JSON Constructors
3101
3102 ********************************************************************************/
begin_visit(json_array_expr & v)3103 bool begin_visit(json_array_expr& v)
3104 {
3105 CODEGEN_TRACE_IN("");
3106 return true;
3107 }
3108
3109
end_visit(json_array_expr & v)3110 void end_visit(json_array_expr& v)
3111 {
3112 CODEGEN_TRACE_OUT("");
3113
3114 std::vector<PlanIter_t> inputs;
3115
3116 expr* inputExpr = v.get_expr();
3117
3118 if (inputExpr != NULL)
3119 {
3120 PlanIter_t inputIter = pop_itstack();
3121
3122 if (dynamic_cast<FnConcatIterator*>(inputIter.getp()) != NULL)
3123 {
3124 inputs = static_cast<FnConcatIterator*>(inputIter.getp())->getChildren();
3125 }
3126 else
3127 {
3128 inputs.push_back(inputIter);
3129 }
3130 }
3131
3132 bool copyInput = true;
3133
3134 push_itstack(new JSONArrayIterator(sctx, qloc, inputs, copyInput));
3135 }
3136
3137
begin_visit(json_object_expr & v)3138 bool begin_visit(json_object_expr& v)
3139 {
3140 CODEGEN_TRACE_IN("");
3141 return true;
3142 }
3143
3144
end_visit(json_object_expr & v)3145 void end_visit(json_object_expr& v)
3146 {
3147 CODEGEN_TRACE_OUT("");
3148
3149 std::vector<PlanIter_t> inputs;
3150
3151 expr* inputExpr = v.get_expr();
3152
3153 if (inputExpr != NULL)
3154 {
3155 PlanIter_t inputIter = pop_itstack();
3156
3157 if (dynamic_cast<FnConcatIterator*>(inputIter.getp()) != NULL)
3158 {
3159 inputs = static_cast<FnConcatIterator*>(inputIter.getp())->getChildren();
3160 }
3161 else
3162 {
3163 inputs.push_back(inputIter);
3164 }
3165 }
3166
3167 bool copyInput = true;
3168
3169 push_itstack(new JSONObjectIterator(sctx,
3170 qloc,
3171 inputs,
3172 copyInput,
3173 v.is_accumulating()));
3174 }
3175
3176
3177
begin_visit(json_direct_object_expr & v)3178 bool begin_visit(json_direct_object_expr& v)
3179 {
3180 CODEGEN_TRACE_IN("");
3181 return true;
3182 }
3183
3184
end_visit(json_direct_object_expr & v)3185 void end_visit(json_direct_object_expr& v)
3186 {
3187 CODEGEN_TRACE_OUT("");
3188
3189 csize numPairs = v.num_pairs();
3190
3191 std::vector<PlanIter_t> names(numPairs);
3192 std::vector<PlanIter_t> values(numPairs);
3193
3194 for (csize i = numPairs; i > 0; --i)
3195 {
3196 values[i-1] = pop_itstack();
3197 }
3198
3199 for (csize i = numPairs; i > 0; --i)
3200 {
3201 names[i-1] = pop_itstack();
3202 }
3203
3204 bool copyInput = true;
3205
3206 push_itstack(new JSONDirectObjectIterator(sctx, qloc, names, values, copyInput));
3207 }
3208
3209
3210
3211 #endif // ZORBA_WITH_JSON
3212
3213
begin_visit(const_expr & v)3214 bool begin_visit(const_expr& v)
3215 {
3216 CODEGEN_TRACE_IN("");
3217 return true;
3218 }
3219
end_visit(const_expr & v)3220 void end_visit(const_expr& v)
3221 {
3222 CODEGEN_TRACE_OUT("");
3223 PlanIter_t it = new SingletonIterator(sctx, qloc, v.get_val());
3224 push_itstack (it);
3225 }
3226
3227
begin_visit(order_expr & v)3228 bool begin_visit(order_expr& v)
3229 {
3230 CODEGEN_TRACE_IN("");
3231 return true;
3232 }
3233
end_visit(order_expr & v)3234 void end_visit(order_expr& v)
3235 {
3236 CODEGEN_TRACE_OUT("");
3237 }
3238
3239
3240 ////////////////////////////////////////////////////////////////////////////////
3241 // //
3242 // Updates (XQUF) //
3243 // //
3244 ////////////////////////////////////////////////////////////////////////////////
3245
3246
begin_visit(insert_expr & v)3247 bool begin_visit(insert_expr& v)
3248 {
3249 CODEGEN_TRACE_IN("");
3250
3251 RootTypeManager& rtm = GENV_TYPESYSTEM;
3252 TypeManager* tm = v.get_type_manager();
3253
3254 store::UpdateConsts::InsertType kind = v.getType();
3255
3256 expr* targetExpr = v.getTargetExpr();
3257 expr* sourceExpr = v.getSourceExpr();
3258 xqtref_t targetType = targetExpr->get_return_type();
3259 xqtref_t sourceType = sourceExpr->get_return_type();
3260
3261 if (TypeOps::is_equal(tm, *targetType, *rtm.EMPTY_TYPE, qloc))
3262 throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( qloc ) );
3263
3264 if (kind == store::UpdateConsts::INTO ||
3265 kind == store::UpdateConsts::AS_FIRST_INTO ||
3266 kind == store::UpdateConsts::AS_LAST_INTO)
3267 {
3268 if (TypeOps::is_subtype(tm, *targetType, *rtm.DOCUMENT_TYPE_STAR, qloc) &&
3269 TypeOps::is_subtype(tm, *sourceType, *rtm.ATTRIBUTE_TYPE_STAR, qloc))
3270 {
3271 throw XQUERY_EXCEPTION(err::XUTY0022, ERROR_LOC(qloc));
3272 }
3273
3274 if (TypeOps::is_subtype(tm, *targetType, *rtm.ANY_SIMPLE_TYPE, qloc))
3275 {
3276 throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( qloc ) );
3277 }
3278
3279 if (TypeOps::is_subtype(tm, *targetType, *rtm.ATTRIBUTE_TYPE_STAR, qloc) ||
3280 TypeOps::is_subtype(tm, *targetType, *rtm.TEXT_TYPE_STAR, qloc) ||
3281 TypeOps::is_subtype(tm, *targetType, *rtm.COMMENT_TYPE_STAR, qloc) ||
3282 TypeOps::is_subtype(tm, *targetType, *rtm.PI_TYPE_STAR, qloc))
3283 {
3284 throw XQUERY_EXCEPTION( err::XUTY0005, ERROR_LOC( qloc ) );
3285 }
3286 }
3287 else
3288 {
3289 }
3290
3291 theEnclosedContextStack.push(UPDATE_CONTEXT);
3292
3293 return true;
3294 }
3295
3296
end_visit(insert_expr & v)3297 void end_visit(insert_expr& v)
3298 {
3299 CODEGEN_TRACE_OUT("");
3300
3301 theEnclosedContextStack.pop();
3302
3303 PlanIter_t lTarget = pop_itstack();
3304 PlanIter_t lSource = pop_itstack();
3305 PlanIter_t lInsert = new InsertIterator(sctx, qloc, v.getType(), lSource, lTarget);
3306 push_itstack(&*lInsert);
3307 }
3308
3309
begin_visit(delete_expr & v)3310 bool begin_visit(delete_expr& v)
3311 {
3312 CODEGEN_TRACE_IN("");
3313
3314 theEnclosedContextStack.push(UPDATE_CONTEXT);
3315
3316 return true;
3317 }
3318
3319
end_visit(delete_expr & v)3320 void end_visit(delete_expr& v)
3321 {
3322 CODEGEN_TRACE_OUT("");
3323
3324 theEnclosedContextStack.pop();
3325
3326 PlanIter_t lTarget = pop_itstack();
3327 PlanIter_t lDelete = new DeleteIterator(sctx, qloc, lTarget);
3328 push_itstack(&*lDelete);
3329 }
3330
3331
begin_visit(replace_expr & v)3332 bool begin_visit(replace_expr& v)
3333 {
3334 CODEGEN_TRACE_IN("");
3335
3336 TypeManager* tm = v.get_type_manager();
3337
3338 expr* targetExpr = v.getTargetExpr();
3339 xqtref_t targetType = targetExpr->get_return_type();
3340
3341 if (TypeOps::is_equal(tm, *targetType, *GENV_TYPESYSTEM.EMPTY_TYPE, qloc))
3342 throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( qloc ) );
3343
3344 theEnclosedContextStack.push(UPDATE_CONTEXT);
3345
3346 return true;
3347 }
3348
3349
end_visit(replace_expr & v)3350 void end_visit(replace_expr& v)
3351 {
3352 CODEGEN_TRACE_OUT("");
3353
3354 theEnclosedContextStack.pop();
3355
3356 PlanIter_t lReplacement = pop_itstack();
3357 PlanIter_t lTarget = pop_itstack();
3358 PlanIter_t lReplace = new ReplaceIterator(sctx,
3359 qloc,
3360 v.getType(),
3361 lTarget,
3362 lReplacement);
3363 push_itstack(&*lReplace);
3364 }
3365
3366
begin_visit(rename_expr & v)3367 bool begin_visit(rename_expr& v)
3368 {
3369 CODEGEN_TRACE_IN("");
3370
3371 TypeManager* tm = v.get_type_manager();
3372
3373 expr* targetExpr = v.getTargetExpr();
3374 xqtref_t targetType = targetExpr->get_return_type();
3375
3376 if (TypeOps::is_equal(tm, *targetType, *GENV_TYPESYSTEM.EMPTY_TYPE, qloc))
3377 throw XQUERY_EXCEPTION( err::XUDY0027, ERROR_LOC( qloc ) );
3378
3379 theEnclosedContextStack.push(UPDATE_CONTEXT);
3380
3381 return true;
3382 }
3383
3384
end_visit(rename_expr & v)3385 void end_visit(rename_expr& v)
3386 {
3387 CODEGEN_TRACE_OUT("");
3388
3389 theEnclosedContextStack.pop();
3390
3391 PlanIter_t lName = pop_itstack();
3392 PlanIter_t lTarget = pop_itstack();
3393 PlanIter_t lRename;
3394
3395 expr* nameExpr = v.getNameExpr();
3396
3397 if (nameExpr->get_expr_kind() == name_cast_expr_kind)
3398 {
3399 name_cast_expr* nameCastExpr = static_cast<name_cast_expr*>(nameExpr);
3400
3401 lRename = new RenameIterator(sctx,
3402 qloc,
3403 lTarget,
3404 lName,
3405 nameCastExpr->getNSCtx());
3406 }
3407 else
3408 {
3409 lRename = new RenameIterator(sctx, qloc, lTarget, lName, NULL);
3410 }
3411
3412 push_itstack(&*lRename);
3413 }
3414
3415
begin_visit(transform_expr & v)3416 bool begin_visit(transform_expr& v)
3417 {
3418 CODEGEN_TRACE_IN("");
3419
3420 TypeManager* tm = v.get_type_manager();
3421
3422 std::vector<copy_clause*>::const_iterator lIter = v.begin();
3423 std::vector<copy_clause*>::const_iterator lEnd = v.end();
3424 for (; lIter != lEnd; ++lIter)
3425 {
3426 var_expr* var = (*lIter)->getVar();
3427 expr* sourceExpr = (*lIter)->getExpr();
3428 xqtref_t sourceType = sourceExpr->get_return_type();
3429
3430 if (TypeOps::is_subtype(tm, *sourceType, *GENV_TYPESYSTEM.ANY_SIMPLE_TYPE, qloc))
3431 throw XQUERY_EXCEPTION(err::XUTY0013, ERROR_LOC(qloc));
3432
3433 uint64_t k = (uint64_t) &*var;
3434 copy_var_iter_map.put(k, new std::vector<ForVarIter_t>());
3435 }
3436 return true;
3437 }
3438
end_visit(transform_expr & v)3439 void end_visit(transform_expr& v)
3440 {
3441 CODEGEN_TRACE_OUT("");
3442
3443 PlanIter_t returnIter = pop_itstack();
3444 PlanIter_t modifyIter = pop_itstack();
3445
3446 std::vector<CopyClause> lClauses;
3447 std::stack<PlanIter_t> lInputs;
3448 size_t lSize = v.size();
3449 for (size_t i = 0; i < lSize; ++i)
3450 {
3451 lInputs.push(pop_itstack());
3452 }
3453
3454 // Create a FOR var iterator into which the PUL produced by the modify
3455 // iterator will be bound.
3456 store::Item_t pulVarName;
3457 GENV_ITEMFACTORY->createQName(pulVarName, "", "", "pulHolder");
3458 PlanIter_t pulHolderIter = new ForVarIterator(sctx, modifyIter->loc, pulVarName);
3459
3460 // Create an ApplyIterator to apply the above PUL
3461 PlanIter_t applyIter = new ApplyIterator(sctx, modifyIter->loc, true, pulHolderIter);
3462
3463 std::vector<copy_clause*>::const_iterator lIter = v.begin();
3464 std::vector<copy_clause*>::const_iterator lEnd = v.end();
3465 for(; lIter != lEnd; ++lIter)
3466 {
3467 PlanIter_t lInput = plan_visitor_ns::pop_stack(lInputs);
3468 std::vector<ForVarIter_t>* lVarIters = 0;
3469 var_expr* lVar = (*lIter)->getVar();
3470 ZORBA_ASSERT(copy_var_iter_map.get((uint64_t)lVar, lVarIters));
3471 lClauses.push_back(CopyClause(*lVarIters, lInput));
3472 }
3473
3474 TransformIterator* transformIter = new TransformIterator(sctx,
3475 qloc,
3476 lClauses,
3477 modifyIter,
3478 pulHolderIter,
3479 applyIter,
3480 returnIter);
3481 push_itstack(transformIter);
3482 }
3483
3484
3485 ////////////////////////////////////////////////////////////////////////////////
3486 // //
3487 // Full Text //
3488 // //
3489 ////////////////////////////////////////////////////////////////////////////////
3490
3491 #ifndef ZORBA_NO_FULL_TEXT
begin_visit(ftcontains_expr & v)3492 bool begin_visit(ftcontains_expr& v)
3493 {
3494 CODEGEN_TRACE_IN("");
3495 return true;
3496 }
3497
end_visit(ftcontains_expr & v)3498 void end_visit(ftcontains_expr& v)
3499 {
3500 CODEGEN_TRACE_OUT("");
3501 PlanIter_t ftignore_it = v.get_ignore() ? pop_itstack() : NULL;
3502 PlanIter_t ftrange_it = pop_itstack();
3503
3504 PlanIter_t ftcontains_it = new FTContainsIterator(
3505 sctx, qloc, ftrange_it, ftignore_it, v.get_ftselection(),
3506 plan_ftnode_visitor_->get_sub_iters()
3507 );
3508
3509 push_itstack( ftcontains_it );
3510 }
3511 #endif /* ZORBA_NO_FULL_TEXT */
3512
3513
result()3514 PlanIter_t result()
3515 {
3516 PlanIter_t res = pop_itstack();
3517
3518 #ifndef NDEBUG
3519 if (!itstack.empty())
3520 {
3521 std::cout << "\nPlan_visitor stack still contains "
3522 << itstack.size() << " entries: " << std::endl;
3523 while (!itstack.empty())
3524 {
3525 PlanIter_t top = pop_itstack();
3526 XMLIterPrinter vp(std::cout);
3527 print_iter_plan(vp, top);
3528 std::cout << "=============================" << std::endl;
3529 }
3530 ZORBA_ASSERT(0);
3531 }
3532 #endif
3533
3534 return res;
3535 }
3536
3537 };
3538
3539 ///////////////////////////////////////////////////////////////////////////////
3540
3541 #ifndef ZORBA_NO_FULL_TEXT
3542
3543 #define V plan_ftnode_visitor
3544
3545 //
3546 // This member function is defined here to avoid an improper cast.
3547 //
get_expr_visitor()3548 expr_visitor* V::get_expr_visitor()
3549 {
3550 return plan_visitor_;
3551 }
3552
3553 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftand )
3554 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftextension_selection )
3555 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftmild_not )
3556 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftor )
3557 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftprimary_with_options )
3558
3559 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftrange );
end_visit(ftrange & r)3560 void V::end_visit( ftrange &r ) {
3561 PlanIter_t it2 = plan_visitor_->pop_itstack();
3562 PlanIter_t it1;
3563 if ( *(r.get_expr2()) ) {
3564 it1 = plan_visitor_->pop_itstack();
3565 } else {
3566 it1 = it2;
3567 it2 = NULL;
3568 }
3569 sub_iters_.push_back( it1 );
3570 if ( it2 )
3571 sub_iters_.push_back( it2 );
3572 r.set_plan_iters( it1, it2 );
3573 }
3574
3575 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftselection )
3576 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftunary_not )
3577
3578 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftweight );
end_visit(ftweight & w)3579 void V::end_visit( ftweight &w ) {
3580 PlanIter_t it = plan_visitor_->pop_itstack();
3581 w.set_weight_iter( it );
3582 sub_iters_.push_back( it );
3583 }
3584
3585 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftwords );
end_visit(ftwords & w)3586 void V::end_visit( ftwords &w ) {
3587 PlanIter_t it = plan_visitor_->pop_itstack();
3588 w.set_plan_iter( it );
3589 sub_iters_.push_back( it );
3590 }
3591
3592 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftwords_times )
3593 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftcontent_filter )
3594 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftdistance_filter )
3595 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftorder_filter )
3596 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftscope_filter )
3597
3598 DEF_FTNODE_VISITOR_BEGIN_VISIT( V, ftwindow_filter );
end_visit(ftwindow_filter & f)3599 void V::end_visit( ftwindow_filter &f ) {
3600 PlanIter_t it = plan_visitor_->pop_itstack();
3601 f.set_window_iter( it );
3602 sub_iters_.push_back( it );
3603 }
3604
DEF_FTNODE_VISITOR_VISIT_MEM_FNS(V,ftcase_option)3605 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftcase_option )
3606 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftdiacritics_option )
3607 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftextension_option )
3608 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftlanguage_option )
3609 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftmatch_options )
3610 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftstem_option )
3611 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftstop_word_option )
3612 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftstop_words )
3613 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftthesaurus_id )
3614 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftthesaurus_option )
3615 DEF_FTNODE_VISITOR_VISIT_MEM_FNS( V, ftwild_card_option )
3616
3617 #undef V
3618
3619 #endif /* ZORBA_NO_FULL_TEXT */
3620
3621 /******************************************************************************
3622
3623 ******************************************************************************/
3624
3625 PlanIter_t codegen(
3626 const char* descr,
3627 expr* root,
3628 CompilerCB* ccb,
3629 ulong& nextDynamicVarId,
3630 hash64map<std::vector<LetVarIter_t> *>* arg_var_map)
3631 {
3632 plan_visitor c(ccb, nextDynamicVarId, arg_var_map);
3633 root->accept(c);
3634 PlanIter_t result = c.result();
3635
3636 if (result != NULL &&
3637 descr != NULL &&
3638 Properties::instance()->printIteratorTree())
3639 {
3640 std::ostream& os = (Properties::instance()->iterPlanTest() ?
3641 std::cout :
3642 Properties::instance()->debug_out());
3643
3644 os << "Iterator tree for " << descr << ":\n";
3645 XMLIterPrinter vp(os);
3646 print_iter_plan(vp, result);
3647 os << std::endl;
3648 }
3649
3650 nextDynamicVarId = c.getNextDynamicVarId();
3651
3652 return result;
3653 }
3654
3655
3656 std::vector<PlanIter_t> plan_visitor::no_var_iters;
3657
3658 } // namespace zorba
3659 /* vim:set et sw=2 ts=2: */
3660