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 <typeinfo>
19 
20 #include "functions/func_sequences.h"
21 #include "functions/func_sequences_impl.h"
22 
23 #include "runtime/sequences/sequences.h"
24 #include "runtime/sequences/SequencesImpl.h"
25 #include "runtime/core/var_iterators.h"
26 
27 #include "runtime/collections/collections_impl.h"
28 #include "runtime/collections/collections.h"
29 #include "runtime/indexing/index_ddl.h"
30 
31 #include "system/globalenv.h"
32 
33 #include "compiler/expression/expr.h"
34 #include "compiler/expression/fo_expr.h"
35 #include "compiler/expression/path_expr.h"
36 
37 #include "types/typeops.h"
38 
39 namespace zorba
40 {
41 
42 
43 /*******************************************************************************
44 
45 ********************************************************************************/
getReturnType(const fo_expr * caller) const46 xqtref_t op_concatenate::getReturnType(const fo_expr* caller) const
47 {
48   TypeManager* tm = caller->get_type_manager();
49 
50   csize sz = caller->num_args();
51 
52   if (sz == 0)
53   {
54     return GENV_TYPESYSTEM.EMPTY_TYPE;
55   }
56   else
57   {
58     xqtref_t t = caller->get_arg(0)->get_return_type();
59     TypeConstants::quantifier_t q = TypeConstants::QUANT_STAR;
60     for (csize i = 1; i < sz; i++)
61     {
62       t = TypeOps::union_type(*t, *caller->get_arg(i)->get_return_type(), tm);
63 
64       TypeConstants::quantifier_t pq = t->get_quantifier();
65 
66       if (pq == TypeConstants::QUANT_ONE || pq == TypeConstants::QUANT_PLUS)
67         q = TypeConstants::QUANT_PLUS;
68     }
69 
70     return tm->create_type_x_quant(*t, q);
71   }
72 }
73 
74 
ignoresSortedNodes(expr * fo,csize input) const75 BoolAnnotationValue op_concatenate::ignoresSortedNodes(expr* fo, csize input) const
76 {
77   return fo->getIgnoresSortedNodes();
78 }
79 
80 
ignoresDuplicateNodes(expr * fo,csize input) const81 BoolAnnotationValue op_concatenate::ignoresDuplicateNodes(expr* fo, csize input) const
82 {
83   return fo->getIgnoresDuplicateNodes();
84 }
85 
86 
87 /*******************************************************************************
88 
89 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const90 BoolAnnotationValue fn_empty::ignoresSortedNodes(expr* fo, csize input) const
91 {
92   return ANNOTATION_TRUE;
93 }
94 
95 
ignoresDuplicateNodes(expr * fo,csize input) const96 BoolAnnotationValue fn_empty::ignoresDuplicateNodes(expr* fo, csize input) const
97 {
98   return ANNOTATION_TRUE;
99 }
100 
101 
102 /*******************************************************************************
103 
104 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const105 BoolAnnotationValue fn_exists::ignoresSortedNodes(expr* fo, csize input) const
106 {
107   return ANNOTATION_TRUE;
108 }
109 
110 
ignoresDuplicateNodes(expr * fo,csize input) const111 BoolAnnotationValue fn_exists::ignoresDuplicateNodes(expr* fo, csize input) const
112 {
113   return ANNOTATION_TRUE;
114 }
115 
116 
117 /*******************************************************************************
118 
119 ********************************************************************************/
getReturnType(const fo_expr * caller) const120 xqtref_t fn_distinct_values::getReturnType(const fo_expr* caller) const
121 {
122   return caller->get_arg(0)->get_return_type();
123 }
124 
125 
ignoresSortedNodes(expr * fo,csize input) const126 BoolAnnotationValue fn_distinct_values::ignoresSortedNodes(
127     expr* fo,
128     csize input) const
129 {
130   if (input == 0)
131     return fo->getIgnoresSortedNodes();
132 
133   return ANNOTATION_FALSE;
134 }
135 
136 
ignoresDuplicateNodes(expr * fo,csize input) const137 BoolAnnotationValue fn_distinct_values::ignoresDuplicateNodes(
138     expr* fo,
139     csize input) const
140 {
141   if (input == 0)
142     return ANNOTATION_TRUE;
143 
144   return ANNOTATION_FALSE;
145 }
146 
147 
148 /*******************************************************************************
149 
150 ********************************************************************************/
getReturnType(const fo_expr * caller) const151 xqtref_t fn_insert_before::getReturnType(const fo_expr* caller) const
152 {
153   TypeManager* tm = caller->get_type_manager();
154   xqtref_t list_type = caller->get_arg(0)->get_return_type();
155   xqtref_t insert_type = caller->get_arg(2)->get_return_type();
156 
157   return TypeOps::union_type(*list_type, *insert_type, tm);
158 }
159 
160 
ignoresSortedNodes(expr * fo,csize input) const161 BoolAnnotationValue fn_insert_before::ignoresSortedNodes(
162     expr* fo,
163     csize input) const
164 {
165   if (input == 0 || input == 2)
166     return fo->getIgnoresSortedNodes();
167 
168   return ANNOTATION_TRUE;
169 }
170 
171 
ignoresDuplicateNodes(expr * fo,csize input) const172 BoolAnnotationValue fn_insert_before::ignoresDuplicateNodes(
173     expr* fo,
174     csize input) const
175 {
176   if (input == 0 || input == 2)
177     return fo->getIgnoresSortedNodes();
178 
179   return ANNOTATION_FALSE;
180 }
181 
182 
183 /*******************************************************************************
184 
185 ********************************************************************************/
getReturnType(const fo_expr * caller) const186 xqtref_t fn_remove::getReturnType(const fo_expr* caller) const
187 {
188   TypeManager* tm = caller->get_type_manager();
189 
190   return tm->create_type_x_quant(*caller->get_arg(0)->get_return_type(),
191                                  TypeConstants::QUANT_QUESTION);
192 }
193 
194 
ignoresSortedNodes(expr * fo,csize input) const195 BoolAnnotationValue fn_remove::ignoresSortedNodes(
196     expr* fo,
197     csize input) const
198 {
199   if (input == 0)
200     return ANNOTATION_FALSE;
201 
202   return ANNOTATION_TRUE;
203 }
204 
205 
ignoresDuplicateNodes(expr * fo,csize input) const206 BoolAnnotationValue fn_remove::ignoresDuplicateNodes(
207     expr* fo,
208     csize input) const
209 {
210   return ANNOTATION_FALSE;
211 }
212 
213 
214 /*******************************************************************************
215 
216 ********************************************************************************/
getReturnType(const fo_expr * caller) const217 xqtref_t fn_reverse::getReturnType(const fo_expr* caller) const
218 {
219   return caller->get_arg(0)->get_return_type();
220 }
221 
222 
ignoresSortedNodes(expr * fo,csize input) const223 BoolAnnotationValue fn_reverse::ignoresSortedNodes(
224     expr* fo,
225     csize input) const
226 {
227   return fo->getIgnoresSortedNodes();
228 }
229 
230 
ignoresDuplicateNodes(expr * fo,csize input) const231 BoolAnnotationValue fn_reverse::ignoresDuplicateNodes(
232     expr* fo,
233     csize input) const
234 {
235   return fo->getIgnoresSortedNodes();
236 }
237 
238 
239 /*******************************************************************************
240 
241 ********************************************************************************/
getReturnType(const fo_expr * caller) const242 xqtref_t fn_subsequence::getReturnType(const fo_expr* caller) const
243 {
244   TypeManager* tm = caller->get_type_manager();
245   xqtref_t list_type = caller->get_arg(0)->get_return_type();
246 
247   //When there is a length argument and it's 1 then we know we will return
248   //a value type T? where the input sequence was type T* or T+
249   if (caller->num_args() > 2 &&
250       caller->get_arg(2)->get_expr_kind() == const_expr_kind)
251   {
252     store::Item* len_item = static_cast<const_expr*>(caller->get_arg(2))->get_val();
253 
254     if (len_item->getDoubleValue().round().getNumber() == 1)
255       return tm->create_type(*list_type, TypeConstants::QUANT_QUESTION);
256   }
257   return tm->create_type_x_quant(*list_type, TypeConstants::QUANT_QUESTION);
258 }
259 
260 
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr & aAnn) const261 PlanIter_t fn_subsequence::codegen(
262     CompilerCB* /*cb*/,
263     static_context* aSctx,
264     const QueryLoc& aLoc,
265     std::vector<PlanIter_t>& aArgs,
266     expr& aAnn) const
267 {
268   fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn);
269 
270   const expr* inputExpr = subseqExpr.get_arg(0);
271 
272   const expr* posExpr = subseqExpr.get_arg(1);
273 
274   const expr* lenExpr = (subseqExpr.num_args() > 2 ? subseqExpr.get_arg(2) : NULL);
275 
276   if (inputExpr->get_expr_kind() == relpath_expr_kind &&
277       posExpr->get_expr_kind() == const_expr_kind &&
278       lenExpr != NULL &&
279       lenExpr->get_expr_kind() == const_expr_kind)
280   {
281     xs_double dpos = static_cast<const const_expr*>(posExpr)->
282                       get_val()->getDoubleValue().round();
283     xs_integer ipos(dpos.getNumber());
284 
285     xs_double dlen = static_cast<const const_expr*>(lenExpr)->
286                       get_val()->getDoubleValue().round();
287     xs_integer ilen(dlen.getNumber());
288 
289     xs_long pos;
290     xs_long len;
291 
292     try
293     {
294       pos = to_xs_long(ipos);
295       len = to_xs_long(ilen);
296     }
297     catch (std::range_error&)
298     {
299       goto done;
300     }
301 
302     const relpath_expr* pathExpr = static_cast<const relpath_expr*>(inputExpr);
303 
304     csize numSteps = pathExpr->numSteps();
305 
306     if (pos > 0 && len == 1 && numSteps == 2)
307     {
308       AxisIteratorHelper* input = dynamic_cast<AxisIteratorHelper*>(aArgs[0].getp());
309       assert(input != NULL);
310 
311       if (input->setTargetPos(pos-1))
312         return aArgs[0];
313     }
314   }
315 
316  done:
317   return new FnSubsequenceIterator(aSctx, aLoc, aArgs);
318 }
319 
320 
321 /******************************************************************************
322 
323 *******************************************************************************/
getReturnType(const fo_expr * caller) const324 xqtref_t op_zorba_subsequence_int::getReturnType(const fo_expr* caller) const
325 {
326   TypeManager* tm = caller->get_type_manager();
327   xqtref_t list_type = caller->get_arg(0)->get_return_type();
328 
329   //When there is a length argument and it's 1 then we know we will return
330   //a value type T? where the input sequence was type T* or T+
331   if (caller->num_args() > 2 &&
332       caller->get_arg(2)->get_expr_kind() == const_expr_kind)
333   {
334     store::Item* len_item = static_cast<const_expr*>(caller->get_arg(2))->get_val();
335 
336     if (len_item->getIntegerValue() == Integer(1))
337       return tm->create_type(*list_type, TypeConstants::QUANT_QUESTION);
338   }
339 
340   return tm->create_type_x_quant(*list_type, TypeConstants::QUANT_QUESTION);
341 }
342 
343 
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr & aAnn) const344 PlanIter_t op_zorba_subsequence_int::codegen(
345     CompilerCB* /*cb*/,
346     static_context* aSctx,
347     const QueryLoc& aLoc,
348     std::vector<PlanIter_t>& aArgs,
349     expr& aAnn) const
350 {
351   fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn);
352 
353   const expr* inputExpr = subseqExpr.get_arg(0);
354 
355   const expr* posExpr = subseqExpr.get_arg(1);
356 
357   const expr* lenExpr = (subseqExpr.num_args() > 2 ? subseqExpr.get_arg(2) : NULL);
358 
359   LetVarIterator* letVarIter;
360   CtxVarIterator* ctxVarIter;
361 
362   if (inputExpr->get_expr_kind() == relpath_expr_kind &&
363       posExpr->get_expr_kind() == const_expr_kind &&
364       lenExpr != NULL &&
365       lenExpr->get_expr_kind() == const_expr_kind)
366   {
367     xs_long pos;
368     xs_long len;
369 
370     try
371     {
372       pos = static_cast<const const_expr*>(posExpr)->get_val()->getLongValue();
373       len = static_cast<const const_expr*>(lenExpr)->get_val()->getLongValue();
374     }
375     catch (std::range_error&)
376     {
377       goto done;
378     }
379 
380     const relpath_expr* pathExpr = static_cast<const relpath_expr*>(inputExpr);
381 
382     csize numSteps = pathExpr->numSteps();
383 
384     if (pos > 0 && len == 1 && numSteps == 2)
385     {
386       AxisIteratorHelper* input = dynamic_cast<AxisIteratorHelper*>(aArgs[0].getp());
387       assert(input != NULL);
388 
389       if (input->setTargetPos(pos-1))
390         return aArgs[0];
391     }
392   }
393   else if ((letVarIter = dynamic_cast<LetVarIterator*>(aArgs[0].getp())) != NULL)
394   {
395     const var_expr* inputVar = inputExpr->get_var();
396 
397     if (inputVar != NULL &&
398         (inputVar->get_kind() == var_expr::let_var ||
399          inputVar->get_kind() == var_expr::win_var ||
400          inputVar->get_kind() == var_expr::non_groupby_var) &&
401         letVarIter->setTargetPosIter(aArgs[1]) &&
402         letVarIter->setTargetLenIter(lenExpr ? aArgs[2] : NULL))
403     {
404       return aArgs[0];
405     }
406   }
407   else if ((ctxVarIter = dynamic_cast<CtxVarIterator*>(aArgs[0].getp())) != NULL)
408   {
409     const var_expr* inputVar = inputExpr->get_var();
410 
411     if (inputVar != NULL &&
412         !inputVar->is_context_item() &&
413         ctxVarIter->setTargetPosIter(aArgs[1]) &&
414         ctxVarIter->setTargetLenIter(lenExpr ? aArgs[2] : NULL))
415     {
416       return aArgs[0];
417     }
418   }
419 
420  done:
421   return new SubsequenceIntIterator(aSctx, aLoc, aArgs);
422 }
423 
424 
425 
426 /*******************************************************************************
427 
428 ********************************************************************************/
getReturnType(const fo_expr * caller) const429 xqtref_t op_zorba_sequence_point_access::getReturnType(
430     const fo_expr* caller) const
431 {
432   TypeManager* tm = caller->get_type_manager();
433 
434   return tm->create_type(*caller->get_arg(0)->get_return_type(),
435                          TypeConstants::QUANT_QUESTION);
436 }
437 
438 
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr & aAnn) const439 PlanIter_t op_zorba_sequence_point_access::codegen(
440     CompilerCB* /*cb*/,
441     static_context* aSctx,
442     const QueryLoc& aLoc,
443     std::vector<PlanIter_t>& aArgs,
444     expr& aAnn) const
445 {
446   fo_expr& subseqExpr = static_cast<fo_expr&>(aAnn);
447 
448   const expr* inputExpr = subseqExpr.get_arg(0);
449 
450   const expr* posExpr = subseqExpr.get_arg(1);
451 
452   LetVarIterator* inputVarIter;
453   CtxVarIterator* ctxVarIter;
454 
455   if (posExpr->get_expr_kind() == const_expr_kind)
456   {
457     store::Item* posItem = static_cast<const const_expr*>(posExpr)->get_val();
458 
459     xs_integer pos = posItem->getIntegerValue();;
460 
461     if (inputExpr->get_expr_kind() == relpath_expr_kind)
462     {
463       const relpath_expr* pathExpr = static_cast<const relpath_expr*>(inputExpr);
464 
465       csize numSteps = pathExpr->numSteps();
466 
467       if (pos > Integer(0) && numSteps == 2)
468       {
469         xs_long pos2;
470         try
471         {
472           pos2 = posItem->getLongValue();
473         }
474         catch (std::range_error&)
475         {
476           goto done;
477         }
478 
479         AxisIteratorHelper* input = dynamic_cast<AxisIteratorHelper*>(aArgs[0].getp());
480         assert(input != NULL);
481 
482         if (input->setTargetPos(pos2 - 1))
483           return aArgs[0];
484       }
485     }
486     else if ((inputVarIter = dynamic_cast<LetVarIterator*>(aArgs[0].getp())) != NULL)
487     {
488       const var_expr* inputVar = inputExpr->get_var();
489 
490       if (inputVar != NULL &&
491           (inputVar->get_kind() == var_expr::let_var ||
492            inputVar->get_kind() == var_expr::win_var ||
493            inputVar->get_kind() == var_expr::non_groupby_var) &&
494           inputVarIter->setTargetPos(pos))
495       {
496         return aArgs[0];
497       }
498     }
499     else if ((ctxVarIter = dynamic_cast<CtxVarIterator*>(aArgs[0].getp())) != NULL)
500     {
501       if (ctxVarIter->setTargetPos(pos))
502         return aArgs[0];
503     }
504   }
505   else if ((inputVarIter = dynamic_cast<LetVarIterator*>(aArgs[0].getp())) != NULL)
506   {
507     const var_expr* inputVar = inputExpr->get_var();
508 
509     if (inputVar != NULL &&
510         (inputVar->get_kind() == var_expr::let_var ||
511          inputVar->get_kind() == var_expr::win_var ||
512          inputVar->get_kind() == var_expr::non_groupby_var) &&
513         inputVarIter->setTargetPosIter(aArgs[1]))
514     {
515       return aArgs[0];
516     }
517   }
518   else if ((ctxVarIter = dynamic_cast<CtxVarIterator*>(aArgs[0].getp())) != NULL)
519   {
520     if (ctxVarIter->setTargetPosIter(aArgs[1]))
521       return aArgs[0];
522   }
523 
524  done:
525   return new SequencePointAccessIterator(aSctx, aLoc, aArgs);
526 }
527 
528 
529 /******************************************************************************
530 fn:count
531 *******************************************************************************/
codegen(CompilerCB *,static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & argv,expr & ann) const532 PlanIter_t fn_count::codegen(
533   CompilerCB*,
534   static_context* sctx,
535   const QueryLoc& loc,
536   std::vector<PlanIter_t>& argv,
537   expr& ann) const
538 {
539   const std::type_info& counted_type = typeid(*argv[0]);
540 
541   if (typeid(ZorbaCollectionIterator) == counted_type)
542   {
543     ZorbaCollectionIterator& collection =
544     static_cast<ZorbaCollectionIterator&>(*argv[0]);
545 
546     if (collection.isCountOptimizable())
547     {
548       return new CountCollectionIterator(
549                    sctx,
550                    loc,
551                    collection.getChildren(),
552                    (
553                      collection.isDynamic()
554                        ? CountCollectionIterator::ZORBADYNAMIC
555                        : CountCollectionIterator::ZORBASTATIC
556                    )
557                  );
558     }
559   }
560   else if (typeid(FnCollectionIterator) == counted_type)
561   {
562     FnCollectionIterator& collection =
563     static_cast<FnCollectionIterator&>(*argv[0]);
564 
565     return new CountCollectionIterator(sctx,
566                                        loc,
567                                        collection.getChildren(),
568                                        CountCollectionIterator::W3C);
569   }
570   else if (typeid(ProbeIndexPointValueIterator) == counted_type)
571   {
572     ProbeIndexPointValueIterator& lIter
573       = static_cast<ProbeIndexPointValueIterator&>(*argv[0]);
574 
575     return new ProbeIndexPointValueIterator(
576         sctx, loc, lIter.getChildren(), true, lIter.hasSkip());
577   }
578   else if (typeid(ProbeIndexRangeValueIterator) == counted_type)
579   {
580     ProbeIndexRangeValueIterator& lIter
581       = static_cast<ProbeIndexRangeValueIterator&>(*argv[0]);
582 
583     return new ProbeIndexRangeValueIterator(
584         sctx, loc, lIter.getChildren(), true, lIter.hasSkip());
585   }
586   else if (typeid(ProbeIndexPointGeneralIterator) == counted_type)
587   {
588     ProbeIndexPointGeneralIterator& lIter
589       = static_cast<ProbeIndexPointGeneralIterator&>(*argv[0]);
590 
591     return new ProbeIndexPointGeneralIterator(
592         sctx, loc, lIter.getChildren(), true);
593   }
594   else if (typeid(ProbeIndexRangeGeneralIterator) == counted_type)
595   {
596     ProbeIndexRangeGeneralIterator& lIter
597       = static_cast<ProbeIndexRangeGeneralIterator&>(*argv[0]);
598 
599     return new ProbeIndexRangeGeneralIterator(
600         sctx, loc, lIter.getChildren(), true);
601   }
602 
603   // fallback
604   return new FnCountIterator(sctx, loc, argv);
605 }
606 
607 
608 /*******************************************************************************
609 
610 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const611 BoolAnnotationValue fn_unordered::ignoresSortedNodes(expr* fo, csize input) const
612 {
613   return ANNOTATION_TRUE;
614 }
615 
616 
ignoresDuplicateNodes(expr * fo,csize input) const617 BoolAnnotationValue fn_unordered::ignoresDuplicateNodes(expr* fo, csize input) const
618 {
619   return fo->getIgnoresDuplicateNodes();
620 }
621 
622 
codegen(CompilerCB *,static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & argv,expr &) const623 PlanIter_t fn_unordered::codegen(
624     CompilerCB* /*cb*/,
625     static_context* sctx,
626     const QueryLoc& loc,
627     std::vector<PlanIter_t>& argv,
628     expr& ) const
629 {
630   return argv[0];
631 }
632 
633 
634 /*******************************************************************************
635 
636 ********************************************************************************/
getReturnType(const fo_expr * caller) const637 xqtref_t fn_zero_or_one::getReturnType(const fo_expr* caller) const
638 {
639   TypeManager* tm = caller->get_type_manager();
640 
641   xqtref_t srcType = caller->get_arg(0)->get_return_type();
642 
643   return tm->create_type(*TypeOps::prime_type(tm, *srcType),
644                          TypeConstants::QUANT_QUESTION);
645 }
646 
647 
ignoresSortedNodes(expr * fo,csize input) const648 BoolAnnotationValue fn_zero_or_one::ignoresSortedNodes(expr* fo, csize input) const
649 {
650   return ANNOTATION_TRUE;
651 }
652 
653 
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr & aAnn) const654 PlanIter_t fn_zero_or_one::codegen(
655     CompilerCB* /*cb*/,
656     static_context* aSctx,
657     const QueryLoc& aLoc,
658     std::vector<PlanIter_t>& aArgs,
659     expr& aAnn) const
660 {
661   return new FnZeroOrOneIterator(aSctx,
662                                  aLoc,
663                                  aArgs,
664                                  testFlag(FunctionConsts::DoDistinct));
665 }
666 
667 
668 /*******************************************************************************
669 
670 ********************************************************************************/
getReturnType(const fo_expr * caller) const671 xqtref_t fn_one_or_more::getReturnType(const fo_expr* caller) const
672 {
673   TypeManager* tm = caller->get_type_manager();
674 
675   return tm->create_type(
676       *TypeOps::prime_type(tm, *(caller->get_arg(0)->get_return_type())),
677       TypeConstants::QUANT_PLUS);
678 }
679 
680 
ignoresSortedNodes(expr * fo,csize input) const681 BoolAnnotationValue fn_one_or_more::ignoresSortedNodes(expr* fo, csize input) const
682 {
683   return fo->getIgnoresSortedNodes();
684 }
685 
686 
ignoresDuplicateNodes(expr * fo,csize input) const687 BoolAnnotationValue fn_one_or_more::ignoresDuplicateNodes(expr* fo, csize input) const
688 {
689   return fo->getIgnoresDuplicateNodes();
690 }
691 
692 
693 /*******************************************************************************
694 
695 ********************************************************************************/
getReturnType(const fo_expr * caller) const696 xqtref_t fn_exactly_one_noraise::getReturnType(const fo_expr* caller) const
697 {
698   TypeManager* tm = caller->get_type_manager();
699 
700   xqtref_t srcType = caller->get_arg(0)->get_return_type();
701 
702   if (theRaiseError)
703     return TypeOps::prime_type(tm, *srcType);
704   else
705     return function::getReturnType(caller);
706 }
707 
708 
codegen(CompilerCB * aCb,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr & aAnn) const709 PlanIter_t fn_exactly_one_noraise::codegen(
710     CompilerCB* aCb,
711     static_context* aSctx,
712     const QueryLoc& aLoc,
713     std::vector<PlanIter_t>& aArgs,
714     expr& aAnn) const
715 {
716   return new FnExactlyOneIterator(aSctx,
717                                   aLoc,
718                                   aArgs,
719                                   theRaiseError,
720                                   testFlag(FunctionConsts::DoDistinct));
721 }
722 
723 
724 /*******************************************************************************
725 
726 ********************************************************************************/
codegen(CompilerCB *,static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & argv,expr & ann) const727 PlanIter_t fn_union::codegen(
728     CompilerCB* /*cb*/,
729     static_context* sctx,
730     const QueryLoc& loc,
731     std::vector<PlanIter_t>& argv,
732     expr& ann) const
733 {
734   return new FnConcatIterator(sctx, loc, argv);
735 }
736 
737 
738 /*******************************************************************************
739 
740 ********************************************************************************/
codegen(CompilerCB *,static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & argv,expr & ann) const741 PlanIter_t fn_intersect::codegen(
742     CompilerCB* /*cb*/,
743     static_context* sctx,
744     const QueryLoc& loc,
745     std::vector<PlanIter_t>& argv,
746     expr& ann) const
747 {
748 #if 0  // we can't access PRODUCES_* from the inputs, must rethink
749   bool distinct = ann.get_annotation (Annotations::IGNORES_DUP_NODES) != TSVAnnotationValue::TRUE_VAL;
750   bool sort = ann.get_annotation (Annotations::IGNORES_SORTED_NODES) != TSVAnnotationValue::TRUE_VAL;
751 
752   std::vector<PlanIter_t> inputs;
753   for (std::vector<PlanIter_t>::iterator i = argv.begin ();
754        i != argv.end (); i++)
755     inputs.push_back (new NodeSortIterator (loc, *i, true, distinct, false));
756   return new SortSemiJoinIterator(loc, inputs);
757 #endif
758 
759   return new HashSemiJoinIterator(sctx, loc, argv);
760 }
761 
762 
763 /*******************************************************************************
764 
765 ********************************************************************************/
codegen(CompilerCB *,static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & argv,expr & ann) const766 PlanIter_t fn_except::codegen(
767     CompilerCB* /*cb*/,
768     static_context* sctx,
769     const QueryLoc& loc,
770     std::vector<PlanIter_t>& argv,
771     expr& ann) const
772 {
773   // TODO: use SortAntiJoinIterator when available (trac ticket 254)
774   return new HashSemiJoinIterator(sctx, loc, argv, true);
775 }
776 
777 
778 /*******************************************************************************
779 
780 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const781 BoolAnnotationValue fn_count::ignoresSortedNodes(expr* fo, csize input) const
782 {
783   return ANNOTATION_TRUE;
784 }
785 
786 
787 /*******************************************************************************
788 
789 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const790 BoolAnnotationValue fn_avg::ignoresSortedNodes(expr* fo, csize input) const
791 {
792   return ANNOTATION_TRUE;
793 }
794 
795 
796 /*******************************************************************************
797 
798 ********************************************************************************/
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr &) const799 PlanIter_t fn_max::codegen(
800     CompilerCB* /*cb*/,
801     static_context* aSctx,
802     const QueryLoc& aLoc,
803     std::vector<PlanIter_t>& aArgs,
804     expr& /*aAnn*/) const
805 {
806   return new FnMinMaxIterator(aSctx, aLoc, aArgs, FnMinMaxIterator::MAX);
807 }
808 
809 
810 /*******************************************************************************
811 
812 ********************************************************************************/
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr &) const813 PlanIter_t fn_min::codegen(
814     CompilerCB* /*cb*/,
815     static_context* aSctx,
816     const QueryLoc& aLoc,
817     std::vector<PlanIter_t>& aArgs,
818     expr& /*ann*/) const
819 {
820   return new FnMinMaxIterator(aSctx, aLoc, aArgs, FnMinMaxIterator::MIN);
821 }
822 
823 
824 /*******************************************************************************
825 
826 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const827 BoolAnnotationValue fn_sum::ignoresSortedNodes(expr* fo, csize input) const
828 {
829   return ANNOTATION_TRUE;
830 }
831 
832 
833 /*******************************************************************************
834 
835 ********************************************************************************/
specialize(static_context * sctx,const std::vector<xqtref_t> & argTypes) const836 function* fn_sum::specialize(
837    static_context* sctx,
838    const std::vector<xqtref_t>& argTypes) const
839 {
840   RootTypeManager& rtm = GENV_TYPESYSTEM;
841   TypeManager* tm = sctx->get_typemanager();
842 
843   xqtref_t argType = argTypes[0];
844 
845   if (TypeOps::is_subtype(tm, *argType, *rtm.UNTYPED_ATOMIC_TYPE_STAR))
846   {
847     return (getArity() == 1 ?
848             GET_BUILTIN_FUNCTION(OP_SUM_DOUBLE_1) :
849             GET_BUILTIN_FUNCTION(OP_SUM_DOUBLE_2));
850   }
851   else if (TypeOps::is_subtype(tm, *argType, *rtm.DOUBLE_TYPE_STAR))
852   {
853     return (getArity() == 1 ?
854             GET_BUILTIN_FUNCTION(OP_SUM_DOUBLE_1) :
855             GET_BUILTIN_FUNCTION(OP_SUM_DOUBLE_2));
856   }
857   else if (TypeOps::is_subtype(tm, *argType, *rtm.FLOAT_TYPE_STAR))
858   {
859     return (getArity() == 1 ?
860             GET_BUILTIN_FUNCTION(OP_SUM_FLOAT_1) :
861             GET_BUILTIN_FUNCTION(OP_SUM_FLOAT_2));
862   }
863   else if (TypeOps::is_subtype(tm, *argType, *rtm.INTEGER_TYPE_STAR))
864   {
865     return (getArity() == 1 ?
866             GET_BUILTIN_FUNCTION(OP_SUM_INTEGER_1) :
867             GET_BUILTIN_FUNCTION(OP_SUM_INTEGER_2));
868   }
869   else if (TypeOps::is_subtype(tm, *argType, *rtm.DECIMAL_TYPE_STAR))
870   {
871     return (getArity() == 1 ?
872             GET_BUILTIN_FUNCTION(OP_SUM_DECIMAL_1) :
873             GET_BUILTIN_FUNCTION(OP_SUM_DECIMAL_2));
874   }
875   else
876   {
877     return NULL;
878   }
879 }
880 
881 
882 /*******************************************************************************
883 
884 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const885 BoolAnnotationValue op_sum_double::ignoresSortedNodes(expr* fo, csize input) const
886 {
887   return ANNOTATION_TRUE;
888 }
889 
890 
891 /*******************************************************************************
892 
893 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const894 BoolAnnotationValue op_sum_float::ignoresSortedNodes(expr* fo, csize input) const
895 {
896   return ANNOTATION_TRUE;
897 }
898 
899 
900 /*******************************************************************************
901 
902 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const903 BoolAnnotationValue op_sum_decimal::ignoresSortedNodes(expr* fo, csize input) const
904 {
905   return ANNOTATION_TRUE;
906 }
907 
908 
909 /*******************************************************************************
910 
911 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const912 BoolAnnotationValue op_sum_integer::ignoresSortedNodes(expr* fo, csize input) const
913 {
914   return ANNOTATION_TRUE;
915 }
916 
917 
918 /*******************************************************************************
919 
920 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const921 BoolAnnotationValue fn_id::ignoresSortedNodes(expr* fo, csize input) const
922 {
923   return ANNOTATION_TRUE;
924 }
925 
926 
ignoresDuplicateNodes(expr * fo,csize input) const927 BoolAnnotationValue fn_id::ignoresDuplicateNodes(expr* fo, csize input) const
928 {
929   if (input == 0)
930     return ANNOTATION_TRUE;
931 
932   return ANNOTATION_FALSE;
933 }
934 
935 
936 /*******************************************************************************
937 
938 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const939 BoolAnnotationValue fn_element_with_id::ignoresSortedNodes(
940     expr* fo,
941     csize input) const
942 {
943   return ANNOTATION_TRUE;
944 }
945 
946 
ignoresDuplicateNodes(expr * fo,csize input) const947 BoolAnnotationValue fn_element_with_id::ignoresDuplicateNodes(
948     expr* fo,
949     csize input) const
950 {
951   if (input == 0)
952     return ANNOTATION_TRUE;
953 
954   return ANNOTATION_FALSE;
955 }
956 
957 
958 /*******************************************************************************
959 
960 ********************************************************************************/
ignoresSortedNodes(expr * fo,csize input) const961 BoolAnnotationValue fn_idref::ignoresSortedNodes(expr* fo, csize input) const
962 {
963   return ANNOTATION_TRUE;
964 }
965 
966 
ignoresDuplicateNodes(expr * fo,csize input) const967 BoolAnnotationValue fn_idref::ignoresDuplicateNodes(expr* fo, csize input) const
968 {
969   if (input == 0)
970     return ANNOTATION_TRUE;
971 
972   return ANNOTATION_FALSE;
973 }
974 
975 
976 /*******************************************************************************
977 
978 ********************************************************************************/
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr &) const979 PlanIter_t fn_head::codegen(
980     CompilerCB* /*cb*/,
981     static_context* aSctx,
982     const QueryLoc& aLoc,
983     std::vector<PlanIter_t>& aArgs,
984     expr& /*aAnn*/) const
985 {
986   ZORBA_ASSERT(false);
987   return NULL;
988 }
989 
990 
991 /*******************************************************************************
992 
993 ********************************************************************************/
codegen(CompilerCB *,static_context * aSctx,const QueryLoc & aLoc,std::vector<PlanIter_t> & aArgs,expr &) const994 PlanIter_t fn_tail::codegen(
995     CompilerCB* /*cb*/,
996     static_context* aSctx,
997     const QueryLoc& aLoc,
998     std::vector<PlanIter_t>& aArgs,
999     expr& /*aAnn*/) const
1000 {
1001   ZORBA_ASSERT(false);
1002   return NULL;
1003 }
1004 
1005 
1006 /*******************************************************************************
1007 
1008 ********************************************************************************/
populate_context_sequences_impl(static_context * sctx)1009 void populate_context_sequences_impl(static_context* sctx)
1010 {
1011   const char* xquery_op_ns = static_context::XQUERY_OP_NS;
1012   const char* zorba_op_ns = static_context::ZORBA_OP_NS;
1013   const char* fn_ns = static_context::W3C_FN_NS;
1014 
1015   DECL(sctx, fn_unordered,
1016        (createQName(fn_ns, "", "unordered"),
1017         GENV_TYPESYSTEM.ITEM_TYPE_STAR,
1018         GENV_TYPESYSTEM.ITEM_TYPE_STAR));
1019 
1020   DECL(sctx, fn_exactly_one,
1021        (createQName(fn_ns, "", "exactly-one"),
1022         GENV_TYPESYSTEM.ITEM_TYPE_STAR,
1023         GENV_TYPESYSTEM.ITEM_TYPE_ONE));
1024 
1025   DECL(sctx, fn_exactly_one_noraise,
1026        (createQName(zorba_op_ns, "", "exactly-one-noraise"),
1027         GENV_TYPESYSTEM.ITEM_TYPE_STAR,
1028         GENV_TYPESYSTEM.BOOLEAN_TYPE_ONE));
1029 
1030   DECL(sctx, fn_union,
1031        (createQName(xquery_op_ns,"","union"),
1032         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR,
1033         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR,
1034         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR));
1035 
1036   DECL(sctx, fn_intersect,
1037        (createQName(xquery_op_ns,"","intersect"),
1038         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR,
1039         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR,
1040         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR));
1041 
1042   DECL(sctx, fn_except,
1043        (createQName(xquery_op_ns,"","except"),
1044         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR,
1045         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR,
1046         GENV_TYPESYSTEM.ANY_NODE_TYPE_STAR));
1047 
1048   DECL(sctx, fn_max,
1049        (createQName(fn_ns,"","max"),
1050         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
1051         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION));
1052 
1053   DECL(sctx, fn_max,
1054        (createQName(fn_ns,"","max"),
1055         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
1056         GENV_TYPESYSTEM.STRING_TYPE_ONE,
1057         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION));
1058 
1059   DECL(sctx, fn_min,
1060        (createQName(fn_ns,"","min"),
1061         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
1062         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION));
1063 
1064   DECL(sctx, fn_min,
1065        (createQName(fn_ns,"","min"),
1066         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
1067         GENV_TYPESYSTEM.STRING_TYPE_ONE,
1068         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION));
1069 
1070   DECL(sctx, fn_head,
1071        (createQName(fn_ns,"","head"),
1072         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
1073         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION));
1074 
1075   DECL(sctx, fn_tail,
1076        (createQName(fn_ns,"","tail"),
1077         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR,
1078         GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR));
1079 
1080 }
1081 
1082 } /* namespace zorba */
1083 /* vim:set et sw=2 ts=2: */
1084