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