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 #include <zorba/config.h>
18
19 #ifdef ZORBA_WITH_JSON
20
21
22 #include <sstream>
23
24 #include "system/globalenv.h"
25
26 #include "api/serialization/serializer.h"
27
28 #include "compiler/api/compilercb.h"
29
30 #include "runtime/json/jsoniq_functions.h"
31 #include "runtime/parsing_and_serializing/parsing_and_serializing.h"
32 #include "runtime/visitors/planiter_visitor.h"
33 #include "runtime/api/plan_iterator_wrapper.h"
34 #include "runtime/util/item_iterator.h"
35
36 #include "diagnostics/diagnostic.h"
37 #include "diagnostics/xquery_diagnostics.h"
38 #include "diagnostics/util_macros.h"
39
40 #include "zorba/internal/diagnostic.h"
41
42 #include "context/static_context.h"
43
44 #include "types/casting.h"
45 #include "types/typeimpl.h"
46 #include "types/typeops.h"
47 #include "types/root_typemanager.h"
48
49 #include "store/api/pul.h"
50 #include "store/api/item.h"
51 #include "store/api/item_factory.h"
52 #include "store/api/store.h"
53 #include "store/api/copymode.h"
54
55 #include <zorba/store_consts.h>
56
57 namespace zorba {
58
59 const zstring XS_URI("http://www.w3.org/2001/XMLSchema");
60
61 const zstring ENCODE_DECODE_DEFAULT_PREFIX("Q{http://jsoniq.org/roundtrip}");
62
63 const zstring NS_PREFIX_KEY("prefix");
64 const zstring TYPE_KEY("type");
65 const zstring VALUE_KEY("value");
66
67 const char * OPTIONS_KEY_PREFIX = "prefix";
68 const char * OPTIONS_KEY_SER_PARAMS = "serialization-parameters";
69
70 const char * SEQTYPE_ANYNODE = "node()";
71 const char * SEQTYPE_COMMENT = "comment()";
72 const char * SEQTYPE_DOCUMENT = "document-node()";
73 const char * SEQTYPE_ELEMENT = "element()";
74 const char * SEQTYPE_PROCINST = "processing-instruction()";
75 const char * SEQTYPE_TEXT = "text()";
76
kind2str(const store::NodeKind & aKind)77 const char * kind2str(const store::NodeKind& aKind)
78 {
79 // we do not support attibutes and namespaces as they cannot be serialized
80 switch (aKind)
81 {
82 case store::StoreConsts::anyNode: return SEQTYPE_ANYNODE;
83 case store::StoreConsts::commentNode: return SEQTYPE_COMMENT;
84 case store::StoreConsts::documentNode: return SEQTYPE_DOCUMENT;
85 case store::StoreConsts::elementNode: return SEQTYPE_ELEMENT;
86 case store::StoreConsts::piNode: return SEQTYPE_PROCINST;
87 case store::StoreConsts::textNode: return SEQTYPE_TEXT;
88 default: return "";
89 }
90 }
91
str2kind(const zstring & aString,store::NodeKind & aKind)92 bool str2kind(const zstring& aString, store::NodeKind& aKind)
93 {
94 switch(aString.at(0))
95 {
96 case 'c':
97 if (aString == SEQTYPE_COMMENT)
98 {
99 aKind = store::StoreConsts::commentNode;
100 return true;
101 }
102 break;
103 case 'd':
104 if (aString == SEQTYPE_DOCUMENT)
105 {
106 aKind = store::StoreConsts::documentNode;
107 return true;
108 }
109 break;
110 case 'e':
111 case 'n': // "node()" maps to element for backwards compatibility
112 if (aString == SEQTYPE_ELEMENT || aString == SEQTYPE_ANYNODE)
113 {
114 aKind = store::StoreConsts::elementNode;
115 return true;
116 }
117 break;
118 case 'p':
119 if (aString == SEQTYPE_PROCINST)
120 {
121 aKind = store::StoreConsts::piNode;
122 return true;
123 }
124 break;
125 case 't':
126 if (aString == SEQTYPE_TEXT)
127 {
128 aKind = store::StoreConsts::textNode;
129 return true;
130 }
131 break;
132 }
133 return false;
134 }
135
136 /*******************************************************************************
137 json:decode-from-roundtrip($items as json-item()*,
138 $options as object()) as structured-item()*
139 ********************************************************************************/
140
141 void
parseQName(store::Item_t & aResult,const zstring & aQNameString,const zstring & aPrefix,store::ItemFactory * aFactory)142 parseQName(store::Item_t& aResult,
143 const zstring& aQNameString,
144 const zstring& aPrefix,
145 store::ItemFactory* aFactory)
146 {
147 // TODO there probably is a better solution somewhere
148 if (aQNameString.substr(0, 3) == "xs:")
149 {
150 aFactory->createQName(aResult, XS_URI, "xs", aQNameString.substr(3));
151 }
152 else if (aQNameString.substr(0, 2) == "Q{")
153 {
154 zstring::size_type lPos = aQNameString.find('}');
155 aFactory->createQName(aResult,
156 aQNameString.substr(2, lPos - 2),
157 aPrefix,
158 aQNameString.substr(lPos + 1));
159 }
160 else
161 {
162 aFactory->createQName(aResult, "", "", aQNameString);
163 }
164 }
165
166 void
extractChildOfKind(const store::Item_t & aParent,const store::NodeKind & aKind,store::Item_t & aChild)167 JSONDecodeFromRoundtripIterator::extractChildOfKind(
168 const store::Item_t& aParent,
169 const store::NodeKind& aKind,
170 store::Item_t& aChild)
171 {
172 store::Iterator_t lIt = aParent->getChildren();
173 bool lFound = false;
174 lIt->open();
175 while (! lFound && lIt->next(aChild))
176 {
177 lFound = aChild->getNodeKind() == aKind;
178 }
179 lIt->close();
180 ZORBA_ASSERT(lFound);
181 }
182
183 bool
decodeNode(const store::Item_t & aSerializedNode,const store::NodeKind & aKind,store::Item_t & aResult) const184 JSONDecodeFromRoundtripIterator::decodeNode(
185 const store::Item_t& aSerializedNode,
186 const store::NodeKind& aKind,
187 store::Item_t& aResult) const
188 {
189 store::LoadProperties lProperties;
190 lProperties.setStoreDocument(false);
191 store::Item_t lDoc;
192 zstring lXmlString;
193 switch (aKind)
194 {
195 case store::StoreConsts::commentNode:
196 case store::StoreConsts::piNode:
197 case store::StoreConsts::textNode:
198 {
199 // we have to wrap these 3 node kinds, so we cannot care about streams
200 aSerializedNode->getStringValue2(lXmlString);
201 lXmlString = "<a>" + lXmlString + "</a>";
202 std::istringstream lStream(lXmlString.c_str());
203 lDoc = GENV.getStore().loadDocument("", "", lStream, lProperties);
204 }
205 break;
206 default:
207 if (aSerializedNode->isStreamable())
208 {
209 lDoc = GENV.getStore().loadDocument(
210 "", "", aSerializedNode->getStream(), lProperties);
211 }
212 else
213 {
214 aSerializedNode->getStringValue2(lXmlString);
215 std::istringstream lStream(lXmlString.c_str());
216 lDoc = GENV.getStore().loadDocument("", "", lStream, lProperties);
217 }
218 break;
219 }
220 if (aKind == store::StoreConsts::documentNode)
221 {
222 aResult = lDoc;
223 }
224 else
225 {
226 store::Item_t lRootElem;
227 extractChildOfKind(lDoc, store::StoreConsts::elementNode, lRootElem);
228 if (aKind == store::StoreConsts::elementNode)
229 {
230 // if we needed an element we're done
231 aResult = lRootElem;
232 }
233 else
234 {
235 // otherwise we have to pass through the wrapper that we've created
236 extractChildOfKind(lRootElem, aKind, aResult);
237 }
238 }
239 return true;
240 }
241
242 bool
decodeXDM(const store::Item_t & anObj,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const243 JSONDecodeFromRoundtripIterator::decodeXDM(
244 const store::Item_t& anObj,
245 store::Item_t& aResult,
246 JSONDecodeFromRoundtripIteratorState* aState) const
247 {
248 store::Item_t lItem;
249
250 zstring lTypeKey = aState->thePrefix + TYPE_KEY;
251 GENV_ITEMFACTORY->createString(lItem, lTypeKey);
252 store::Item_t lTypeValueItem = anObj->getObjectValue(lItem);
253 if (lTypeValueItem.isNull())
254 {
255 // nothing to change, aResult is not set, the caller needs to use anObj
256 return false;
257 }
258
259 zstring lValueKey = aState->thePrefix + VALUE_KEY;
260 GENV_ITEMFACTORY->createString(lItem, lValueKey);
261 store::Item_t lValueValueItem = anObj->getObjectValue(lItem);
262 if (lValueValueItem.isNull())
263 {
264 // nothing to change, aResult is not set, the caller needs to use anObj
265 return false;
266 }
267
268 zstring lTypeNameString;
269 lTypeValueItem->getStringValue2(lTypeNameString);
270 store::NodeKind lNodeKind;
271 if (str2kind(lTypeNameString, lNodeKind))
272 {
273 return decodeNode(lValueValueItem, lNodeKind, aResult);
274 }
275 else
276 {
277 store::Item_t lTypeQName;
278 parseQName(lTypeQName, lTypeNameString, "", GENV_ITEMFACTORY);
279 if (lTypeQName->getLocalName() == "QName"
280 && lTypeQName->getNamespace() == XS_URI)
281 {
282 zstring lPrefixKey = aState->thePrefix + NS_PREFIX_KEY;
283 GENV_ITEMFACTORY->createString(lItem, lPrefixKey);
284 store::Item_t lPrefixValue = anObj->getObjectValue(lItem);
285 zstring lPrefixString;
286 if (! lPrefixValue.isNull())
287 {
288 lPrefixValue->getStringValue2(lPrefixString);
289 }
290 zstring lValueValue;
291 lValueValueItem->getStringValue2(lValueValue);
292 parseQName(aResult, lValueValue, lPrefixString, GENV_ITEMFACTORY);
293 }
294 else
295 {
296 TypeManager* lTypeMgr = theSctx->get_typemanager();
297 xqtref_t lTargetType = lTypeMgr->create_named_type(
298 lTypeQName.getp(), TypeConstants::QUANT_ONE, loc);
299 namespace_context lTmpNsCtx(theSctx);
300 GenericCast::castToAtomic(aResult,
301 lValueValueItem,
302 lTargetType.getp(),
303 lTypeMgr,
304 &lTmpNsCtx,
305 loc);
306 }
307 return true;
308 }
309 }
310
311 bool
decodeObject(const store::Item_t & anObj,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const312 JSONDecodeFromRoundtripIterator::decodeObject(
313 const store::Item_t& anObj,
314 store::Item_t& aResult,
315 JSONDecodeFromRoundtripIteratorState* aState) const
316 {
317 if (decodeXDM(anObj, aResult, aState))
318 {
319 return true;
320 }
321
322 std::vector<store::Item_t> newNames;
323 std::vector<store::Item_t> newValues;
324 bool modified = false;
325
326 store::Item_t key;
327 store::Item_t value;
328 store::Item_t newValue;
329 store::Iterator_t it = anObj->getObjectKeys();
330 it->open();
331 while (it->next(key))
332 {
333 newNames.push_back(key);
334 value = anObj->getObjectValue(key);
335 const bool gotNew = decodeItem(value, newValue, aState);
336 newValues.push_back(gotNew ? newValue : value);
337 modified = modified || gotNew;
338 }
339 it->close();
340 if (modified)
341 {
342 GENV_ITEMFACTORY->createJSONObject(aResult, newNames, newValues);
343 return true;
344 }
345 // nothing to change, aResult is not set, the caller needs to use anObj
346 return false;
347 }
348
349 bool
decodeArray(const store::Item_t & anArray,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const350 JSONDecodeFromRoundtripIterator::decodeArray(
351 const store::Item_t& anArray,
352 store::Item_t& aResult,
353 JSONDecodeFromRoundtripIteratorState* aState) const
354 {
355 std::vector<store::Item_t> newItems;
356 bool modified = false;
357
358 store::Item_t item, newItem;
359 store::Iterator_t it = anArray->getArrayValues();
360 it->open();
361 while (it->next(item))
362 {
363 const bool gotNew = decodeItem(item, newItem, aState);
364 newItems.push_back(gotNew ? newItem : item);
365 modified = modified || gotNew;
366 }
367 it->close();
368 if (modified)
369 {
370 GENV_ITEMFACTORY->createJSONArray(aResult, newItems);
371 return true;
372 }
373 // nothing to change, aResult is not set, the caller needs to use anArray
374 return false;
375 }
376
377 bool
decodeItem(const store::Item_t & anItem,store::Item_t & aResult,JSONDecodeFromRoundtripIteratorState * aState) const378 JSONDecodeFromRoundtripIterator::decodeItem(
379 const store::Item_t& anItem,
380 store::Item_t& aResult,
381 JSONDecodeFromRoundtripIteratorState* aState) const
382 {
383 if (anItem->isJSONObject())
384 {
385 return decodeObject(anItem, aResult, aState);
386 }
387 else if (anItem->isJSONArray())
388 {
389 return decodeArray(anItem, aResult, aState);
390 }
391 else
392 {
393 // nothing to change, aResult is not set, the caller needs to use anItem
394 return false;
395 }
396 }
397
398 bool
nextImpl(store::Item_t & aResult,PlanState & aPlanState) const399 JSONDecodeFromRoundtripIterator::nextImpl(
400 store::Item_t& aResult,
401 PlanState& aPlanState) const
402 {
403 store::Item_t lInput;
404 store::Item_t lDecParams;
405
406 JSONDecodeFromRoundtripIteratorState* lState;
407 DEFAULT_STACK_INIT(JSONDecodeFromRoundtripIteratorState, lState, aPlanState);
408
409 // get decoding parameters
410 if (theChildren.size() == 2)
411 {
412 // the signature says that the second parameter has to be exactly one object
413 consumeNext(lDecParams, theChildren.at(1), aPlanState);
414 store::Item_t lPrefixKey;
415 zstring lPrefixNameStr = OPTIONS_KEY_PREFIX;
416 GENV_ITEMFACTORY->createString(lPrefixKey, lPrefixNameStr);
417 store::Item_t lPrefixValue = lDecParams->getObjectValue(lPrefixKey);
418 if (! lPrefixValue.isNull())
419 {
420 if (lPrefixValue->getTypeCode() != store::XS_STRING)
421 {
422 RAISE_ERROR(jerr::JNTY0023, loc,
423 ERROR_PARAMS(lPrefixValue->getStringValue(),
424 OPTIONS_KEY_PREFIX,
425 "string"));
426 }
427 lPrefixValue->getStringValue2(lState->thePrefix);
428 }
429 }
430 else
431 {
432 lState->thePrefix = ENCODE_DECODE_DEFAULT_PREFIX;
433 }
434
435 while (consumeNext(lInput, theChildren.at(0), aPlanState))
436 {
437 if (! decodeItem(lInput, aResult, lState))
438 {
439 aResult = lInput;
440 }
441 STACK_PUSH (true, lState);
442 }
443
444 STACK_END(lState);
445 }
446
447
448 /*******************************************************************************
449 jn:encode-for-roundtrip($items as structured-item()*,
450 $options as object()) as json-item()*
451 ********************************************************************************/
452 bool
encodeObject(const store::Item_t & anObj,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const453 JSONEncodeForRoundtripIterator::encodeObject(
454 const store::Item_t& anObj,
455 store::Item_t& aResult,
456 JSONEncodeForRoundtripIteratorState* aState) const
457 {
458 std::vector<store::Item_t> newNames;
459 std::vector<store::Item_t> newValues;
460 bool modified = false;
461
462 store::Item_t key;
463 store::Item_t value;
464 store::Item_t newValue;
465 store::Iterator_t it = anObj->getObjectKeys();
466 it->open();
467 while (it->next(key))
468 {
469 newNames.push_back(key);
470 value = anObj->getObjectValue(key);
471 const bool gotNew = encodeItem(value, newValue, aState);
472 newValues.push_back(gotNew ? newValue : value);
473 modified = modified || gotNew;
474 }
475 it->close();
476 if (modified)
477 {
478 GENV_ITEMFACTORY->createJSONObject(aResult, newNames, newValues);
479 return true;
480 }
481 // nothing to change, aResult is not set, the caller needs to use anObj
482 return false;
483 }
484
485 bool
encodeArray(const store::Item_t & anArray,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const486 JSONEncodeForRoundtripIterator::encodeArray(
487 const store::Item_t& anArray,
488 store::Item_t& aResult,
489 JSONEncodeForRoundtripIteratorState* aState) const
490 {
491 std::vector<store::Item_t> newItems;
492 bool modified = false;
493
494 store::Item_t item, newItem;
495 store::Iterator_t it = anArray->getArrayValues();
496 it->open();
497 while (it->next(item))
498 {
499 const bool gotNew = encodeItem(item, newItem, aState);
500 newItems.push_back(gotNew ? newItem : item);
501 modified = modified || gotNew;
502 }
503 it->close();
504 if (modified)
505 {
506 GENV_ITEMFACTORY->createJSONArray(aResult, newItems);
507 return true;
508 }
509 // nothing to change, aResult is not set, the caller needs to use anArray
510 return false;
511 }
512
513 bool
encodeAtomic(const store::Item_t & aValue,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const514 JSONEncodeForRoundtripIterator::encodeAtomic(
515 const store::Item_t& aValue,
516 store::Item_t& aResult,
517 JSONEncodeForRoundtripIteratorState* aState) const
518 {
519 store::SchemaTypeCode typeCode = aValue->getTypeCode();
520 switch (typeCode) {
521 case store::XS_DOUBLE:
522 case store::XS_FLOAT:
523 if (aValue->getBaseItem() == NULL
524 && ! aValue->isNaN() && ! aValue->isPosOrNegInf())
525 {
526 // nothing to change, aResult is not set, the caller needs to use aValue
527 return false;
528 }
529 break;
530 case store::XS_STRING:
531 case store::XS_INTEGER:
532 case store::XS_DECIMAL:
533 case store::XS_BOOLEAN:
534 case store::JS_NULL:
535 if (aValue->getBaseItem() == NULL)
536 {
537 // nothing to change, aResult is not set, the caller needs to use aValue
538 return false;
539 }
540 break;
541 default:
542 break;
543 }
544
545 std::vector<store::Item_t> names(2);
546 std::vector<store::Item_t> values(2);
547
548 {
549 const store::Item_t& typeName = aValue->getType();
550
551 zstring typeKey = aState->thePrefix + TYPE_KEY;
552 const zstring ns = typeName->getNamespace();
553 const zstring local = typeName->getLocalName();
554 zstring typeValue = ns.compare(XS_URI)
555 ? "Q{" + ns + "}" + local : "xs:" + local;
556
557 GENV_ITEMFACTORY->createString(names.at(0), typeKey);
558 GENV_ITEMFACTORY->createString(values.at(0), typeValue);
559 }
560
561 {
562 zstring valueKey = aState->thePrefix + VALUE_KEY;
563 zstring valueValue;
564 if (typeCode == store::XS_QNAME)
565 {
566 // QNames are a special case, as the prefix should be maintained as well
567 // but it's not part of the EQName serialization
568 zstring prefixValue = aValue->getPrefix();
569 if (prefixValue.length() > 0)
570 {
571 zstring prefixKey = aState->thePrefix + NS_PREFIX_KEY;
572 store::Item_t lItem;
573 GENV_ITEMFACTORY->createString(lItem, prefixKey);
574 names.push_back(lItem);
575 GENV_ITEMFACTORY->createString(lItem, prefixValue);
576 values.push_back(lItem);
577 }
578
579 const zstring ns = aValue->getNamespace();
580 const zstring local = aValue->getLocalName();
581 valueValue = ns.empty() ? local : "Q{" + ns + "}" + local;
582 }
583 else
584 {
585 aValue->getStringValue2(valueValue);
586 }
587 GENV_ITEMFACTORY->createString(names.at(1), valueKey);
588 GENV_ITEMFACTORY->createString(values.at(1), valueValue);
589 }
590
591 GENV_ITEMFACTORY->createJSONObject(aResult, names, values);
592 return true;
593 }
594
595 bool
encodeNode(const store::Item_t & aNode,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const596 JSONEncodeForRoundtripIterator::encodeNode(
597 const store::Item_t& aNode,
598 store::Item_t& aResult,
599 JSONEncodeForRoundtripIteratorState* aState) const
600 {
601 std::vector<store::Item_t> names(2);
602 std::vector<store::Item_t> values(2);
603
604 {
605 zstring typeKey = aState->thePrefix + TYPE_KEY;
606 zstring typeValue = kind2str(aNode->getNodeKind());
607 GENV_ITEMFACTORY->createString(names.at(0), typeKey);
608 GENV_ITEMFACTORY->createString(values.at(0), typeValue);
609 }
610
611 {
612 zstring valueKey = aState->thePrefix + VALUE_KEY;
613
614 store::Iterator_t lItemIt = new ItemIterator(aNode);
615 zorba::serializer lSerializer(aState->theDiag);
616 // TODO what do we set, if nothing is passed?
617 lSerializer.setParameter("omit-xml-declaration", "yes");
618
619 if (! aState->theSerParams.isNull())
620 {
621 FnSerializeIterator::setSerializationParams(
622 lSerializer,
623 aState->theSerParams,
624 theSctx,
625 loc);
626 }
627
628 // and now serialize
629 std::auto_ptr<std::stringstream> lResultStream(new std::stringstream());
630 lItemIt->open();
631 lSerializer.serialize(lItemIt, *lResultStream.get());
632 lItemIt->close();
633
634 GENV_ITEMFACTORY->createString(names.at(1), valueKey);
635 GENV_ITEMFACTORY->createStreamableString(
636 values.at(1), *lResultStream.release(),
637 FnSerializeIterator::streamReleaser, true);
638 }
639
640 GENV_ITEMFACTORY->createJSONObject(aResult, names, values);
641 return true;
642 }
643
644 bool
encodeItem(const store::Item_t & anItem,store::Item_t & aResult,JSONEncodeForRoundtripIteratorState * aState) const645 JSONEncodeForRoundtripIterator::encodeItem(
646 const store::Item_t& anItem,
647 store::Item_t& aResult,
648 JSONEncodeForRoundtripIteratorState* aState) const
649 {
650 if (anItem->isJSONObject())
651 {
652 return encodeObject(anItem, aResult, aState);
653 }
654 else if (anItem->isJSONArray())
655 {
656 return encodeArray(anItem, aResult, aState);
657 }
658 else if (anItem->isAtomic())
659 {
660 return encodeAtomic(anItem, aResult, aState);
661 }
662 else
663 {
664 return encodeNode(anItem, aResult, aState);
665 }
666 }
667
668 bool
nextImpl(store::Item_t & aResult,PlanState & aPlanState) const669 JSONEncodeForRoundtripIterator::nextImpl(
670 store::Item_t& aResult,
671 PlanState& aPlanState) const
672 {
673 store::Item_t lInput;
674
675 JSONEncodeForRoundtripIteratorState* lState;
676 DEFAULT_STACK_INIT(JSONEncodeForRoundtripIteratorState, lState, aPlanState);
677
678 lState->thePrefix = ENCODE_DECODE_DEFAULT_PREFIX;
679 lState->theDiag = aPlanState.theCompilerCB->theXQueryDiagnostics;
680
681 // get encoding parameters
682 if (theChildren.size() == 2)
683 {
684 // the signature says that the second parameter has to be exactly one object
685 store::Item_t lEncParams;
686 consumeNext(lEncParams, theChildren.at(1), aPlanState);
687 store::Item_t lPrefixKey;
688 zstring lPrefixNameStr = OPTIONS_KEY_PREFIX;
689 GENV_ITEMFACTORY->createString(lPrefixKey, lPrefixNameStr);
690 store::Item_t lPrefixValue = lEncParams->getObjectValue(lPrefixKey);
691 if (! lPrefixValue.isNull())
692 {
693 if (lPrefixValue->getTypeCode() != store::XS_STRING)
694 {
695 RAISE_ERROR(jerr::JNTY0023, loc,
696 ERROR_PARAMS(lPrefixValue->getStringValue(),
697 OPTIONS_KEY_PREFIX,
698 "string"));
699 }
700 lPrefixValue->getStringValue2(lState->thePrefix);
701 }
702
703 store::Item_t lSerParamKey;
704 zstring lSerParamNameStr = OPTIONS_KEY_SER_PARAMS;
705 GENV_ITEMFACTORY->createString(lSerParamKey, lSerParamNameStr);
706 store::Item_t lSerParamValue = lEncParams->getObjectValue(lSerParamKey);
707 if (! lSerParamValue.isNull())
708 {
709 if (! lSerParamValue->isNode()
710 || lSerParamValue->getNodeKind() != store::StoreConsts::elementNode)
711 {
712 RAISE_ERROR(jerr::JNTY0023, loc,
713 ERROR_PARAMS(lSerParamValue->getStringValue(),
714 OPTIONS_KEY_SER_PARAMS,
715 ZED(ElementNode)));
716 }
717 lState->theSerParams = lSerParamValue;
718 }
719 }
720
721 while(consumeNext(lInput, theChildren.at(0), aPlanState))
722 {
723 if (! encodeItem(lInput, aResult, lState))
724 {
725 aResult = lInput;
726 }
727 STACK_PUSH (true, lState);
728 }
729 STACK_END(lState);
730 }
731
732
733 /*******************************************************************************
734
735 ********************************************************************************/
736 void
init(PlanState & aState)737 JSONParseIteratorState::init(PlanState& aState)
738 {
739 PlanIteratorState::init(aState);
740 theAllowMultiple = true; // default
741 theInputStream = 0;
742 theGotOne = false;
743 }
744
745 void
reset(PlanState & aState)746 JSONParseIteratorState::reset(PlanState& aState)
747 {
748 PlanIteratorState::reset(aState);
749 if (theInput == NULL && theInputStream)
750 {
751 delete theInputStream;
752 }
753 }
754
~JSONParseIteratorState()755 JSONParseIteratorState::~JSONParseIteratorState()
756 {
757 if (theInput == NULL && theInputStream)
758 {
759 delete theInputStream;
760 }
761 }
762
763 void
processOptions(const store::Item_t & aOptions,bool & aAllowMultiple) const764 JSONParseIterator::processOptions(
765 const store::Item_t& aOptions,
766 bool& aAllowMultiple) const
767 {
768 store::Item_t lOptionName, lOptionValue;
769
770 zstring s("jsoniq-multiple-top-level-items");
771 GENV_ITEMFACTORY->createString(lOptionName, s);
772 lOptionValue = aOptions->getObjectValue(lOptionName);
773
774 if (lOptionValue != NULL)
775 {
776 store::SchemaTypeCode lType = lOptionValue->getTypeCode();
777 if (!TypeOps::is_subtype(lType, store::XS_BOOLEAN))
778 {
779 const TypeManager* tm = theSctx->get_typemanager();
780 xqtref_t lType = tm->create_value_type(lOptionValue, loc);
781 RAISE_ERROR(jerr::JNTY0020, loc,
782 ERROR_PARAMS(lType->toSchemaString(), s, "xs:boolean"));
783 }
784 aAllowMultiple = lOptionValue->getBooleanValue();
785 }
786 }
787
788 bool
nextImpl(store::Item_t & result,PlanState & planState) const789 JSONParseIterator::nextImpl(
790 store::Item_t& result,
791 PlanState& planState) const
792 {
793 store::Item_t lInput;
794
795 JSONParseIteratorState* state;
796 DEFAULT_STACK_INIT(JSONParseIteratorState, state, planState);
797
798 if (consumeNext(lInput, theChildren[0].getp(), planState))
799 {
800 if (theChildren.size() == 2)
801 {
802 store::Item_t lOptions;
803 consumeNext(lOptions, theChildren[1].getp(), planState);
804 processOptions(lOptions, state->theAllowMultiple);
805 }
806
807 if (lInput->isStreamable())
808 {
809 state->theInput = lInput;
810 state->theInputStream = &lInput->getStream();
811 }
812 else
813 {
814 // will be deleted in the state
815 state->theInputStream = new std::stringstream(
816 lInput->getStringValue().c_str());
817 }
818
819 while (true)
820 {
821 try
822 {
823 // streamable string or non-literal string
824 if (state->theInput != NULL || theRelativeLocation == QueryLoc::null)
825 {
826 result = GENV_STORE.parseJSON(*state->theInputStream, 0);
827 }
828 else
829 {
830 // pass the query location of the StringLiteral to the JSON
831 // parser such that it can give better error locations.
832 zorba::internal::diagnostic::location lLoc;
833 lLoc = ERROR_LOC(theRelativeLocation);
834 result = GENV_STORE.parseJSON(*state->theInputStream, &lLoc);
835 }
836 }
837 catch (zorba::XQueryException& e)
838 {
839 // rethrow with JNDY0021
840 XQueryException xq = XQUERY_EXCEPTION(
841 jerr::JNDY0021,
842 ERROR_PARAMS(e.what()),
843 ERROR_LOC(loc));
844
845 // use location of e in case of literal string
846 if (!(theRelativeLocation == QueryLoc::null)) set_source(xq, e);
847 throw xq;
848 }
849
850 if (result != NULL)
851 {
852 if (!state->theAllowMultiple && state->theGotOne)
853 {
854 RAISE_ERROR(jerr::JNDY0021, loc,
855 ERROR_PARAMS(ZED(JSON_UNEXPECTED_EXTRA_CONTENT)));
856 }
857 state->theGotOne = true;
858 STACK_PUSH(true, state);
859 continue;
860 }
861 else
862 {
863 break;
864 }
865 }
866 }
867
868 STACK_END(state);
869 }
870
871
872 /*******************************************************************************
873 json:names($o as object()) as xs:string*
874 ********************************************************************************/
875 bool
nextImpl(store::Item_t & result,PlanState & planState) const876 JSONObjectNamesIterator::nextImpl(
877 store::Item_t& result,
878 PlanState& planState) const
879 {
880 store::Item_t input;
881 store::Item_t key;
882
883 JSONObjectNamesIteratorState* state;
884 DEFAULT_STACK_INIT(JSONObjectNamesIteratorState, state, planState);
885
886 consumeNext(input, theChild.getp(), planState);
887
888 state->theNames = input->getObjectKeys();
889 state->theNames->open();
890
891 while (state->theNames->next(key))
892 {
893 result = key;
894 STACK_PUSH (true, state);
895 }
896 state->theNames = NULL;
897
898 STACK_END(state);
899 }
900
901
902 /*******************************************************************************
903 json:value($o as object(), $name as xs:string) as item()?
904 ********************************************************************************/
905 bool
nextImpl(store::Item_t & result,PlanState & planState) const906 JSONObjectValueIterator::nextImpl(
907 store::Item_t& result,
908 PlanState& planState) const
909 {
910 store::Item_t lInput;
911 store::Item_t lName;
912
913 PlanIteratorState* state;
914 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
915
916 consumeNext(lInput, theChild0.getp(), planState);
917 consumeNext(lName, theChild1.getp(), planState);
918
919 result = lInput->getObjectValue(lName);
920
921 STACK_PUSH(result != 0, state);
922
923 STACK_END(state);
924 }
925
926
927 /*******************************************************************************
928 json:project($o as object(), $names as xs:string*) as object()
929 ********************************************************************************/
930 bool
nextImpl(store::Item_t & result,PlanState & planState) const931 JSONObjectProjectIterator::nextImpl(
932 store::Item_t& result,
933 PlanState& planState) const
934 {
935 store::Item_t obj;
936 store::Item_t key;
937 store::Iterator_t keysIte;
938 store::Item_t value;
939 store::Item_t name;
940 std::vector<store::Item_t> names;
941 csize numNames = 0;
942 store::CopyMode copymode;
943 std::vector<store::Item_t> newNames;
944 std::vector<store::Item_t> newValues;
945 csize i;
946
947 PlanIteratorState* state;
948 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
949
950 consumeNext(obj, theChild0.getp(), planState);
951
952 while (consumeNext(name, theChild1.getp(), planState))
953 {
954 ++numNames;
955 names.resize(numNames);
956 names[numNames - 1].transfer(name);
957 }
958
959 keysIte = obj->getObjectKeys();
960 keysIte->open();
961
962 while (keysIte->next(key))
963 {
964 for (i = 0; i < numNames; ++i)
965 {
966 if (names[i]->getStringValue() == key->getStringValue())
967 break;
968 }
969
970 if (i < numNames)
971 {
972 value = obj->getObjectValue(key);
973
974 if (value->isNode() || value->isJSONItem())
975 value = value->copy(NULL, copymode);
976
977 newValues.push_back(value);
978 newNames.push_back(key);
979 }
980 }
981
982 keysIte->close();
983
984 GENV_ITEMFACTORY->createJSONObject(result, newNames, newValues);
985
986 STACK_PUSH(true, state);
987 STACK_END(state);
988 }
989
990
991 /*******************************************************************************
992 j:size($i as array()) as xs:integer*
993 ********************************************************************************/
994 bool
nextImpl(store::Item_t & result,PlanState & planState) const995 JSONArraySizeIterator::nextImpl(
996 store::Item_t& result,
997 PlanState& planState) const
998 {
999 store::Item_t lJSONItem;
1000 xs_integer lSize;
1001
1002 PlanIteratorState* state;
1003 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1004
1005 consumeNext(lJSONItem, theChild.getp(), planState);
1006
1007 lSize = lJSONItem->getArraySize();
1008
1009 STACK_PUSH(GENV_ITEMFACTORY->createInteger(result, lSize), state);
1010
1011 STACK_END(state);
1012 }
1013
1014
1015 /*******************************************************************************
1016 json:member($a as array(), $pos as xs:integer) as item()?
1017 ********************************************************************************/
1018 bool
nextImpl(store::Item_t & result,PlanState & planState) const1019 JSONArrayMemberIterator::nextImpl(
1020 store::Item_t& result,
1021 PlanState& planState) const
1022 {
1023 store::Item_t lInput;
1024 store::Item_t lPosition;
1025
1026 PlanIteratorState* state;
1027 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1028
1029 consumeNext(lInput, theChild0.getp(), planState);
1030 consumeNext(lPosition, theChild1.getp(), planState);
1031
1032 result = lInput->getArrayValue(lPosition->getIntegerValue());
1033
1034 STACK_PUSH(result != 0, state);
1035
1036 STACK_END(state);
1037 }
1038
1039
1040 /*******************************************************************************
1041 json:members($a as array()) as item()*
1042 ********************************************************************************/
1043 bool
nextImpl(store::Item_t & result,PlanState & planState) const1044 JSONArrayMembersIterator::nextImpl(
1045 store::Item_t& result,
1046 PlanState& planState) const
1047 {
1048 store::Item_t array;
1049
1050 JSONArrayMembersIteratorState* state;
1051 DEFAULT_STACK_INIT(JSONArrayMembersIteratorState, state, planState);
1052
1053 consumeNext(array, theChild.getp(), planState);
1054
1055 state->theMembers = array->getArrayValues();
1056 state->theMembers->open();
1057 while (state->theMembers->next(result))
1058 {
1059 STACK_PUSH(true, state);
1060 }
1061 state->theMembers->close();
1062
1063 STACK_END(state);
1064 }
1065
1066
1067 /*******************************************************************************
1068 json:flatten($a as array()) as item()*
1069
1070 op-zorba:flatten-internal($a as item()*) as item()*
1071 ********************************************************************************/
reset(PlanState & planState)1072 void JSONArrayFlattenIteratorState::reset(PlanState& planState)
1073 {
1074 PlanIteratorState::reset(planState);
1075 while (!theStack.empty())
1076 {
1077 theStack.pop();
1078 }
1079 }
1080
1081
1082 bool
nextImpl(store::Item_t & result,PlanState & planState) const1083 JSONArrayFlattenIterator::nextImpl(
1084 store::Item_t& result,
1085 PlanState& planState) const
1086 {
1087 store::Item_t item;
1088 bool lFoundArray = false;
1089
1090 JSONArrayFlattenIteratorState* state;
1091 DEFAULT_STACK_INIT(JSONArrayFlattenIteratorState, state, planState);
1092
1093 consumeNext(item, theChild.getp(), planState);
1094
1095 assert(item->isJSONArray());
1096
1097 state->theStack.push(item->getArrayValues());
1098 state->theStack.top()->open();
1099
1100 while (!state->theStack.empty())
1101 {
1102 while (state->theStack.top()->next(result))
1103 {
1104 if (result->isJSONArray())
1105 {
1106 state->theStack.push(result->getArrayValues());
1107 state->theStack.top()->open();
1108 lFoundArray = true;
1109 break;
1110 }
1111
1112 STACK_PUSH(true, state);
1113 }
1114
1115 if (lFoundArray)
1116 {
1117 lFoundArray = false;
1118 continue;
1119 }
1120
1121 state->theStack.top()->close();
1122 state->theStack.pop();
1123 }
1124
1125 STACK_END(state);
1126 }
1127
1128
1129 /*******************************************************************************
1130 op_zorba:json-item-accessor($i as json-item(), $s as xs:anyAtomic) as item()?
1131 ********************************************************************************/
1132 bool
nextImpl(store::Item_t & result,PlanState & planState) const1133 JSONItemAccessorIterator::nextImpl(
1134 store::Item_t& result,
1135 PlanState& planState) const
1136 {
1137 store::Item_t input;
1138 store::Item_t selector;
1139
1140 const TypeManager* tm = theSctx->get_typemanager();
1141
1142 PlanIteratorState* state;
1143 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1144
1145 consumeNext(input, theChild0.getp(), planState);
1146 consumeNext(selector, theChild1.getp(), planState);
1147
1148 if (input->isJSONArray())
1149 {
1150 store::SchemaTypeCode type = selector->getTypeCode();
1151
1152 if (!TypeOps::is_subtype(type, store::XS_INTEGER))
1153 {
1154 xqtref_t type = tm->create_value_type(selector, loc);
1155
1156 RAISE_ERROR(err::XPTY0004, loc,
1157 ERROR_PARAMS(ZED(XPTY0004_NoTypePromotion_23),
1158 type->toSchemaString(),
1159 GENV_TYPESYSTEM.INTEGER_TYPE_ONE->toSchemaString()));
1160 }
1161
1162 result = input->getArrayValue(selector->getIntegerValue());
1163 }
1164 else if (input->isJSONObject())
1165 {
1166 store::SchemaTypeCode type = selector->getTypeCode();
1167
1168 if (!TypeOps::is_subtype(type, store::XS_STRING) &&
1169 !TypeOps::is_subtype(type, store::XS_UNTYPED_ATOMIC) &&
1170 !TypeOps::is_subtype(type, store::XS_ANY_URI))
1171 {
1172 xqtref_t type = tm->create_value_type(selector, loc);
1173
1174 RAISE_ERROR(err::XPTY0004, loc,
1175 ERROR_PARAMS(ZED(XPTY0004_NoTypePromotion_23),
1176 type->toSchemaString(),
1177 GENV_TYPESYSTEM.STRING_TYPE_ONE->toSchemaString()));
1178 }
1179
1180 result = input->getObjectValue(selector);
1181 }
1182 else
1183 {
1184 ZORBA_ASSERT(false);
1185 }
1186
1187 STACK_PUSH(result != 0, state);
1188
1189 STACK_END(state);
1190 }
1191
1192
1193 /*******************************************************************************
1194 jn:null() as jn:null
1195 ********************************************************************************/
1196 bool
nextImpl(store::Item_t & result,PlanState & planState) const1197 JSONNullIterator::nextImpl(
1198 store::Item_t& result,
1199 PlanState& planState) const
1200 {
1201 PlanIteratorState* state;
1202 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1203
1204 STACK_PUSH(GENV_ITEMFACTORY->createJSONNull(result), state);
1205
1206 STACK_END(state);
1207 }
1208
1209
1210 /*******************************************************************************
1211 jn:is-null(xs:anyAtomicType) as xs:boolean
1212 ********************************************************************************/
1213 bool
nextImpl(store::Item_t & result,PlanState & planState) const1214 JSONIsNullIterator::nextImpl(
1215 store::Item_t& result,
1216 PlanState& planState) const
1217 {
1218 PlanIteratorState* state;
1219 store::Item_t lItem;
1220 bool lIsNull;
1221
1222 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1223
1224 consumeNext(lItem, theChild.getp(), planState);
1225
1226 lIsNull = (lItem->getTypeCode() == store::JS_NULL);
1227
1228 STACK_PUSH(GENV_ITEMFACTORY->createBoolean(result, lIsNull), state);
1229
1230 STACK_END(state);
1231 }
1232
1233
1234 /*******************************************************************************
1235 updating function op-zorba:object-insert(
1236 $o as object(),
1237 $c as object())
1238 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1239 bool JSONObjectInsertIterator::nextImpl(
1240 store::Item_t& result,
1241 PlanState& planState) const
1242 {
1243 store::Item_t target;
1244 store::Item_t content;
1245 store::PUL_t pul;
1246 store::CopyMode copymode;
1247 PlanIteratorState* state;
1248
1249 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1250
1251 consumeNext(target, theChildren[0].getp(), planState);
1252
1253 consumeNext(content, theChildren[1].getp(), planState);
1254
1255 copymode.set(true,
1256 theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1257 theSctx->preserve_ns(),
1258 theSctx->inherit_ns());
1259
1260 if (content->isNode() || content->isJSONItem())
1261 {
1262 content = content->copy(NULL, copymode);
1263 }
1264
1265 pul = GENV_ITEMFACTORY->createPendingUpdateList();
1266
1267 pul->addJSONObjectInsert(&loc, target, content);
1268
1269 result.transfer(pul);
1270
1271 STACK_PUSH(true, state);
1272
1273 STACK_END(state);
1274 }
1275
1276
1277 /*******************************************************************************
1278 updating function op-zorba:array-insert(
1279 $o as array(),
1280 $pos as xs:integer,
1281 $values as item()*,
1282 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1283 bool JSONArrayInsertIterator::nextImpl(
1284 store::Item_t& result,
1285 PlanState& planState) const
1286 {
1287 store::Item_t array;
1288 store::Item_t member;
1289 store::Item_t pos;
1290 std::vector<store::Item_t> members;
1291 store::PUL_t pul;
1292 store::CopyMode copymode;
1293
1294 PlanIteratorState* state;
1295 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1296
1297 consumeNext(array, theChildren[0].getp(), planState);
1298 consumeNext(pos, theChildren[1].getp(), planState);
1299
1300 copymode.set(true,
1301 theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1302 theSctx->preserve_ns(),
1303 theSctx->inherit_ns());
1304
1305 while (consumeNext(member, theChildren[2].getp(), planState))
1306 {
1307 if (member->isNode() || member->isJSONItem())
1308 {
1309 member = member->copy(NULL, copymode);
1310 }
1311
1312 members.resize(members.size() + 1);
1313 members.back().transfer(member);
1314 }
1315
1316 pul = GENV_ITEMFACTORY->createPendingUpdateList();
1317
1318 pul->addJSONArrayInsert(&loc, array, pos, members);
1319
1320 result.transfer(pul);
1321
1322 STACK_PUSH(true, state);
1323
1324 STACK_END (state);
1325 }
1326
1327
1328 /*******************************************************************************
1329 updating function op-zorba:array-append(
1330 $o as array(),
1331 $values as item()*)
1332 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1333 bool JSONArrayAppendIterator::nextImpl(
1334 store::Item_t& result,
1335 PlanState& planState) const
1336 {
1337 store::Item_t array;
1338 store::Item_t member;
1339 std::vector<store::Item_t> members;
1340 store::PUL_t pul;
1341 store::CopyMode copymode;
1342
1343 PlanIteratorState* state;
1344 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1345
1346 consumeNext(array, theChildren[0].getp(), planState);
1347
1348 copymode.set(true,
1349 theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1350 theSctx->preserve_ns(),
1351 theSctx->inherit_ns());
1352
1353 while (consumeNext(member, theChildren[1].getp(), planState))
1354 {
1355 if (member->isNode() || member->isJSONItem())
1356 {
1357 member = member->copy(NULL, copymode);
1358 }
1359
1360 members.resize(members.size() + 1);
1361 members.back().transfer(member);
1362 }
1363
1364 pul = GENV_ITEMFACTORY->createPendingUpdateList();
1365
1366 pul->addJSONArrayAppend(&loc, array, members);
1367
1368 result.transfer(pul);
1369
1370 STACK_PUSH(true, state);
1371
1372 STACK_END (state);
1373 }
1374
1375
1376 /*******************************************************************************
1377 updating function op-zorba:json-delete(
1378 $target as json-item(),
1379 $selector as xs:anyAtomicType)
1380 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1381 bool JSONDeleteIterator::nextImpl(
1382 store::Item_t& result,
1383 PlanState& planState) const
1384 {
1385 store::Item_t target;
1386 store::Item_t selector;
1387 store::PUL_t pul;
1388
1389 const TypeManager* tm = theSctx->get_typemanager();
1390
1391 PlanIteratorState* state;
1392 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1393
1394 consumeNext(target, theChildren[0].getp(), planState);
1395 consumeNext(selector, theChildren[1].getp(), planState);
1396
1397 pul = GENV_ITEMFACTORY->createPendingUpdateList();
1398
1399 if (target->isJSONObject())
1400 {
1401 store::SchemaTypeCode type = selector->getTypeCode();
1402
1403 if (type != store::XS_STRING && type != store::XS_ANY_URI)
1404 {
1405 xqtref_t type = tm->create_value_type(selector, loc);
1406
1407 RAISE_ERROR(jerr::JNUP0007, loc,
1408 ERROR_PARAMS(ZED(JNUP0007_Object), type->toSchemaString()));
1409 }
1410
1411 pul->addJSONObjectDelete(&loc, target, selector);
1412 }
1413 else if (target->isJSONArray())
1414 {
1415 store::SchemaTypeCode type = selector->getTypeCode();
1416
1417 if (type != store::XS_INTEGER)
1418 {
1419 xqtref_t type = tm->create_value_type(selector, loc);
1420
1421 RAISE_ERROR(jerr::JNUP0007, loc,
1422 ERROR_PARAMS(ZED(JNUP0007_Array), type->toSchemaString()));
1423 }
1424
1425 pul->addJSONArrayDelete(&loc, target, selector);
1426 }
1427
1428 result.transfer(pul);
1429
1430 STACK_PUSH(true, state);
1431
1432 STACK_END (state);
1433 }
1434
1435
1436 /*******************************************************************************
1437 updating function op-zorba:replace-value(
1438 $target as json-item(),
1439 $selector as xs:anyAtomicType,
1440 $newValue as item())
1441 ********************************************************************************/
JSONReplaceValueIterator(static_context * sctx,const QueryLoc & loc,std::vector<PlanIter_t> & args,bool copyInput)1442 JSONReplaceValueIterator::JSONReplaceValueIterator(
1443 static_context* sctx,
1444 const QueryLoc& loc,
1445 std::vector<PlanIter_t>& args,
1446 bool copyInput)
1447 :
1448 NaryBaseIterator<JSONReplaceValueIterator, PlanIteratorState>(sctx, loc, args)
1449 {
1450 if (theChildren[2]->isConstructor())
1451 {
1452 theCopyInput = false;
1453 }
1454 else
1455 {
1456 theCopyInput = copyInput;
1457 }
1458 }
1459
1460
nextImpl(store::Item_t & result,PlanState & planState) const1461 bool JSONReplaceValueIterator::nextImpl(
1462 store::Item_t& result,
1463 PlanState& planState) const
1464 {
1465 store::Item_t target;
1466 store::Item_t selector;
1467 store::Item_t newValue;
1468 store::PUL_t pul;
1469 store::CopyMode copymode;
1470
1471 const TypeManager* tm = theSctx->get_typemanager();
1472
1473 PlanIteratorState* state;
1474 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1475
1476 consumeNext(target, theChildren[0].getp(), planState);
1477 consumeNext(selector, theChildren[1].getp(), planState);
1478 consumeNext(newValue, theChildren[2].getp(), planState);
1479
1480 if (theCopyInput && (newValue->isNode() || newValue->isJSONItem()))
1481 {
1482 copymode.set(true,
1483 theSctx->construction_mode() == StaticContextConsts::cons_preserve,
1484 theSctx->preserve_ns(),
1485 theSctx->inherit_ns());
1486
1487 newValue = newValue->copy(NULL, copymode);
1488 }
1489
1490 pul = GENV_ITEMFACTORY->createPendingUpdateList();
1491
1492 if (target->isJSONObject())
1493 {
1494 store::SchemaTypeCode type = selector->getTypeCode();
1495
1496 if (type != store::XS_STRING && type != store::XS_ANY_URI)
1497 {
1498 xqtref_t type = tm->create_value_type(selector, loc);
1499
1500 RAISE_ERROR(jerr::JNUP0007, loc,
1501 ERROR_PARAMS(ZED(JNUP0007_Object), type->toSchemaString()));
1502 }
1503
1504 pul->addJSONObjectReplaceValue(&loc, target, selector, newValue);
1505 }
1506 else if (target->isJSONArray())
1507 {
1508 store::SchemaTypeCode type = selector->getTypeCode();
1509
1510 if (type != store::XS_INTEGER)
1511 {
1512 xqtref_t type = tm->create_value_type(selector, loc);
1513
1514 RAISE_ERROR(jerr::JNUP0007, loc,
1515 ERROR_PARAMS(ZED(JNUP0007_Array), type->toSchemaString()));
1516 }
1517
1518 pul->addJSONArrayReplaceValue(&loc, target, selector, newValue);
1519 }
1520
1521 result.transfer(pul);
1522
1523 STACK_PUSH(true, state);
1524
1525 STACK_END(state);
1526 }
1527
1528
1529 /*******************************************************************************
1530 updating function op-zorba:object-rename(
1531 $o as object(),
1532 $name as xs:string,
1533 $newName as xs:string)
1534 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1535 bool JSONRenameIterator::nextImpl(
1536 store::Item_t& result,
1537 PlanState& planState) const
1538 {
1539 store::Item_t target;
1540 store::Item_t name;
1541 store::Item_t newName;
1542 store::PUL_t pul;
1543
1544 PlanIteratorState* state;
1545 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1546
1547 consumeNext(target, theChildren[0].getp(), planState);
1548 consumeNext(name, theChildren[1].getp(), planState);
1549 consumeNext(newName, theChildren[2].getp(), planState);
1550
1551 pul = GENV_ITEMFACTORY->createPendingUpdateList();
1552
1553 pul->addJSONObjectRename(&loc, target, name, newName);
1554
1555 result.transfer(pul);
1556
1557 STACK_PUSH(true, state);
1558
1559 STACK_END(state);
1560 }
1561
1562
1563 /*******************************************************************************
1564
1565 ********************************************************************************/
nextImpl(store::Item_t & result,PlanState & planState) const1566 bool JSONBoxIterator::nextImpl(
1567 store::Item_t& result,
1568 PlanState& planState) const
1569 {
1570 store::Item_t value1;
1571 store::Item_t value2;
1572 store::Item_t value;
1573
1574 PlanIteratorState* state;
1575 DEFAULT_STACK_INIT(PlanIteratorState, state, planState);
1576
1577 if (!consumeNext(value1, theChild, planState))
1578 {
1579 GENV_STORE.getItemFactory()->createJSONNull(result);
1580 }
1581 else if (!consumeNext(value2, theChild, planState))
1582 {
1583 result.transfer(value1);
1584 }
1585 else
1586 {
1587 store::CopyMode copymode;
1588 copymode.set(false, true, true, true);
1589
1590 store::Iterator_t wrapper = new PlanIteratorWrapper(theChild, planState);
1591
1592 GENV_STORE.getItemFactory()->
1593 createJSONArray(result, value1, value2, wrapper, copymode);
1594 }
1595
1596 STACK_PUSH(true, state);
1597 STACK_END(state);
1598 }
1599
1600
1601 } /* namespace zorba */
1602 /* vim:set et sw=2 ts=2: */
1603
1604 #endif /* ZORBA_WITH_JSON */
1605