bool MultiDynamicFnCallIterator::nextImpl( store::Item_t& result, PlanState& planState) const { store::Item_t item; store::Item_t targetItem; FunctionItem* fnItem; zstring key; MultiDynamicFnCallIteratorState* state; DEFAULT_STACK_INIT(MultiDynamicFnCallIteratorState, state, planState); while (consumeNext(targetItem, theChild, planState)) { if (targetItem->isFunction()) { fnItem = static_cast<FunctionItem*>(targetItem.getp()); if (fnItem->getArity() != 0) { RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS("dynamic function invoked with incorrect number of arguments")); } state->thePlan = fnItem->getImplementation(planState.theCompilerCB); // must be opened after vars and params are set state->thePlan->open(planState, state->theUDFStateOffset); state->theIsOpen = true; while (consumeNext(result, state->thePlan, planState)) { STACK_PUSH(true, state); } // Need to close here early in case the plan is completely consumed. // Otherwise, the plan would still be opened if destroyed from the // state's destructor. state->thePlan->close(planState); state->theIsOpen = false; } // if (targetItem->isFunction()) else if (targetItem->isJSONItem()) { if (targetItem->isObject()) { if (!state->theKeysSet.get()) state->theKeysSet.reset(new HashSet<zstring, HashMapZStringCmp>(64, false)); state->theIterator = targetItem->getObjectKeys(); state->theIterator->open(); while (state->theIterator->next(result)) { key = result->getStringValue(); if (!state->theKeysSet->exists(key)) { state->theKeysSet->insert(key); STACK_PUSH(true, state); } } } else { state->theIterator = targetItem->getArrayValues(); state->theIterator->open(); while (state->theIterator->next(result)) { STACK_PUSH(true, state); } } state->theIterator->close(); } // jsoniq item #if 0 else if (theSctx->language_kind() == StaticContextConsts::language_kind_xquery) { xqtref_t type = theSctx->get_typemanager()->create_value_type(targetItem); RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(XPTY0004_NoTypePromote_23), type->toSchemaString(), GENV_TYPESYSTEM.ANY_FUNCTION_TYPE_ONE->toSchemaString())); } #endif } STACK_END(state); };
bool SingleDynamicFnCallIterator::nextImpl( store::Item_t& result, PlanState& planState) const { store::Item_t item; store::Item_t targetItem; FunctionItem* fnItem; store::Item_t selectorItem1; store::Item_t selectorItem2; store::Item_t selectorItem3; SingleDynamicFnCallIteratorState* state; DEFAULT_STACK_INIT(SingleDynamicFnCallIteratorState, state, planState); // first child must return exactly one item which is a function item // otherwise XPTY0004 is raised if (!consumeNext(targetItem, theChildren[0], planState) || targetItem == NULL) { RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(XPTY0004_NoTypePromote_23), "empty-sequence()", GENV_TYPESYSTEM.ANY_FUNCTION_TYPE_ONE->toSchemaString())); } if (targetItem->isFunction()) { if (consumeNext(item, theChildren[0], planState)) { RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(XPTY0004_NoMultiSeqTypePromotion_2), GENV_TYPESYSTEM.ANY_FUNCTION_TYPE_ONE->toSchemaString())); } fnItem = static_cast<FunctionItem*>(targetItem.getp()); if (theChildren.size() - 1 != fnItem->getArity()) { RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS("dynamic function invoked with incorrect number of arguments")); } if (theIsPartialApply) { for (csize i = 1, pos = 0; i < theChildren.size(); ++i) { if (dynamic_cast<ArgumentPlaceholderIterator*>(theChildren[i].getp()) == NULL) { // The argument needs to be materialized only for local vars and only // if the function item is returned and used outside of the current // function. It might be impossible to determine if the partially // applied function item will be used outside of the current function, // so it is quite probable that it always needs to be materialized. std::vector<store::Item_t> argValues; store::Item_t tempItem; while (consumeNext(tempItem, theChildren[i], planState)) argValues.push_back(tempItem); store::TempSeq_t argSeq = GENV_STORE.createTempSeq(argValues); store::Iterator_t argSeqIter = argSeq->getIterator(); PlanIter_t value = new PlanStateIteratorWrapper(argSeqIter); fnItem->setArgumentValue(pos, value); } else { ++pos; } } result = fnItem; STACK_PUSH(true, state); } else { state->thePlan = fnItem->getImplementation(theChildren, planState.theCompilerCB); // must be opened after vars and params are set state->thePlan->open(planState, state->theUDFStateOffset); state->theIsOpen = true; while (consumeNext(result, state->thePlan, planState)) { STACK_PUSH(true, state); } // Need to close here early in case the plan is completely consumed. // Otherwise, the plan would still be opened if destroyed from the // state's destructor. state->thePlan->close(planState); state->theIsOpen = false; } // if (!theIsPartialApply) } // if (targetItem->isFunction()) else if (targetItem->isJSONItem()) { if (theChildren.size() > 2) { RAISE_ERROR_NO_PARAMS(jerr::JNTY0018, loc); } else if (theChildren.size() == 2) { if (consumeNext(selectorItem1, theChildren[1], planState)) { if (consumeNext(item, theChildren[1], planState)) { RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(NoSeqCastToTypeWithQuantOneOrQuestion))); } // Atomize the selector item switch (selectorItem1->getKind()) { case store::Item::ATOMIC: { selectorItem2.transfer(selectorItem1); break; } case store::Item::NODE: { store::Iterator_t iter; selectorItem1->getTypedValue(selectorItem2, iter); if (iter != NULL && iter->next(selectorItem2)) { if (iter->next(item)) { RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(NoSeqCastToTypeWithQuantOneOrQuestion))); } } break; } case store::Item::OBJECT: { RAISE_ERROR(jerr::JNTY0004, loc, ERROR_PARAMS("object")); } case store::Item::ARRAY: { RAISE_ERROR(jerr::JNTY0004, loc, ERROR_PARAMS("array")); } case store::Item::FUNCTION: { store::Item_t fnName = selectorItem1->getFunctionName(); RAISE_ERROR(err::FOTY0013, loc, ERROR_PARAMS(fnName.getp() ? result->getFunctionName()->getStringValue() : zstring("???"))); } default: { ZORBA_ASSERT(false); } } if (selectorItem2 != NULL) { if (targetItem->isObject()) { GenericCast::castToBuiltinAtomic(selectorItem3, selectorItem2, store::XS_STRING, NULL, loc); result = targetItem->getObjectValue(selectorItem3); } else { GenericCast::castToBuiltinAtomic(selectorItem3, selectorItem2, store::XS_INTEGER, NULL, loc); result = targetItem->getArrayValue(selectorItem3->getIntegerValue()); } STACK_PUSH(result != NULL, state); } } // there is a selector item } // 1 argument else // no arguments { if (targetItem->isObject()) state->theIterator = targetItem->getObjectKeys(); else state->theIterator = targetItem->getArrayValues(); state->theIterator->open(); while (state->theIterator->next(result)) { STACK_PUSH(true, state); } state->theIterator->close(); } } #if 0 else if (theSctx->language_kind() == StaticContextConsts::language_kind_xquery) { xqtref_t type = theSctx->get_typemanager()->create_value_type(targetItem); RAISE_ERROR(err::XPTY0004, loc, ERROR_PARAMS(ZED(XPTY0004_NoTypePromote_23), type->toSchemaString(), GENV_TYPESYSTEM.ANY_FUNCTION_TYPE_ONE->toSchemaString())); } #endif STACK_END(state); };