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 "zorbautils/fatal.h"
19 #include "diagnostics/assert.h"
20 #include "diagnostics/util_macros.h"
21 #include "diagnostics/xquery_diagnostics.h"
22 #include "diagnostics/util_macros.h"
23
24 #include "system/globalenv.h"
25
26 #include "types/root_typemanager.h"
27 #include "types/casting.h"
28 #include "types/typeops.h"
29
30 #include "context/static_context.h"
31 #include "context/namespace_context.h"
32
33 #include "compiler/api/compilercb.h"
34
35 #include "runtime/core/constructors.h"
36 #include "runtime/visitors/planiter_visitor.h"
37 #include "runtime/api/plan_iterator_wrapper.h"
38
39 #include "store/api/temp_seq.h"
40 #include "store/api/item_factory.h"
41 #include "store/api/copymode.h"
42
43 #include "util/ascii_util.h"
44 #include "util/string_util.h"
45 #include "util/utf8_util.h"
46
47 using namespace std;
48
49 namespace zorba
50 {
51
52 SERIALIZABLE_CLASS_VERSIONS(DocumentIterator)
53
SERIALIZABLE_CLASS_VERSIONS(ElementIterator)54 SERIALIZABLE_CLASS_VERSIONS(ElementIterator)
55
56 SERIALIZABLE_CLASS_VERSIONS(AttributeIterator)
57
58 SERIALIZABLE_CLASS_VERSIONS(NameCastIterator)
59
60 SERIALIZABLE_CLASS_VERSIONS(CommentIterator)
61
62 SERIALIZABLE_CLASS_VERSIONS(PiIterator)
63
64 SERIALIZABLE_CLASS_VERSIONS(TextIterator)
65
66 SERIALIZABLE_CLASS_VERSIONS(EnclosedIterator)
67
68 /*******************************************************************************
69
70 ********************************************************************************/
71 DocumentIterator::DocumentIterator(
72 static_context* sctx,
73 const QueryLoc& loc,
74 PlanIter_t& child,
75 bool copyInputNodes)
76 :
77 UnaryBaseIterator<DocumentIterator, PlanIteratorState>(sctx, loc, child),
78 theTypePreserve(false),
79 theNsPreserve(false),
80 theNsInherit(false),
81 theCopyInputNodes(copyInputNodes)
82 {
83 }
84
85
serialize(::zorba::serialization::Archiver & ar)86 void DocumentIterator::serialize(::zorba::serialization::Archiver& ar)
87 {
88 serialize_baseclass(ar,
89 (UnaryBaseIterator<DocumentIterator, PlanIteratorState>*)this);
90
91 ar & theTypePreserve;
92 ar & theNsPreserve;
93 ar & theNsInherit;
94 ar & theCopyInputNodes;
95 }
96
97
openImpl(PlanState & planState,uint32_t & offset)98 void DocumentIterator::openImpl(PlanState& planState, uint32_t& offset)
99 {
100 UnaryBaseIterator<DocumentIterator, PlanIteratorState>::openImpl(planState, offset);
101
102 theTypePreserve =
103 (theSctx->construction_mode() == StaticContextConsts::cons_preserve ? true : false);
104
105 theNsPreserve = theSctx->preserve_ns();
106
107 theNsInherit = theSctx->inherit_ns();
108 }
109
110
nextImpl(store::Item_t & result,PlanState & planState) const111 bool DocumentIterator::nextImpl(store::Item_t& result, PlanState& planState) const
112 {
113 // Note: baseUri has to be rchandle because if createDocumentNode throws
114 // an exception, we don't know if the exception was thrown before or after
115 // the ownership of the uri was transfered to the doc node.
116 zstring baseUri = theSctx->get_base_uri();
117 zstring docUri;
118
119 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
120 store::CopyMode copymode;
121 store::Item_t child;
122
123 PlanIteratorState* state;
124 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
125
126 GENV_ITEMFACTORY->createDocumentNode(result, baseUri, docUri);
127
128 path.push(result);
129
130 // Compute the children of the element node
131 copymode.set(theCopyInputNodes, theTypePreserve, theNsPreserve, theNsInherit);
132
133 try
134 {
135 while (consumeNext(child, theChild, planState))
136 {
137 ZORBA_FATAL(child->isNode(), "");
138
139 if (child->getNodeKind() == store::StoreConsts::attributeNode)
140 {
141 RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(NoAttrNodesInDocument)));
142 }
143
144 if (child->getParent() != result.getp())
145 {
146 // Skip text node with zero-length value
147 if (child->getNodeKind() == store::StoreConsts::textNode &&
148 child->getStringValue().empty())
149 {
150 continue;
151 }
152
153 child->copy(result, copymode);
154 }
155 }
156
157 result->finalizeNode();
158 }
159 catch (...)
160 {
161 path.pop();
162 result = NULL;
163 throw;
164 }
165
166 path.pop();
167
168 STACK_PUSH(true, state);
169 STACK_END (state);
170 }
171
172
173 UNARY_ACCEPT(DocumentIterator);
174
175
176 /*******************************************************************************
177
178 ********************************************************************************/
init(PlanState &)179 void ElementIteratorState::init(PlanState&)
180 {
181 }
182
183
reset(PlanState &)184 void ElementIteratorState::reset(PlanState&)
185 {
186 baseUri.clear();
187 }
188
189
ElementIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & qnameIter,PlanIter_t & attrsIter,PlanIter_t & childrenIter,const namespace_context * localBindings,bool isRoot,bool copyInputNodes)190 ElementIterator::ElementIterator (
191 static_context* sctx,
192 const QueryLoc& loc,
193 PlanIter_t& qnameIter,
194 PlanIter_t& attrsIter,
195 PlanIter_t& childrenIter,
196 const namespace_context* localBindings,
197 bool isRoot,
198 bool copyInputNodes)
199 :
200 NoaryBaseIterator<ElementIterator, ElementIteratorState>(sctx, loc),
201 theQNameIter(qnameIter),
202 theAttributesIter(attrsIter),
203 theChildrenIter(childrenIter),
204 theLocalBindings(const_cast<namespace_context*>(localBindings)),
205 theIsRoot(isRoot),
206 theTypePreserve(false),
207 theNsPreserve(false),
208 theNsInherit(false),
209 theCopyInputNodes(copyInputNodes)
210 {
211 }
212
213
serialize(::zorba::serialization::Archiver & ar)214 void ElementIterator::serialize(::zorba::serialization::Archiver& ar)
215 {
216 serialize_baseclass(ar, (NoaryBaseIterator<ElementIterator,
217 ElementIteratorState>*)this);
218 ar & theQNameIter;
219 ar & theAttributesIter;
220 ar & theChildrenIter;
221 ar & theNamespacesIter;
222 ar & theLocalBindings;
223 ar & theIsRoot;
224 ar & theTypePreserve;
225 ar & theNsPreserve;
226 ar & theNsInherit;
227 ar & theCopyInputNodes;
228 }
229
230
getStateSizeOfSubtree() const231 uint32_t ElementIterator::getStateSizeOfSubtree() const
232 {
233 int32_t size = 0;
234
235 if (theQNameIter != 0)
236 size += theQNameIter->getStateSizeOfSubtree();
237
238 if (theChildrenIter != 0)
239 size += theChildrenIter->getStateSizeOfSubtree();
240
241 if (theAttributesIter != 0)
242 size += theAttributesIter->getStateSizeOfSubtree();
243
244 if (theNamespacesIter != 0)
245 size += theNamespacesIter->getStateSizeOfSubtree();
246
247 return getStateSize() + size;
248 }
249
250
accept(PlanIterVisitor & v) const251 void ElementIterator::accept(PlanIterVisitor& v) const
252 {
253 v.beginVisit(*this);
254
255 if (theQNameIter != 0)
256 theQNameIter->accept(v);
257
258 if (theAttributesIter != 0)
259 theAttributesIter->accept(v);
260
261 if (theChildrenIter != 0)
262 theChildrenIter->accept(v);
263
264 if (theNamespacesIter != 0)
265 theNamespacesIter->accept(v);
266
267 v.endVisit(*this);
268 }
269
270
openImpl(PlanState & planState,uint32_t & offset)271 void ElementIterator::openImpl(PlanState& planState, uint32_t& offset)
272 {
273 StateTraitsImpl<ElementIteratorState>::createState(planState,
274 theStateOffset,
275 offset);
276
277 StateTraitsImpl<ElementIteratorState>::initState(planState, theStateOffset);
278
279 if (theQNameIter != 0)
280 theQNameIter->open(planState, offset);
281
282 if ( theChildrenIter != 0 )
283 theChildrenIter->open(planState, offset);
284
285 if (theAttributesIter != 0)
286 theAttributesIter->open(planState, offset);
287
288 if (theNamespacesIter != 0)
289 theNamespacesIter->open(planState, offset);
290
291 theTypePreserve =
292 (theSctx->construction_mode() == StaticContextConsts::cons_preserve ? true : false);
293
294 theNsPreserve = theSctx->preserve_ns();
295
296 theNsInherit = theSctx->inherit_ns();
297 }
298
299
nextImpl(store::Item_t & result,PlanState & planState) const300 bool ElementIterator::nextImpl(store::Item_t& result, PlanState& planState) const
301 {
302 store::ItemFactory* factory = GENV_ITEMFACTORY;
303
304 store::Item* parent;
305 store::Item_t nodeName;
306 store::Item_t typeName;
307 store::Item_t nullValue;
308 zstring content;
309
310 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
311 store::Item_t attr;
312 store::Item_t child;
313 store::CopyMode copymode;
314 zstring baseuri;
315 zstring pre;
316 zstring ns;
317
318 ElementIteratorState* state;
319 DEFAULT_STACK_INIT(ElementIteratorState, state, planState);
320
321 // Compute the node name. Note: the compiler wraps an xs:qname cast around
322 // the name expression, so we know that consumeNext() returns exactly one,
323 // well formed qname.
324 consumeNext(nodeName, theQNameIter, planState);
325
326 if (nodeName->getLocalName().empty())
327 {
328 RAISE_ERROR(err::XQDY0074, loc, ERROR_PARAMS("", ZED(NoEmptyLocalname)));
329 }
330
331 pre = nodeName->getPrefix();
332 ns = nodeName->getNamespace();
333
334 if (pre == "xmlns" ||
335 ns == "http://www.w3.org/2000/xmlns/" ||
336 (pre == "xml" && ns != "http://www.w3.org/XML/1998/namespace") ||
337 (pre != "xml" && ns == "http://www.w3.org/XML/1998/namespace"))
338 {
339 RAISE_ERROR(err::XQDY0096, loc, ERROR_PARAMS(nodeName->getStringValue()));
340 }
341
342 typeName = (theTypePreserve ?
343 GENV_TYPESYSTEM.XS_ANY_TYPE_QNAME :
344 GENV_TYPESYSTEM.XS_UNTYPED_QNAME);
345
346 // Get the parent, if any, of the new element node
347 ZORBA_FATAL(theIsRoot || !path.empty(), "");
348 parent = (theIsRoot ? NULL : path.top());
349
350 if (theIsRoot)
351 {
352 // Conservatively, assign the base uri from the static ctx as the base uri
353 // of the new node. If theAttributesIter does not later produce any explicit
354 // base-uri attribute, then the base-uri used here is the correct one, and
355 // it MUST be assigned here, because it is needed for resolving any relative
356 // uris that may appear in the children. If theAttributesIter does produce
357 // an explicit base-uri attribute, then the base-uri added here will be
358 // replaced with the explicit one.
359 state->baseUri = theSctx->get_base_uri();
360 if (state->baseUri.empty())
361 RAISE_ERROR(err::XPST0001, loc, ERROR_PARAMS("", ZED(BaseURI)));
362
363 store::NsBindings bindings;
364 theLocalBindings->getAllBindings(bindings);
365
366 // Create the element node and push it to the construction path.
367 GENV_ITEMFACTORY->createElementNode(result,
368 parent,
369 nodeName,
370 typeName,
371 true,
372 false,
373 bindings,
374 state->baseUri);
375 }
376 else
377 {
378 // Create the element node and push it to the construction path.
379 GENV_ITEMFACTORY->createElementNode(result,
380 parent,
381 nodeName,
382 typeName,
383 true,
384 false,
385 theLocalBindings->getLocalBindings(),
386 state->baseUri);
387 }
388
389 path.push(result);
390
391 // Compute the attributes and children of the element node
392 copymode.set(theCopyInputNodes, theTypePreserve, theNsPreserve, theNsInherit);
393
394 try
395 {
396 if (theAttributesIter != 0)
397 {
398 while (consumeNext(attr, theAttributesIter, planState))
399 {
400 assert(attr->isNode());
401 assert(attr->getNodeKind() == store::StoreConsts::attributeNode);
402
403 if (attr->getParent() != result.getp())
404 attr->copy(result, copymode);
405 }
406 }
407
408 if (theChildrenIter != 0)
409 {
410 bool valid = false;
411
412 while ((valid = consumeNext(child, theChildrenIter, planState)))
413 {
414 if (!child->isNode())
415 {
416 assert(child->isAtomic());
417
418 child->getStringValue2(content);
419 factory->createTextNode(child, result, content);
420 }
421
422 assert(child->getNodeKind() != store::StoreConsts::documentNode);
423
424 if (child->getNodeKind() != store::StoreConsts::attributeNode)
425 {
426 // Remove empty text nodes, as per 3.8.3.1 Computed Element Constructors
427 // http://www.w3.org/TR/xquery-30/#id-computedElements
428 if (child->getNodeKind() == store::StoreConsts::textNode &&
429 child->getStringValue().empty())
430 continue;
431 else
432 break;
433 }
434
435 if (child->getParent() != result.getp())
436 child->copy(result, copymode);
437 }
438
439 while (valid)
440 {
441 if (!child->isNode())
442 {
443 assert(child->isAtomic());
444 child->getStringValue2(content);
445 factory->createTextNode(child, result, content);
446 }
447
448 assert(child->getNodeKind() != store::StoreConsts::documentNode);
449
450 if (child->getNodeKind() == store::StoreConsts::attributeNode)
451 throw XQUERY_EXCEPTION(err::XQTY0024, ERROR_LOC(loc));
452
453 // Skip text node with zero-length value
454 if (child->getNodeKind() == store::StoreConsts::textNode &&
455 child->getStringValue().empty())
456 {
457 ;
458 }
459 // Else copy the child node if it was not a node constructed by a
460 // directly nested constructor
461 else if (child->getParent() != result.getp())
462 {
463 child->copy(result, copymode);
464 }
465
466 valid = consumeNext(child, theChildrenIter, planState);
467 }
468 }
469
470 result->finalizeNode();
471 }
472 catch (XQueryException& e)
473 {
474 result = NULL;
475 path.pop();
476 set_source(e, loc, false);
477 throw;
478 }
479 catch (...)
480 {
481 result = NULL;
482 path.pop();
483 throw;
484 }
485
486 path.pop();
487
488 STACK_PUSH(true, state);
489 STACK_END(state);
490 }
491
492
resetImpl(PlanState & planState) const493 void ElementIterator::resetImpl(PlanState& planState) const
494 {
495 StateTraitsImpl<PlanIteratorState>::reset(planState, this->theStateOffset);
496
497 if (theQNameIter != 0)
498 theQNameIter->reset(planState);
499
500 if (theChildrenIter != 0)
501 theChildrenIter->reset(planState);
502
503 if (theAttributesIter != 0)
504 theAttributesIter->reset(planState);
505
506 if (theNamespacesIter != 0)
507 theNamespacesIter->reset(planState);
508 }
509
510
closeImpl(PlanState & planState)511 void ElementIterator::closeImpl(PlanState& planState)
512 {
513 if (theQNameIter != 0)
514 theQNameIter->close(planState);
515
516 if (theChildrenIter != 0)
517 theChildrenIter->close(planState);
518
519 if (theAttributesIter != 0)
520 theAttributesIter->close(planState);
521
522 if (theNamespacesIter != 0)
523 theNamespacesIter->close(planState);
524
525 StateTraitsImpl<ElementIteratorState>::destroyState(planState, theStateOffset);
526 }
527
528
529 /*******************************************************************************
530
531 ********************************************************************************/
AttributeIterator(static_context * sctx,const QueryLoc & loc,const store::Item_t & qname,PlanIter_t & qnameIte,PlanIter_t & valueIte,bool isRoot)532 AttributeIterator::AttributeIterator(
533 static_context* sctx,
534 const QueryLoc& loc,
535 const store::Item_t& qname,
536 PlanIter_t& qnameIte,
537 PlanIter_t& valueIte,
538 bool isRoot)
539 :
540 BinaryBaseIterator<AttributeIterator, PlanIteratorState>(sctx, loc, qnameIte, valueIte),
541 theQName(qname),
542 theIsId(false),
543 theIsRoot(isRoot),
544 theRaiseXQDY0074(false),
545 theRaiseXQDY0044(false)
546 {
547 if (theQName)
548 {
549 if (theQName->getLocalName().empty())
550 {
551 theRaiseXQDY0074 = true;
552 }
553
554 if (ZSTREQ(theQName->getNamespace(), "http://www.w3.org/2000/xmlns/") ||
555 (theQName->getNamespace().empty() &&
556 ZSTREQ(theQName->getLocalName(), "xmlns")))
557 {
558 theRaiseXQDY0044 = true;
559 }
560
561 if ((ZSTREQ(theQName->getNamespace(), "http://www.w3.org/XML/1998/namespace") &&
562 !theQName->getPrefix().empty() &&
563 !ZSTREQ(theQName->getPrefix(), "xml")) ||
564 (ZSTREQ(theQName->getPrefix(), "xml") &&
565 !ZSTREQ(theQName->getNamespace(), "http://www.w3.org/XML/1998/namespace")))
566 {
567 theRaiseXQDY0044 = true;
568 }
569
570 if ((ZSTREQ(theQName->getNamespace(), "http://www.w3.org/2000/xmlns/") &&
571 !theQName->getPrefix().empty() &&
572 !ZSTREQ(theQName->getPrefix(), "xmlns")) ||
573 (ZSTREQ(theQName->getPrefix(), "xmlns") &&
574 !ZSTREQ(theQName->getNamespace(), "http://www.w3.org/2000/xmlns/")))
575 {
576 theRaiseXQDY0044 = true;
577 }
578
579 if (ZSTREQ(theQName->getPrefix(), "xml") &&
580 ZSTREQ(theQName->getLocalName(), "id"))
581 theIsId = true;
582 }
583 }
584
585
serialize(::zorba::serialization::Archiver & ar)586 void AttributeIterator::serialize(::zorba::serialization::Archiver& ar)
587 {
588 serialize_baseclass(ar,
589 (BinaryBaseIterator<AttributeIterator, PlanIteratorState>*)this);
590
591 ar & theQName;
592 ar & theIsId;
593 ar & theIsRoot;
594 ar & theRaiseXQDY0074;
595 ar & theRaiseXQDY0044;
596 }
597
598
nextImpl(store::Item_t & result,PlanState & planState) const599 bool AttributeIterator::nextImpl(store::Item_t& result, PlanState& planState) const
600 {
601 store::Item_t qname;
602 store::Item_t typeName = GENV_TYPESYSTEM.XS_UNTYPED_ATOMIC_QNAME;
603 store::Item_t valueItem;
604 zstring lexicalValue;
605 store::Item_t typedValue;
606 store::Item* parent;
607 bool isId = theIsId;
608 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
609
610 PlanIteratorState* state;
611 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
612
613 if (theQName != NULL)
614 {
615 // need to raise those errors here and not in the constructor
616 // because they are dynamic errors and might be caught by try-catch
617 // (bug 955135)
618 if (theRaiseXQDY0074)
619 {
620 RAISE_ERROR(err::XQDY0074, loc, ERROR_PARAMS("", ZED(NoEmptyLocalname)));
621 }
622
623 if (theRaiseXQDY0044)
624 {
625 RAISE_ERROR(err::XQDY0044, loc, ERROR_PARAMS(theQName->getStringValue()));
626 }
627 }
628
629 if (theChild0 != NULL)
630 {
631 // Compute the attribute name. Note: we don't have to check that itemQName
632 // is indeed a valid qname, because the compiler wraps an xs:qname cast
633 // around the name expression.
634 consumeNext(qname, theChild0, planState);
635
636 if (ZSTREQ(qname->getPrefix(), "xml") &&
637 ZSTREQ(qname->getLocalName(), "id"))
638 {
639 isId = true;
640 }
641
642 if (qname->getLocalName().empty())
643 {
644 RAISE_ERROR(err::XQDY0074, loc, ERROR_PARAMS("", ZED(NoEmptyLocalname)));
645 }
646
647 if (ZSTREQ(qname->getNamespace(), "http://www.w3.org/2000/xmlns/") ||
648 (qname->getNamespace().empty() &&
649 ZSTREQ(qname->getLocalName(), "xmlns")))
650 {
651 RAISE_ERROR(err::XQDY0044, loc, ERROR_PARAMS(qname->getStringValue()));
652 }
653 }
654 else
655 {
656 qname = theQName;
657 }
658
659 // Compute lexical value of the attribute.
660 if (consumeNext(valueItem, theChild1, planState))
661 {
662 valueItem->getStringValue2(lexicalValue);
663
664 while (consumeNext(valueItem, theChild1, planState))
665 {
666 valueItem->appendStringValue(lexicalValue);
667 }
668 }
669
670 // normalize value of xml:id
671 if (isId)
672 {
673 ascii::normalize_whitespace(lexicalValue);
674 }
675
676 GENV_ITEMFACTORY->createUntypedAtomic(typedValue, lexicalValue);
677
678 // Create the attribute node
679 ZORBA_FATAL(theIsRoot || !path.empty(), "");
680
681 parent = (theIsRoot ? NULL : path.top());
682
683 GENV_ITEMFACTORY->createAttributeNode(result,
684 parent,
685 qname,
686 typeName,
687 typedValue);
688 STACK_PUSH(true, state);
689 STACK_END(state);
690 }
691
692
693 BINARY_ACCEPT(AttributeIterator);
694
695
696 /*******************************************************************************
697
698 ********************************************************************************/
TextIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & aChild,bool isRoot)699 TextIterator::TextIterator(
700 static_context* sctx,
701 const QueryLoc& loc,
702 PlanIter_t& aChild,
703 bool isRoot)
704 :
705 UnaryBaseIterator<TextIterator, PlanIteratorState>(sctx, loc, aChild),
706 theIsRoot(isRoot)
707 {
708 }
709
710
nextImpl(store::Item_t & result,PlanState & planState) const711 bool TextIterator::nextImpl(store::Item_t& result, PlanState& planState) const
712 {
713 zstring content;
714 bool haveContent = false;
715 store::Item_t valueItem;
716 store::Item_t typedVal;
717 store::Iterator_t typedIter;
718 store::Item* parent;
719 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
720
721 PlanIteratorState* state;
722 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
723
724 // Compute the text content. If the value is the empty sequence, no text
725 // node should be constructed.
726 if (consumeNext(valueItem, theChild, planState))
727 {
728 haveContent = true;
729
730 if (valueItem->isAtomic())
731 {
732 valueItem->getStringValue2(content);
733 }
734 else
735 {
736 valueItem->getTypedValue(typedVal, typedIter);
737
738 if (typedIter == NULL)
739 {
740 typedVal->getStringValue2(content);
741 }
742 else
743 {
744 typedIter->open();
745
746 if (typedIter->next(typedVal))
747 {
748 typedVal->appendStringValue(content);
749
750 while (typedIter->next(typedVal))
751 {
752 content += " ";
753 typedVal->appendStringValue(content);
754 }
755 }
756
757 typedIter->close();
758 }
759 }
760
761 while (consumeNext(valueItem, theChild, planState))
762 {
763 content += " ";
764
765 if (valueItem->isAtomic())
766 {
767 valueItem->appendStringValue(content);
768 }
769 else
770 {
771 valueItem->getTypedValue(typedVal, typedIter);
772
773 if (typedIter == NULL)
774 {
775 typedVal->appendStringValue(content);
776 }
777 else
778 {
779 typedIter->open();
780
781 while (typedIter->next(typedVal))
782 {
783 content += " ";
784 typedVal->appendStringValue(content);
785 }
786
787 typedIter->close();
788 }
789 }
790 }
791 }
792
793 if (haveContent)
794 {
795 ZORBA_FATAL(theIsRoot || !path.empty(), "");
796
797 parent = (theIsRoot ? NULL : path.top());
798
799 STACK_PUSH(GENV_ITEMFACTORY->createTextNode(result, parent, content),
800 state);
801 }
802 else
803 {
804 result = NULL;
805 STACK_PUSH(false, state);
806 }
807
808 STACK_END (state);
809 }
810
811
812 UNARY_ACCEPT(TextIterator);
813
814
815 /*******************************************************************************
816
817 ********************************************************************************/
PiIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & aTarget,PlanIter_t & aContent,bool isRoot)818 PiIterator::PiIterator (
819 static_context* sctx,
820 const QueryLoc& loc,
821 PlanIter_t& aTarget,
822 PlanIter_t& aContent,
823 bool isRoot)
824 :
825 BinaryBaseIterator<PiIterator, PlanIteratorState>(sctx, loc, aTarget, aContent),
826 theIsRoot(isRoot)
827 {
828 }
829
830
nextImpl(store::Item_t & result,PlanState & planState) const831 bool PiIterator::nextImpl(store::Item_t& result, PlanState& planState) const
832 {
833 store::Item_t lItem;
834 store::Item_t temp;
835 zstring content;
836 zstring target;
837 zstring baseUri;
838 bool lFirst;
839
840 store::Item* parent;
841 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
842
843 PlanIteratorState* state;
844 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
845
846 // Compute the target of the pi node.
847 try
848 {
849 if (!consumeNext(lItem, theChild0, planState))
850 {
851 // translator places a cast to xs:NCName op
852 ZORBA_ASSERT(false);
853 }
854 }
855 catch (ZorbaException const& e)
856 {
857 if (e.diagnostic() == err::FORG0001)
858 throw XQUERY_EXCEPTION(err::XQDY0041, ERROR_LOC(loc));
859 else
860 throw;
861 }
862
863 if (consumeNext(temp, theChild0, planState))
864 {
865 // translator places a cast to xs:NCName op
866 ZORBA_ASSERT(false);
867 }
868
869 lItem->getStringValue2(target);
870
871 if (target.empty())
872 {
873 throw XQUERY_EXCEPTION(err::XQDY0041, ERROR_LOC(loc));
874 }
875 else if (target.size() == 3)
876 {
877 zstring upper;
878 utf8::to_upper(target, &upper);
879
880 if (ZSTREQ(upper, "XML"))
881 throw XQUERY_EXCEPTION(err::XQDY0064, ERROR_LOC(loc));
882 }
883
884 // Compute the content of the pi node
885 for (lFirst = true;
886 consumeNext(lItem, theChild1.getp(), planState);
887 lFirst = false)
888 {
889 if (! lFirst)
890 content += " ";
891
892 zstring strvalue;
893 lItem->getStringValue2(strvalue);
894
895 if (strvalue.find("?>", 0, 2) != zstring::npos)
896 throw XQUERY_EXCEPTION(err::XQDY0026, ERROR_LOC(loc));
897
898 content += strvalue;
899 }
900
901 ascii::trim_start(content, " \n\r\t", &content);
902
903 // Create the pi node
904 ZORBA_FATAL(theIsRoot || !path.empty(), "");
905
906 parent = (theIsRoot ? NULL : path.top());
907
908 GENV_ITEMFACTORY->createPiNode(result, parent, target, content, baseUri);
909 STACK_PUSH(true, state);
910
911 STACK_END (state);
912 }
913
914
915 BINARY_ACCEPT(PiIterator);
916
917
918 /********************************************************************************
919
920 ********************************************************************************/
CommentIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & aComment,bool isRoot)921 CommentIterator::CommentIterator(
922 static_context* sctx,
923 const QueryLoc& loc,
924 PlanIter_t& aComment,
925 bool isRoot)
926 :
927 UnaryBaseIterator<CommentIterator, PlanIteratorState>(sctx, loc, aComment),
928 theIsRoot(isRoot)
929 {
930 }
931
932
nextImpl(store::Item_t & result,PlanState & planState) const933 bool CommentIterator::nextImpl(store::Item_t& result, PlanState& planState) const
934 {
935 store::Item_t lItem;
936 zstring content;
937 bool lFirst;
938 store::Item* parent;
939 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
940
941 PlanIteratorState* state;
942 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
943
944 lFirst = true;
945 while (true)
946 {
947 if (!consumeNext(lItem, theChild.getp(), planState))
948 break;
949
950 if (!lFirst)
951 content += " ";
952
953 lItem->appendStringValue(content);
954 lFirst = false;
955 }
956
957 if (!content.empty())
958 {
959 if (content[content.size()-1] == '-' || content.find("--") != zstring::npos)
960 throw XQUERY_EXCEPTION(err::XQDY0072, ERROR_LOC(loc));
961 }
962
963 ZORBA_FATAL(theIsRoot || !path.empty(), "");
964
965 parent = (theIsRoot ? NULL : path.top());
966
967 GENV_ITEMFACTORY->createCommentNode(result, parent, content);
968 STACK_PUSH(true, state);
969
970 STACK_END(state);
971 }
972
973
974 UNARY_ACCEPT(CommentIterator);
975
976
977 /*******************************************************************************
978
979 ********************************************************************************/
init(PlanState & planState)980 void EnclosedIteratorState::init(PlanState& planState)
981 {
982 PlanIteratorState::init(planState);
983 theDocChildren = NULL;
984 }
985
986
reset(PlanState & planState)987 void EnclosedIteratorState::reset(PlanState& planState)
988 {
989 PlanIteratorState::reset(planState);
990
991 theContextItem = NULL;
992
993 if (theDocChildren != NULL)
994 {
995 theDocChildren->close();
996 theDocChildren = 0;
997 }
998 }
999
1000
~EnclosedIteratorState()1001 EnclosedIteratorState::~EnclosedIteratorState()
1002 {
1003 if (theDocChildren != NULL)
1004 {
1005 theDocChildren->close();
1006 theDocChildren = 0;
1007 }
1008 }
1009
1010
EnclosedIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & childIter)1011 EnclosedIterator::EnclosedIterator(
1012 static_context* sctx,
1013 const QueryLoc& loc,
1014 PlanIter_t& childIter)
1015 :
1016 UnaryBaseIterator<EnclosedIterator, EnclosedIteratorState>(sctx, loc, childIter),
1017 theAttrContent(false),
1018 theTextContent(false),
1019 theIsInUpdateExpr(false)
1020 {
1021 }
1022
1023
serialize(::zorba::serialization::Archiver & ar)1024 void EnclosedIterator::serialize(::zorba::serialization::Archiver& ar)
1025 {
1026 serialize_baseclass(ar,
1027 (UnaryBaseIterator<EnclosedIterator, EnclosedIteratorState>*)this);
1028
1029 ar & theAttrContent;
1030 ar & theTextContent;
1031 ar & theIsInUpdateExpr;
1032 }
1033
1034
getAttrContent() const1035 bool EnclosedIterator::getAttrContent() const
1036 {
1037 return theAttrContent;
1038 }
1039
1040
setAttrContent()1041 void EnclosedIterator::setAttrContent()
1042 {
1043 assert(theTextContent == false);
1044 theAttrContent = true;
1045 }
1046
1047
getTextContent() const1048 bool EnclosedIterator::getTextContent() const
1049 {
1050 return theTextContent;
1051 }
1052
1053
setTextContent()1054 void EnclosedIterator::setTextContent()
1055 {
1056 assert(theAttrContent == false);
1057 theTextContent = true;
1058 }
1059
1060
setInUpdateExpr()1061 void EnclosedIterator::setInUpdateExpr()
1062 {
1063 theIsInUpdateExpr = true;
1064 }
1065
1066
nextImpl(store::Item_t & result,PlanState & planState) const1067 bool EnclosedIterator::nextImpl(store::Item_t& result, PlanState& planState) const
1068 {
1069 store::ItemFactory* factory = GENV_ITEMFACTORY;
1070 zstring strval;
1071 std::stack<store::Item*>& path = planState.theNodeConstuctionPath;
1072 bool haveContent = false;
1073 store::Item* parent;
1074
1075 EnclosedIteratorState* state;
1076 DEFAULT_STACK_INIT(EnclosedIteratorState, state, planState);
1077
1078 if (theAttrContent || theTextContent)
1079 {
1080 if (consumeNext(result, theChild, planState))
1081 {
1082 haveContent = true;
1083
1084 if (result->isNode())
1085 {
1086 store::Item_t typedValue;
1087 store::Iterator_t typedIter;
1088 result->getTypedValue(typedValue, typedIter);
1089
1090 if (typedIter == NULL)
1091 {
1092 typedValue->getStringValue2(strval);
1093 }
1094 else
1095 {
1096 if (typedIter->next(typedValue))
1097 {
1098 typedValue->appendStringValue(strval);
1099 }
1100
1101 while (typedIter->next(typedValue))
1102 {
1103 strval += " ";
1104 typedValue->appendStringValue(strval);
1105 }
1106 }
1107 }
1108 #ifdef ZORBA_WITH_JSON
1109 else if (result->isJSONItem())
1110 {
1111 RAISE_ERROR_NO_PARAMS(jerr::JNTY0011, loc);
1112 }
1113 #endif
1114 else
1115 {
1116 assert(result->isAtomic());
1117
1118 result->getStringValue2(strval);
1119 }
1120
1121 while (consumeNext(result, theChild, planState))
1122 {
1123 strval += " ";
1124
1125 if (result->isNode())
1126 {
1127 store::Item_t typedValue;
1128 store::Iterator_t typedIter;
1129 result->getTypedValue(typedValue, typedIter);
1130
1131 if (typedIter == NULL)
1132 {
1133 typedValue->appendStringValue(strval);
1134 }
1135 else
1136 {
1137 if (typedIter->next(typedValue))
1138 {
1139 typedValue->appendStringValue(strval);
1140 }
1141
1142 while (typedIter->next(typedValue))
1143 {
1144 strval += " ";
1145 typedValue->appendStringValue(strval);
1146 }
1147 }
1148 }
1149 #ifdef ZORBA_WITH_JSON
1150 else if (result->isJSONItem())
1151 {
1152 RAISE_ERROR_NO_PARAMS(jerr::JNTY0011, loc);
1153 }
1154 #endif
1155 else
1156 {
1157 assert(result->isAtomic());
1158
1159 result->appendStringValue(strval);
1160 }
1161 }
1162 }
1163
1164 if (theTextContent && !haveContent)
1165 {
1166 STACK_PUSH(false, state);
1167 }
1168 else
1169 {
1170 factory->createString(result, strval);
1171 STACK_PUSH(true, state);
1172 }
1173 }
1174 else
1175 {
1176 while ( true )
1177 {
1178 if (state->theDocChildren != 0)
1179 {
1180 if (!state->theDocChildren->next(result))
1181 {
1182 state->theDocChildren->close();
1183 state->theDocChildren = 0;
1184 }
1185 else
1186 {
1187 STACK_PUSH(true, state);
1188 }
1189 }
1190 else
1191 {
1192 if (!consumeNext(result, theChild, planState))
1193 break;
1194
1195 if (result->isNode())
1196 {
1197 if (result->getNodeKind() == store::StoreConsts::documentNode)
1198 {
1199 state->theDocChildren = result->getChildren();
1200 state->theDocChildren->open();
1201 }
1202 else
1203 {
1204 STACK_PUSH(true, state);
1205 }
1206 }
1207 #ifdef ZORBA_WITH_JSON
1208 else if (result->isJSONItem())
1209 {
1210 RAISE_ERROR_NO_PARAMS(jerr::JNTY0011, loc);
1211 }
1212 #endif
1213 else
1214 {
1215 assert(result->isAtomic());
1216
1217 result->getStringValue2(strval);
1218
1219 {
1220 while(true)
1221 {
1222 bool status = consumeNext(state->theContextItem, theChild, planState);
1223 if (!status)
1224 {
1225 state->theContextItem = NULL;
1226 break;
1227 }
1228
1229 if (!state->theContextItem->isAtomic())
1230 break;
1231
1232 strval += " ";
1233 state->theContextItem->appendStringValue(strval);
1234 }
1235 }
1236
1237 if (!strval.empty())
1238 {
1239 parent = NULL;
1240 if (!theIsInUpdateExpr && !path.empty())
1241 parent = path.top();
1242
1243 STACK_PUSH(factory->createTextNode(result, parent, strval),
1244 state);
1245 }
1246
1247 if (state->theContextItem != NULL &&
1248 state->theContextItem->getNodeKind() == store::StoreConsts::documentNode)
1249 {
1250 state->theDocChildren = state->theContextItem->getChildren();
1251 state->theDocChildren->open();
1252 }
1253 else
1254 {
1255 result.transfer(state->theContextItem);
1256 STACK_PUSH(result != NULL, state);
1257 }
1258 }
1259 }
1260 }
1261 }
1262
1263 STACK_END(state);
1264 }
1265
1266
1267 UNARY_ACCEPT(EnclosedIterator);
1268
1269
1270 /*******************************************************************************
1271
1272 ********************************************************************************/
NameCastIterator(static_context * sctx,const QueryLoc & loc,PlanIter_t & aChild,const namespace_context * aNCtx,bool isAttrName)1273 NameCastIterator::NameCastIterator(
1274 static_context* sctx,
1275 const QueryLoc& loc,
1276 PlanIter_t& aChild,
1277 const namespace_context* aNCtx,
1278 bool isAttrName)
1279 :
1280 UnaryBaseIterator<NameCastIterator, PlanIteratorState>(sctx, loc, aChild),
1281 theNCtx(const_cast<namespace_context*>(aNCtx)),
1282 theIsAttrName(isAttrName)
1283 {
1284 }
1285
1286
~NameCastIterator()1287 NameCastIterator::~NameCastIterator()
1288 {
1289 }
1290
1291
nextImpl(store::Item_t & result,PlanState & planState) const1292 bool NameCastIterator::nextImpl(store::Item_t& result, PlanState& planState) const
1293 {
1294 xqtref_t lItemType;
1295 store::Item_t temp;
1296 bool valid = false;
1297
1298 PlanIteratorState* state;
1299 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1300
1301 if (!consumeNext(result, theChild.getp(), planState))
1302 {
1303 RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(EmptySeqNoCastToQName)));
1304 }
1305 valid = true;
1306
1307 if (consumeNext(temp, theChild, planState))
1308 {
1309 RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(SeqNoCastToQName)));
1310 }
1311
1312 try
1313 {
1314 temp = result;
1315 valid = GenericCast::instance()->castToQName(result,
1316 temp,
1317 &*theNCtx,
1318 theIsAttrName,
1319 theSctx->get_typemanager(),
1320 loc);
1321 }
1322 catch (ZorbaException const& e)
1323 {
1324 if (e.diagnostic() != err::XPTY0004)
1325 {
1326 zstring name = result->getStringValue();
1327 if (name.find(":") != zstring::npos && name.substr(0, name.find(":")) == "xmlns")
1328 {
1329 // this needs to be checked and thrown here as the optimizer
1330 // might try to fold a const expression and would return a different error code
1331 if (theIsAttrName)
1332 RAISE_ERROR(err::XQDY0044, loc, ERROR_PARAMS(name));
1333 else
1334 RAISE_ERROR(err::XQDY0096, loc, ERROR_PARAMS(name));
1335 }
1336 else
1337 // the returned error codes are wrong for name casting => they must be changed
1338 RAISE_ERROR(err::XQDY0074, loc, ERROR_PARAMS("item"));
1339 }
1340 else
1341 {
1342 throw;
1343 }
1344 }
1345
1346 STACK_PUSH(valid, state);
1347 STACK_END(state);
1348 }
1349
1350
1351 UNARY_ACCEPT(NameCastIterator);
1352
1353
1354 } // namespace zorba
1355 /* vim:set et sw=2 ts=2: */
1356