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