zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #26938
[Merge] lp:~zorba-coders/zorba/feature-caching into lp:zorba
Federico Cavalieri has proposed merging lp:~zorba-coders/zorba/feature-caching into lp:zorba.
Commit message:
Improved automatic caching, with support of non-atomic arguments with any cardinality.
Fixed caching bug where partly evaluated results were cached.
Added %strictlydeterministic annotation, that caches only within the same snapshot.
Enabled caching of external functions.
Changed automatic caching to be only within the same snapshot and to be completely transparent.
Added dynamic context module.
Added snapshot counting.
Fixed skip for external functions, where empty results were returned when skip was used.
Fixed error reporting (uncatchable exceptions in xquery/jsoniq) in external functions count/skip.
Added external module with utility functions for testing.
Requested reviews:
Federico Cavalieri (fcavalieri)
Matthias Brantner (matthias-brantner)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/feature-caching/+merge/216291
Improved automatic caching, with support of non-atomic arguments with any cardinality.
Fixed caching bug where partly evaluated results were cached.
Added %strictlydeterministic annotation, that caches only within the same snapshot.
Enabled caching of external functions.
Changed automatic caching to be only within the same snapshot and to be completely transparent.
Added dynamic context module.
Added snapshot counting.
Fixed skip for external functions, where empty results were returned when skip was used.
Fixed error reporting (uncatchable exceptions in xquery/jsoniq) in external functions count/skip.
Added external module with utility functions for testing.
--
https://code.launchpad.net/~zorba-coders/zorba/feature-caching/+merge/216291
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h 2014-01-20 16:52:44 +0000
+++ include/zorba/pregenerated/diagnostic_list.h 2014-04-17 12:18:12 +0000
@@ -495,6 +495,14 @@
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZXQP0061_DISABLE_HTTP_OPTION_IN_QUERY;
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZXQP0062_MISSING_ANNOTATION_LITERALS;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZXQP0063_INVALID_ANNOTATION_LITERAL_TYPE;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZXQP0064_INVALID_ARGUMENT_INDEX;
+
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZXQP0065_INVALID_ANNOTATION;
+
#if !defined(ZORBA_NO_FULL_TEXT)
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZXQP8401_THESAURUS_VERSION_MISMATCH;
=== modified file 'include/zorba/serializer.h'
--- include/zorba/serializer.h 2013-02-07 17:24:36 +0000
+++ include/zorba/serializer.h 2014-04-17 12:18:12 +0000
@@ -43,6 +43,11 @@
static Serializer_t
createSerializer(ItemSequence* options);
+ virtual void
+ serialize(
+ Iterator_t object,
+ std::ostream& stream) const = 0;
+
};
} /* namespace zorba */
=== modified file 'modules/CMakeLists.txt'
--- modules/CMakeLists.txt 2014-01-03 17:31:44 +0000
+++ modules/CMakeLists.txt 2014-04-17 12:18:12 +0000
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+ADD_SUBDIRECTORY(util-tests)
ADD_SUBDIRECTORY(util-curl)
ADD_SUBDIRECTORY(atomic)
ADD_SUBDIRECTORY(com)
@@ -26,6 +27,7 @@
ADD_SUBDIRECTORY(org)
ADD_SUBDIRECTORY(schema)
ADD_SUBDIRECTORY(sctx)
+ADD_SUBDIRECTORY(dctx)
ADD_SUBDIRECTORY(sequence)
ADD_SUBDIRECTORY(store)
ADD_SUBDIRECTORY(structured-items)
=== added directory 'modules/dctx'
=== added file 'modules/dctx/CMakeLists.txt'
--- modules/dctx/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ modules/dctx/CMakeLists.txt 2014-04-17 12:18:12 +0000
@@ -0,0 +1,16 @@
+# Copyright 2014 The FLWOR Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+DECLARE_ZORBA_MODULE(FILE dctx.jq VERSION 1.0
+ URI "http://zorba.io/modules/dctx")
=== added file 'modules/dctx/dctx.jq'
--- modules/dctx/dctx.jq 1970-01-01 00:00:00 +0000
+++ modules/dctx/dctx.jq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,42 @@
+jsoniq version "1.0";
+
+(:
+ : Copyright 2006-2014 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+:)
+
+(:===========================================================================:)
+
+(:~
+ : This module provides functions that gets components of the dynamic context.
+ :
+ : @author Federico Cavalieri
+ : @project Zorba/Dynamic Context
+ :)
+module namespace dctx = "http://zorba.io/modules/dctx";
+
+declare namespace ver = "http://zorba.io/options/versioning";
+declare option ver:module-version "1.0";
+
+(:~
+ : <p>Retrieves the current snapshot id.</p>
+ :
+ : <p>The returned id is opaque and should not be used for reasoning about time.
+ : The only guarantee is that the value returned by this function increases each
+ : time a snapshot finishes.</p>
+ :
+ : @return the current snapshot id.
+ :)
+declare function dctx:snapshot-id()
+ as xs:unsignedLong external;
=== modified file 'modules/pregenerated/zorba-errors.xq'
--- modules/pregenerated/zorba-errors.xq 2013-12-12 18:41:52 +0000
+++ modules/pregenerated/zorba-errors.xq 2014-04-17 12:18:12 +0000
@@ -205,6 +205,22 @@
declare variable $zerr:ZXQP0061 as xs:QName := fn:QName($zerr:NS, "zerr:ZXQP0061");
(:~
+:)
+declare variable $zerr:ZXQP0062 as xs:QName := fn:QName($zerr:NS, "zerr:ZXQP0062");
+
+(:~
+:)
+declare variable $zerr:ZXQP0063 as xs:QName := fn:QName($zerr:NS, "zerr:ZXQP0063");
+
+(:~
+:)
+declare variable $zerr:ZXQP0064 as xs:QName := fn:QName($zerr:NS, "zerr:ZXQP0064");
+
+(:~
+:)
+declare variable $zerr:ZXQP0065 as xs:QName := fn:QName($zerr:NS, "zerr:ZXQP0065");
+
+(:~
:
: The version of the thesaurus is not the expected version.
:
=== modified file 'modules/pregenerated/zorba-warnings.xq'
--- modules/pregenerated/zorba-warnings.xq 2013-10-12 01:10:05 +0000
+++ modules/pregenerated/zorba-warnings.xq 2014-04-17 12:18:12 +0000
@@ -59,9 +59,11 @@
(:~
:
: This warning is raised if the user explicitly enables caching
- : of function results (using the %an:cache annotation) but the function
- : is updating or its parameter and return types are not subtypes of
- : xs:anyAtomicType.
+ : of function results (using the %an:cache or %an:strictlydeterministic
+ : annotation) but the function cannot be cached.
+ : For %an:cache this happens if the function is updating or variadic.
+ : For %an:strictlydeterministic this happens if the function is updating,
+ : variadic or sequential.
:
:)
declare variable $zwarn:ZWST0005 as xs:QName := fn:QName($zwarn:NS, "zwarn:ZWST0005");
=== added directory 'modules/util-tests'
=== added file 'modules/util-tests/CMakeLists.txt'
--- modules/util-tests/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ modules/util-tests/CMakeLists.txt 2014-04-17 12:18:12 +0000
@@ -0,0 +1,23 @@
+# Copyright 2006-2014 The FLWOR Foundation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+PROJECT(ZorbaUtilTestsModule)
+
+DECLARE_ZORBA_MODULE(
+ FILE util-tests.xq
+ URI "http://zorba.io/modules/util-tests"
+ VERSION 1.0
+)
\ No newline at end of file
=== added file 'modules/util-tests/util-tests.xq'
--- modules/util-tests/util-tests.xq 1970-01-01 00:00:00 +0000
+++ modules/util-tests/util-tests.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,196 @@
+jsoniq version "1.0";
+(:
+ : Copyright 2014 The FLWOR Foundation.
+ :
+ : Licensed under the Apache License, Version 2.0 (the "License");
+ : you may not use this file except in compliance with the License.
+ : You may obtain a copy of the License at
+ :
+ : http://www.apache.org/licenses/LICENSE-2.0
+ :
+ : Unless required by applicable law or agreed to in writing, software
+ : distributed under the License is distributed on an "AS IS" BASIS,
+ : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ : See the License for the specific language governing permissions and
+ : limitations under the License.
+ :)
+
+
+(:~
+ : This module contains internal test functions.
+ : @author Federico Cavalieri
+ :)
+module namespace tests = "http://zorba.io/modules/util-tests";
+
+declare namespace an = "http://zorba.io/annotations";
+declare namespace ver = "http://zorba.io/options/versioning";
+
+declare option ver:module-version "1.0";
+
+(:~
+ : Equivalent to:
+ : declare %an:cache function local:test-01-cache($x as xs:integer)
+ : {
+ : if ($x < 10)
+ : then $x * $x
+ : else if ($x < 20)
+ : then ()
+ : else ($x, " == ", $x * $x)
+ : };
+ :
+ : @param $arg as described above
+ : @return as described above
+ :)
+declare %an:cache function tests:test-01-cache($arg as xs:integer) as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic function local:test-01-sd($x as xs:integer)
+ : {
+ : if ($x < 10)
+ : then $x * $x
+ : else if ($x < 20)
+ : then ()
+ : else ($x, " == ", $x * $x)
+ : };
+ :
+ : @param $arg as described above
+ : @return as described above
+ :)
+declare %an:strictlydeterministic function tests:test-01-sd($arg as xs:integer) as item()* external;
+
+(:~
+ :
+ : Equivalent to:
+ : declare %an:cache function local:test-02-cache($arg)
+ : {
+ : serialize($arg),
+ : uuid:uuid()
+ : };
+ :
+ : @param $arg as described above
+ : @return as described above
+ :)
+declare %an:cache function tests:test-02-cache($arg) as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic function local:test-02-sd($arg)
+ : {
+ : serialize($arg),
+ : uuid:uuid()
+ : };
+ :
+ : @param $arg as described above
+ : @return as described above
+ :)
+declare %an:strictlydeterministic function tests:test-02-sd($arg) as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:cache function local:test-03-cache()
+ : {
+ : { "a" : 1 },
+ : [1],
+ : <a/>,
+ : 1
+ : };
+ :
+ : @return as described above
+ :)
+declare %an:cache function tests:test-03-cache() as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic function local:test-03-sd()
+ : {
+ : { "a" : 1 },
+ : [1],
+ : <a/>,
+ : 1
+ : };
+ :
+ : @return as described above
+ :)
+declare %an:strictlydeterministic function tests:test-03-sd() as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:cache function local:test-04-cache($x, $y)
+ : {
+ : tests:non-seeakable-streamable-string(),
+ : {"key" : tests:non-seeakable-streamable-string()},
+ : [tests:non-seeakable-streamable-string()],
+ : <a>{tests:non-seeakable-streamable-string()}</a>
+ : serialize($x),
+ : serialize($y)
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:cache function tests:test-04-cache($x, $y) as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic function local:test-04-sd($x, $y)
+ : {
+ : tests:non-seeakable-streamable-string(),
+ : {"key" : tests:non-seeakable-streamable-string()},
+ : [tests:non-seeakable-streamable-string()],
+ : <a>{tests:non-seeakable-streamable-string()}</a>
+ : serialize($x),
+ : serialize($y)
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:strictlydeterministic function tests:test-04-sd($x, $y) as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:cache function local:test-05-cache($x as xs:boolean, $y)
+ : {
+ : if ($x)
+ : then $y
+ : else $x
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:cache function tests:test-05-cache($x as xs:boolean, $y) as item()* external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic function local:test-05-sd($x as xs:boolean, $y)
+ : {
+ : if ($x)
+ : then $y
+ : else $x
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:strictlydeterministic function tests:test-05-sd($x as xs:boolean, $y) as item()* external;
+
+(:~
+ : Returns a non seekable streamable string
+ :
+ : @return a non seekable streamable string
+ :)
+declare %an:deterministic function tests:non-seeakable-streamable-string() as string external;
+
+(:~
+ : This function is not deterministic despite the annotation
+ :
+ : @return a uuid
+ :)
+declare %an:deterministic function tests:uuid() as string external;
+
=== added directory 'modules/util-tests/util-tests.xq.src'
=== added file 'modules/util-tests/util-tests.xq.src/util-tests.cpp'
--- modules/util-tests/util-tests.xq.src/util-tests.cpp 1970-01-01 00:00:00 +0000
+++ modules/util-tests/util-tests.xq.src/util-tests.cpp 2014-04-17 12:18:12 +0000
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2014 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "util-tests.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <stdlib.h>
+
+#include <zorba/function.h>
+#include <zorba/zorba.h>
+#include <zorba/singleton_item_sequence.h>
+#include <zorba/empty_sequence.h>
+#include <zorba/vector_item_sequence.h>
+#include <zorba/serializer.h>
+#include <zorba/util/uuid.h>
+
+
+namespace zorba {
+
+namespace tests {
+
+String
+TestFunction::getURI() const
+{
+ return theModule->getURI();
+}
+
+zorba::Item
+TestFunction::getOneItemArgument(const Arguments_t& aArgs, int aIndex)
+{
+ Item lItem;
+ Iterator_t args_iter = aArgs[aIndex]->getIterator();
+ args_iter->open();
+ args_iter->next(lItem);
+ args_iter->close();
+
+ return lItem;
+}
+
+zorba::Item
+UtilTestsModule::getOneItemArgument(const Arguments_t& aArgs, int aIndex)
+{
+ Item lItem;
+ Iterator_t args_iter = aArgs[aIndex]->getIterator();
+ args_iter->open();
+ args_iter->next(lItem);
+ args_iter->close();
+
+ return lItem;
+}
+
+/******************************************************************************
+ *****************************************************************************/
+zorba::ItemSequence_t
+NonSeeakableStreamableStringFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+
+ std::unique_ptr<std::stringstream> lResultStream(new std::stringstream());
+ (*lResultStream.get()) << "streamable";
+
+ return zorba::ItemSequence_t(
+ new zorba::SingletonItemSequence(
+ lFactory->createStreamableString(*lResultStream.release(), NonSeeakableStreamableStringFunction::streamReleaser, false)
+ )
+ );
+}
+
+zorba::ItemSequence_t
+UtilTestsModule::test01(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+
+ zorba::Item lItem = getOneItemArgument(aArgs, 0);
+ int lParam = lItem.getLongValue();
+
+
+ if (lParam < 10)
+ {
+ //x*x
+ return zorba::ItemSequence_t(
+ new zorba::SingletonItemSequence(
+ lFactory->createInteger(lParam * lParam)
+ )
+ );
+ }
+ else if (lParam < 20)
+ {
+ //()
+ return zorba::ItemSequence_t(
+ new zorba::EmptySequence);
+ }
+ else
+ {
+ //$x, " == ", $x * $x
+ std::vector<zorba::Item> lItems;
+ lItems.push_back(lFactory->createInteger(lParam));
+ lItems.push_back(lFactory->createString(" == "));
+ lItems.push_back(lFactory->createInteger(lParam * lParam));
+
+ return zorba::ItemSequence_t(
+ new zorba::VectorItemSequence(lItems));
+ }
+}
+
+zorba::ItemSequence_t
+UtilTestsModule::test02(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+ std::ostringstream os;
+ Zorba_SerializerOptions_t lOptions;
+ lOptions.omit_xml_declaration = ZORBA_OMIT_XML_DECLARATION_YES;
+ Serializer_t lSerializer = Serializer::createSerializer(lOptions);
+
+ std::stringstream lSerializedArg;
+ lSerializer->serialize(aArgs[0]->getIterator(), lSerializedArg);
+ std::vector<zorba::Item> lResult;
+ zorba::Item lSerializedItem = lFactory->createString(lSerializedArg.str());
+ lResult.push_back(lSerializedItem);
+
+ uuid u;
+ uuid::create(&u);
+ std::ostringstream oss;
+ oss << "urn:uuid:" << u;
+ zorba::Item lRandomItem = lFactory->createString(oss.str());
+ lResult.push_back(lRandomItem);
+
+ return zorba::ItemSequence_t(
+ new zorba::VectorItemSequence(
+ lResult
+ )
+ );
+}
+
+zorba::ItemSequence_t
+UtilTestsModule::test03(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+
+ // {"a":1}
+ std::vector<std::pair<zorba::Item, zorba::Item> > lObjectPairs;
+ zorba::Item lFieldName = lFactory->createString("a");
+ zorba::Item lFieldValue = lFactory->createInteger(1);
+ lObjectPairs.push_back(std::pair<zorba::Item, zorba::Item>(lFieldName, lFieldValue));
+ zorba::Item lObject = lFactory->createJSONObject(lObjectPairs);
+
+ //[1]
+ std::vector<zorba::Item> lStackArray;
+ zorba::Item lArrayValue = lFactory->createInteger("1");
+ lStackArray.push_back(lArrayValue);
+ zorba::Item lArray = lFactory->createJSONArray(lStackArray);
+
+ //<a/>
+ std::vector<std::pair<zorba::String, zorba::String> > lNSBindings;
+ zorba::Item lNullItem;
+ zorba::Item lTypeName = lFactory->createQName("http://www.w3.org/2001/XMLSchema", "untyped");
+ zorba::Item lQName = lFactory->createQName("http://www.w3.org/2001/XMLSchema", "a");
+ zorba::Item lElement = lFactory->createElementNode(lNullItem, lQName, lTypeName, false, false, lNSBindings);
+
+ //1
+ zorba::Item lInteger = lFactory->createInteger(1);
+
+ std::vector<zorba::Item> lResult;
+ lResult.push_back(lObject);
+ lResult.push_back(lArray);
+ lResult.push_back(lElement);
+ lResult.push_back(lInteger);
+
+ return zorba::ItemSequence_t(
+ new zorba::VectorItemSequence(
+ lResult
+ )
+ );
+}
+
+zorba::ItemSequence_t
+UtilTestsModule::test04(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+ std::ostringstream os;
+ Zorba_SerializerOptions_t lOptions;
+ lOptions.omit_xml_declaration = ZORBA_OMIT_XML_DECLARATION_YES;
+ Serializer_t lSerializer = Serializer::createSerializer(lOptions);
+
+ std::vector<zorba::Item> lResult;
+
+ std::unique_ptr<std::stringstream> lResultStream(new std::stringstream());
+ (*lResultStream.get()) << "streamable";
+ zorba::Item lString = lFactory->createStreamableString(
+ *lResultStream.release(),
+ NonSeeakableStreamableStringFunction::streamReleaser,
+ false);
+ lResult.push_back(lString);
+
+ //{"key" : debug:non-seeakable-streamable-string()},
+ std::vector<std::pair<zorba::Item, zorba::Item> > lObjectPairs;
+ zorba::Item lFieldName = lFactory->createString("key");
+ std::unique_ptr<std::stringstream> lResultStream2(new std::stringstream());
+ (*lResultStream2.get()) << "streamable";
+ zorba::Item lFieldValue = lFactory->createStreamableString(
+ *lResultStream2.release(),
+ NonSeeakableStreamableStringFunction::streamReleaser,
+ false);
+ lObjectPairs.push_back(std::pair<zorba::Item, zorba::Item>(lFieldName, lFieldValue));
+ zorba::Item lObject = lFactory->createJSONObject(lObjectPairs);
+
+ lResult.push_back(lObject);
+
+ //[debug:non-seeakable-streamable-string()],
+ std::vector<zorba::Item> lStackArray;
+ std::unique_ptr<std::stringstream> lResultStream3(new std::stringstream());
+ (*lResultStream3.get()) << "streamable";
+ zorba::Item lArrayValue = lFactory->createStreamableString(
+ *lResultStream3.release(),
+ NonSeeakableStreamableStringFunction::streamReleaser,
+ false);
+ lStackArray.push_back(lArrayValue);
+ zorba::Item lArray = lFactory->createJSONArray(lStackArray);
+
+ lResult.push_back(lArray);
+
+ //<a/>
+ std::vector<std::pair<zorba::String, zorba::String> > lNSBindings;
+ zorba::Item lNullItem;
+ zorba::Item lTypeName = lFactory->createQName("http://www.w3.org/2001/XMLSchema", "untyped");
+ zorba::Item lQName = lFactory->createQName("http://www.w3.org/2001/XMLSchema", "a");
+ zorba::Item lElement = lFactory->createElementNode(lNullItem, lQName, lTypeName, false, false, lNSBindings);
+
+ zorba::Item lAQName = lFactory->createQName("http://www.w3.org/2001/XMLSchema", "b");
+ zorba::Item lATypeName = lFactory->createQName("http://www.w3.org/2001/XMLSchema", "untyped");
+ std::unique_ptr<std::stringstream> lResultStream4(new std::stringstream());
+ (*lResultStream4.get()) << "streamable";
+ zorba::Item lAttrValue = lFactory->createStreamableString(
+ *lResultStream4.release(),
+ NonSeeakableStreamableStringFunction::streamReleaser,
+ false);
+ lFactory->createAttributeNode(lElement, lQName, lATypeName, lAttrValue);
+
+ lResult.push_back(lElement);
+
+
+ std::stringstream lFirstArg;
+ lSerializer->serialize(aArgs[0]->getIterator(), lFirstArg);
+ zorba::Item lFirstSerializedItem = lFactory->createString(lFirstArg.str());
+ lResult.push_back(lFirstSerializedItem);
+
+ std::stringstream lSecondArg;
+ lSerializer->serialize(aArgs[1]->getIterator(), lSecondArg);
+ zorba::Item lSecondSerializedItem = lFactory->createString(lSecondArg.str());
+ lResult.push_back(lSecondSerializedItem);
+
+ return zorba::ItemSequence_t(
+ new zorba::VectorItemSequence(
+ lResult
+ )
+ );
+}
+
+zorba::ItemSequence_t
+UtilTestsModule::test05(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::Item lBool = getOneItemArgument(aArgs, 0);
+ zorba::Item lRet;
+ if (lBool.getBooleanValue())
+ lRet = getOneItemArgument(aArgs, 1);
+ else
+ lRet = lBool;
+
+ return zorba::ItemSequence_t(
+ new zorba::SingletonItemSequence(
+ lRet
+ )
+ );
+}
+
+zorba::ItemSequence_t
+UUIDFunction::evaluate(
+ const Arguments_t& aArgs,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+ uuid u;
+ uuid::create(&u);
+ std::ostringstream oss;
+ oss << "urn:uuid:" << u;
+ zorba::Item lRandomItem = lFactory->createString(oss.str());
+
+ return zorba::ItemSequence_t(
+ new zorba::SingletonItemSequence(
+ lRandomItem
+ )
+ );
+}
+
+
+/******************************************************************************
+ *****************************************************************************/
+zorba::ExternalFunction*
+UtilTestsModule::getExternalFunction(const zorba::String& aLocalname)
+{
+ FuncMap_t::const_iterator lFind = theFunctions.find(aLocalname);
+ zorba::ExternalFunction*& lFunc = theFunctions[aLocalname];
+ if (lFind == theFunctions.end()) {
+ if (aLocalname.compare("test-01-cache") == 0)
+ lFunc = new Test01CacheFunction(this);
+ else if (aLocalname.compare("test-01-sd") == 0)
+ lFunc = new Test01SDFunction(this);
+ else if (aLocalname.compare("test-02-cache") == 0)
+ lFunc = new Test02CacheFunction(this);
+ else if (aLocalname.compare("test-02-sd") == 0)
+ lFunc = new Test02SDFunction(this);
+ else if (aLocalname.compare("test-03-cache") == 0)
+ lFunc = new Test03CacheFunction(this);
+ else if (aLocalname.compare("test-03-sd") == 0)
+ lFunc = new Test03SDFunction(this);
+ else if (aLocalname.compare("test-04-cache") == 0)
+ lFunc = new Test04CacheFunction(this);
+ else if (aLocalname.compare("test-04-sd") == 0)
+ lFunc = new Test04SDFunction(this);
+ else if (aLocalname.compare("test-05-cache") == 0)
+ lFunc = new Test05CacheFunction(this);
+ else if (aLocalname.compare("test-05-sd") == 0)
+ lFunc = new Test05SDFunction(this);
+ else if (aLocalname.compare("non-seeakable-streamable-string") == 0)
+ lFunc = new NonSeeakableStreamableStringFunction(this);
+ else if (aLocalname.compare("uuid") == 0)
+ lFunc = new UUIDFunction(this);
+ }
+ return lFunc;
+}
+
+} /* namespace debugmodule */ } /* namespace zorba */
+
+
+/******************************************************************************
+ *****************************************************************************/
+#ifdef WIN32
+# define DLL_EXPORT __declspec(dllexport)
+#else
+# define DLL_EXPORT __attribute__ ((visibility("default")))
+#endif
+extern "C" DLL_EXPORT zorba::ExternalModule* createModule() {
+ return new zorba::tests::UtilTestsModule();
+}
=== added file 'modules/util-tests/util-tests.xq.src/util-tests.h'
--- modules/util-tests/util-tests.xq.src/util-tests.h 1970-01-01 00:00:00 +0000
+++ modules/util-tests/util-tests.xq.src/util-tests.h 2014-04-17 12:18:12 +0000
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2014 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef EXTERNAL_MODULE_UTIL_TESTS_H
+#define EXTERNAL_MODULE_UTIL_TESTS_H
+
+#include <zorba/zorba.h>
+#include <zorba/item_factory.h>
+#include <zorba/external_module.h>
+#include <zorba/function.h>
+
+namespace zorba {
+
+namespace tests {
+
+/******************************************************************************
+ *****************************************************************************/
+class UtilTestsModule : public ExternalModule
+{
+ typedef std::vector<ItemSequence*> Arguments_t;
+
+protected:
+ class ltstr
+ {
+ public:
+ bool operator()(const String& s1, const String& s2) const
+ {
+ return s1.compare(s2) < 0;
+ }
+ };
+
+ typedef std::map<String, ExternalFunction*, ltstr> FuncMap_t;
+
+ FuncMap_t theFunctions;
+public:
+ virtual zorba::String
+ getURI() const { return "http://zorba.io/modules/util-tests"; }
+
+ virtual zorba::ExternalFunction*
+ getExternalFunction(const zorba::String& aLocalname);
+
+ zorba::ItemSequence_t
+ test01(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const;
+
+ zorba::ItemSequence_t
+ test02(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const;
+
+ zorba::ItemSequence_t
+ test03(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const;
+
+ zorba::ItemSequence_t
+ test04(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const;
+
+ zorba::ItemSequence_t
+ test05(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const;
+
+ static zorba::Item
+ getOneItemArgument(const Arguments_t& aArgs, int aIndex);
+};
+
+
+/*******************************************************************************
+ ******************************************************************************/
+class TestFunction : public ContextualExternalFunction
+{
+protected:
+ const UtilTestsModule* theModule;
+
+public:
+ static zorba::Item
+ getOneItemArgument(const Arguments_t& aArgs, int aIndex);
+
+public:
+ TestFunction(const UtilTestsModule* aModule) : theModule(aModule) {};
+
+ String getURI() const;
+
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test01CacheFunction : public TestFunction
+{
+public:
+ Test01CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test01CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-01-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test01(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test01SDFunction : public TestFunction
+{
+public:
+ Test01SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test01SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-01-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test01(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test02CacheFunction : public TestFunction
+{
+public:
+ Test02CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test02CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-02-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test02(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test02SDFunction : public TestFunction
+{
+public:
+ Test02SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test02SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-02-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test02(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test03CacheFunction : public TestFunction
+{
+public:
+ Test03CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test03CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-03-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test03(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test03SDFunction : public TestFunction
+{
+public:
+ Test03SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test03SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-03-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test03(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test04CacheFunction : public TestFunction
+{
+public:
+ Test04CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test04CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-04-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test04(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test04SDFunction : public TestFunction
+{
+public:
+ Test04SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test04SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-04-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test04(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test05CacheFunction : public TestFunction
+{
+public:
+ Test05CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test05CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-05-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test05(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test05SDFunction : public TestFunction
+{
+public:
+ Test05SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test05SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-05-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test05(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class NonSeeakableStreamableStringFunction : public TestFunction
+{
+public:
+ NonSeeakableStreamableStringFunction(const UtilTestsModule* aModule)
+: TestFunction(aModule) {};
+
+ virtual ~NonSeeakableStreamableStringFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "non-seeakable-streamable-string"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+
+ static void streamReleaser(std::istream* stream) {delete stream;};
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class UUIDFunction : public TestFunction
+{
+public:
+ UUIDFunction(const UtilTestsModule* aModule)
+: TestFunction(aModule) {};
+
+ virtual ~UUIDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "uuid"; }
+
+ virtual zorba::ItemSequence_t
+ evaluate(const Arguments_t&,
+ const zorba::StaticContext*,
+ const zorba::DynamicContext*) const;
+};
+
+} /* namespace tests */ } /* namespace zorba */
+
+#endif
=== modified file 'src/annotations/annotations.cpp'
--- src/annotations/annotations.cpp 2013-10-01 03:25:43 +0000
+++ src/annotations/annotations.cpp 2014-04-17 12:18:12 +0000
@@ -78,8 +78,9 @@
//
- // Zorba annotations - deterministic/nondeterministic
+ // Zorba annotations - strictlydeterministic/deterministic/nondeterministic
//
+ ZANN(strictlydeterministic, strictlydeterministic);
ZANN(deterministic, deterministic);
ZANN(nondeterministic, nondeterministic);
@@ -106,7 +107,6 @@
ZANN(streamable, streamable);
ZANN(cache, cache);
- ZANN(no-cache, nocache);
//
// Zorba annotations - xqddf
@@ -168,18 +168,19 @@
ZANN(zann_nonassignable));
theRuleSet.push_back(
+ ZANN(zann_strictlydeterministic) |
ZANN(zann_deterministic) |
ZANN(zann_nondeterministic));
theRuleSet.push_back(
+ ZANN(zann_strictlydeterministic) |
+ ZANN(zann_cache));
+
+ theRuleSet.push_back(
ZANN(zann_sequential) |
ZANN(zann_nonsequential));
theRuleSet.push_back(
- ZANN(zann_cache) |
- ZANN(zann_nocache));
-
- theRuleSet.push_back(
ZANN(fn_private) |
ZANN(fn_public));
=== modified file 'src/annotations/annotations.h'
--- src/annotations/annotations.h 2013-10-01 03:25:43 +0000
+++ src/annotations/annotations.h 2014-04-17 12:18:12 +0000
@@ -59,6 +59,7 @@
{
fn_public = 0,
fn_private,
+ zann_strictlydeterministic,
zann_deterministic,
zann_nondeterministic,
zann_assignable,
@@ -68,7 +69,6 @@
zann_propagates_input_nodes,
zann_must_copy_input_nodes,
zann_cache,
- zann_nocache,
zann_variadic,
zann_streamable,
zann_unique,
=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp 2013-09-16 09:08:27 +0000
+++ src/api/dynamiccontextimpl.cpp 2014-04-17 12:18:12 +0000
@@ -884,7 +884,5 @@
return false;
}
-
-
} // namespace zorba
/* vim:set et sw=2 ts=2: */
=== modified file 'src/api/dynamiccontextimpl.h'
--- src/api/dynamiccontextimpl.h 2013-08-01 07:57:57 +0000
+++ src/api/dynamiccontextimpl.h 2014-04-17 12:18:12 +0000
@@ -66,6 +66,8 @@
static_context * theStaticContext;
+ long theSnapshotID;
+
protected:
static void checkItem(const store::Item_t& aItem);
@@ -78,7 +80,10 @@
dynamic_context* aDctx,
static_context* aSctx)
:
- theQuery(aQuery), theCtx(aDctx), theStaticContext(aSctx)
+ theQuery(aQuery),
+ theCtx(aDctx),
+ theStaticContext(aSctx),
+ theSnapshotID(0)
{
}
=== modified file 'src/api/serializerimpl.cpp'
--- src/api/serializerimpl.cpp 2013-09-11 01:43:33 +0000
+++ src/api/serializerimpl.cpp 2014-04-17 12:18:12 +0000
@@ -84,6 +84,18 @@
}
}
+void
+SerializerImpl::serialize(Iterator_t aIterator, std::ostream& aOs) const
+{
+ try {
+ aIterator->open();
+ theInternalSerializer.serialize(Unmarshaller::getInternalIterator(aIterator), aOs);
+ aIterator->close();
+ } catch (ZorbaException const &e) {
+ ZorbaImpl::notifyError(theDiagnosticHandler, e);
+ }
+}
+
int
SerializerImpl::getSerializationMethod() const
{
=== modified file 'src/api/serializerimpl.h'
--- src/api/serializerimpl.h 2013-02-07 17:24:36 +0000
+++ src/api/serializerimpl.h 2014-04-17 12:18:12 +0000
@@ -51,6 +51,11 @@
ItemSequence* object,
std::ostream& stream) const;
+ virtual void
+ serialize(
+ Iterator_t iterator,
+ std::ostream& stream) const;
+
virtual int
getSerializationMethod() const;
=== modified file 'src/compiler/codegen/plan_visitor.cpp'
--- src/compiler/codegen/plan_visitor.cpp 2014-02-21 03:53:46 +0000
+++ src/compiler/codegen/plan_visitor.cpp 2014-04-17 12:18:12 +0000
@@ -106,6 +106,7 @@
#include "functions/function.h"
#include "functions/udf.h"
+#include "functions/external_function.h"
#include "functions/library.h"
#include "types/typeops.h"
@@ -2526,6 +2527,12 @@
user_function* udf = static_cast<user_function*>(func);
udf->computeResultCaching(theCCB->theXQueryDiagnostics);
}
+ else if (func->isExternal())
+ {
+ // need to computeResultCaching here for iterprint to work
+ external_function* extf = static_cast<external_function*>(func);
+ extf->computeResultCaching(theCCB->theXQueryDiagnostics);
+ }
}
else
{
=== modified file 'src/compiler/rewriter/rules/fold_rules.cpp'
--- src/compiler/rewriter/rules/fold_rules.cpp 2013-09-16 09:08:27 +0000
+++ src/compiler/rewriter/rules/fold_rules.cpp 2014-04-17 12:18:12 +0000
@@ -1060,6 +1060,11 @@
expr* body = udf->getBody();
if (//!udf->isSequential() &&
+ (
+ !udf->getAnnotationList() ||
+ (!udf->getAnnotationList()->contains(AnnotationInternal::zann_cache) &&
+ !udf->getAnnotationList()->contains(AnnotationInternal::zann_strictlydeterministic))
+ ) &&
body != NULL &&
!udf->isExiting() &&
udf->isLeaf())
=== modified file 'src/compiler/translator/translator.cpp'
--- src/compiler/translator/translator.cpp 2014-02-10 00:44:55 +0000
+++ src/compiler/translator/translator.cpp 2014-04-17 12:18:12 +0000
@@ -4204,7 +4204,8 @@
qnameItem->getNamespace(),
sig,
scriptKind,
- ef);
+ ef,
+ theCCB->theXQueryDiagnostics);
}
else
{
=== modified file 'src/context/dynamic_context.cpp'
--- src/context/dynamic_context.cpp 2013-08-29 20:21:59 +0000
+++ src/context/dynamic_context.cpp 2014-04-17 12:18:12 +0000
@@ -128,6 +128,7 @@
theAvailableIndices(NULL),
theAvailableMaps(NULL),
theEnvironmentVariables(NULL),
+ theSnapshotID(0),
theDocLoadingUserTime(0.0),
theDocLoadingTime(0)
{
@@ -1019,5 +1020,15 @@
}
#endif
+uint64_t dynamic_context::getSnapshotID() const
+{
+ return theSnapshotID;
+}
+
+void dynamic_context::changeSnapshot()
+{
+ ++theSnapshotID;
+}
+
} // namespace zorba
/* vim:set et sw=2 ts=2: */
=== modified file 'src/context/dynamic_context.h'
--- src/context/dynamic_context.h 2013-08-29 20:21:59 +0000
+++ src/context/dynamic_context.h 2014-04-17 12:18:12 +0000
@@ -145,6 +145,8 @@
locale::iso3166_1::type theCountry;
time::calendar::type theCalendar;
+ uint64_t theSnapshotID;
+
public:
double theDocLoadingUserTime;
double theDocLoadingTime;
@@ -284,6 +286,9 @@
std::string toString();
#endif
+ uint64_t getSnapshotID() const;
+ void changeSnapshot();
+
protected:
bool lookup_once(const std::string& key, dctx_value_t& val) const
{
=== modified file 'src/context/static_context.cpp'
--- src/context/static_context.cpp 2013-12-04 14:28:07 +0000
+++ src/context/static_context.cpp 2014-04-17 12:18:12 +0000
@@ -446,6 +446,10 @@
"http://zorba.io/modules/sctx";
const char*
+static_context::ZORBA_DCTX_FN_NS =
+"http://zorba.io/modules/dctx";
+
+const char*
static_context::ZORBA_REFLECTION_FN_NS =
"http://zorba.io/modules/reflection";
@@ -565,6 +569,7 @@
ns == ZORBA_XQDOC_FN_NS ||
ns == ZORBA_RANDOM_FN_NS ||
ns == ZORBA_SCTX_FN_NS ||
+ ns == ZORBA_DCTX_FN_NS ||
ns == ZORBA_REFLECTION_FN_NS ||
ns == ZORBA_SCRIPTING_FN_NS ||
ns == ZORBA_STRING_FN_NS ||
=== modified file 'src/context/static_context.h'
--- src/context/static_context.h 2013-11-06 19:01:05 +0000
+++ src/context/static_context.h 2014-04-17 12:18:12 +0000
@@ -545,6 +545,7 @@
static const char* ZORBA_XQDOC_FN_NS;
static const char* ZORBA_RANDOM_FN_NS;
static const char* ZORBA_SCTX_FN_NS;
+ static const char* ZORBA_DCTX_FN_NS;
static const char* ZORBA_REFLECTION_FN_NS;
static const char* ZORBA_STRING_FN_NS;
=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml 2014-03-14 22:38:03 +0000
+++ src/diagnostics/diagnostic_en.xml 2014-04-17 12:18:12 +0000
@@ -3675,23 +3675,22 @@
<diagnostic code="ZWST0005" name="CACHING_NOT_POSSIBLE">
<comment>
This warning is raised if the user explicitly enables caching
- of function results (using the %an:cache annotation) but the function
- is updating or its parameter and return types are not subtypes of
- xs:anyAtomicType.
+ of function results (using the %an:cache or %an:strictlydeterministic
+ annotation) but the function cannot be cached.
+ For %an:cache this happens if the function is updating or variadic.
+ For %an:strictlydeterministic this happens if the function is updating,
+ variadic or sequential.
</comment>
- <value>"$1": function caching not possible; $2</value>
- <entry key="RETURN_TYPE">
- <value>return type ($3) is not subtype of xs:anyAtomicType</value>
- </entry>
- <entry key="PARAM_TYPE">
- <value>type of parameter $3 is $4 which is not a subtype of xs:anyAtomicType</value>
- </entry>
+ <value>"$1": function caching not possible; $2</value>
<entry key="UPDATING">
<value>function is updating</value>
</entry>
<entry key="VARIADIC">
<value>function is variadic</value>
</entry>
+ <entry key="SEQUENTIAL">
+ <value>function is sequential</value>
+ </entry>
</diagnostic>
<diagnostic code="ZWST0006" name="CACHING_MIGHT_NOT_BE_INTENDED">
@@ -3892,6 +3891,10 @@
<entry key="AlreadySpecified">
<value>already specified</value>
</entry>
+
+ <entry key="AppendStringValue">
+ <value>append string value</value>
+ </entry>
<entry key="AppliedAt">
<value>applied at</value>
=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp 2014-01-20 16:52:44 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp 2014-04-17 12:18:12 +0000
@@ -724,6 +724,18 @@
ZorbaErrorCode ZXQP0061_DISABLE_HTTP_OPTION_IN_QUERY( "zerr:ZXQP0061" );
+ZorbaErrorCode ZXQP0062_MISSING_ANNOTATION_LITERALS( "zerr:ZXQP0062" );
+
+
+ZorbaErrorCode ZXQP0063_INVALID_ANNOTATION_LITERAL_TYPE( "zerr:ZXQP0063" );
+
+
+ZorbaErrorCode ZXQP0064_INVALID_ARGUMENT_INDEX( "zerr:ZXQP0064" );
+
+
+ZorbaErrorCode ZXQP0065_INVALID_ANNOTATION( "zerr:ZXQP0065" );
+
+
#if !defined(ZORBA_NO_FULL_TEXT)
ZorbaErrorCode ZXQP8401_THESAURUS_VERSION_MISMATCH( "zerr:ZXQP8401" );
=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp 2014-03-14 22:38:03 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp 2014-04-17 12:18:12 +0000
@@ -517,6 +517,10 @@
{ "zerr:ZXQP0050", "\"$1\": feature not available" },
{ "zerr:ZXQP0060", "\"$1\": unknown option" },
{ "zerr:ZXQP0061", "\"$1\": this option cannot be specified in a query, it must be set via C++ API or command-line parameter" },
+ { "zerr:ZXQP0062", "\"$1\": annotation requires at least one literal" },
+ { "zerr:ZXQP0063", "\"$1\": is not a valid annotation literal for annotation \"$2\", literal has type $3, whereas the allowed types are: $4" },
+ { "zerr:ZXQP0064", "\"$1\": is not a valid argument index for function \"$2\", valid indexes are in the range [1-$3]" },
+ { "zerr:ZXQP0065", "\"$1\": is not a valid annotation for function \"$2\", $3" },
#if !defined(ZORBA_NO_FULL_TEXT)
{ "zerr:ZXQP8401", "\"$1\": wrong WordNet file version; should be \"$2\"" },
#endif
@@ -541,6 +545,7 @@
{ "zwarn:ZWST0009", "feature not supported by the common language grammar${: 1}" },
{ "~AllMatchesHasExcludes", "AllMatches contains StringExclude" },
{ "~AlreadySpecified", "already specified" },
+ { "~AppendStringValue", "append string value" },
{ "~AppliedAt", "applied at" },
{ "~ArithOpNotDefinedBetween_23", "arithmetic operation not defined between types \"$2\" and \"$3\"" },
{ "~AtomizationHasMoreThanOneValue", "atomization has more than one value" },
@@ -1018,8 +1023,10 @@
{ "~XQST0097_MustBeZeroDigit", "must be a digit (Unicode category Nd) and represent zero" },
{ "~XQST0106_Conflicting", "$2: conflicting annotations in declaration" },
{ "~XQST0106_Duplicate", "$2: annotation appears more than once in declaration" },
+ { "~XQST0106_Requirement", "$2: annotation requires one of the following annotations: $3" },
{ "~XQST0116_Conflicting", "$2: conflicting annotations in declaration" },
{ "~XQST0116_Duplicate", "$2: annotation appears more than once in declaration" },
+ { "~XQST0116_Requirement", "$2: annotation requires one of the following annotations: $3" },
{ "~XQST0123_UnrecognizedRequiredFeature_2", "\"$2\": unrecognized required feature" },
{ "~XQST0123_UnrecognizedXQueryOption_2", "\"$2\": unrecognized option in XQuery namespace" },
{ "~XUDY0021_AttributeName", "\"$3\": attribute with the same name already exists" },
@@ -1048,8 +1055,7 @@
{ "~ZJ2X0002_tagNameRequired", "must contain a \"tagName\" key" },
{ "~ZSTR0060_ForCollection_3", "for collection \"$3\"" },
{ "~ZSTR0060_ForSequence", "for sequence" },
- { "~ZWST0005_PARAM_TYPE", "type of parameter $3 is $4 which is not a subtype of xs:anyAtomicType" },
- { "~ZWST0005_RETURN_TYPE", "return type ($3) is not subtype of xs:anyAtomicType" },
+ { "~ZWST0005_SEQUENTIAL", "function is sequential" },
{ "~ZWST0005_UPDATING", "function is updating" },
{ "~ZWST0005_VARIADIC", "function is variadic" },
{ "~ZWST0009_APOS_STRING", "single-quote (apostrophe) quoted strings" },
@@ -1072,6 +1078,7 @@
{ "~ZXQD0004_NOT_WITHIN_RANGE", "not within allowed range ($2)" },
{ "~ZXQP0004_TypeOps_is_in_scope_ForFunctionItemTypes", "TypeOps::is_in_scope() for function-item types" },
{ "~ZXQP0025_RESOURCE_NOT_FOUND", "resource not found" },
+ { "~ZXQP0065_NO_ARGUMENTS", "function has no arguments" },
{ "~ZeroLenURI", "zero-length URI (and no base URI given)" },
{ "~dynamic error", "dynamic error" },
{ "~dynamic warning", "dynamic warning" },
=== modified file 'src/diagnostics/pregenerated/dict_zed_keys.h'
--- src/diagnostics/pregenerated/dict_zed_keys.h 2014-03-14 22:38:03 +0000
+++ src/diagnostics/pregenerated/dict_zed_keys.h 2014-04-17 12:18:12 +0000
@@ -80,8 +80,10 @@
#define ZED_XQST0097_MustBeZeroDigit "~XQST0097_MustBeZeroDigit"
#define ZED_XQST0106_Duplicate "~XQST0106_Duplicate"
#define ZED_XQST0106_Conflicting "~XQST0106_Conflicting"
+#define ZED_XQST0106_Requirement "~XQST0106_Requirement"
#define ZED_XQST0116_Duplicate "~XQST0116_Duplicate"
#define ZED_XQST0116_Conflicting "~XQST0116_Conflicting"
+#define ZED_XQST0116_Requirement "~XQST0116_Requirement"
#define ZED_XQST0123_UnrecognizedXQueryOption_2 "~XQST0123_UnrecognizedXQueryOption_2"
#define ZED_XQST0123_UnrecognizedRequiredFeature_2 "~XQST0123_UnrecognizedRequiredFeature_2"
#define ZED_XPDY0002_VariableHasNoValue_2 "~XPDY0002_VariableHasNoValue_2"
@@ -158,6 +160,7 @@
#define ZED_SENR0001_NamespaceNode "~SENR0001_NamespaceNode"
#define ZED_ZXQP0004_TypeOps_is_in_scope_ForFunctionItemTypes "~ZXQP0004_TypeOps_is_in_scope_ForFunctionItemTypes"
#define ZED_ZXQP0025_RESOURCE_NOT_FOUND "~ZXQP0025_RESOURCE_NOT_FOUND"
+#define ZED_ZXQP0065_NO_ARGUMENTS "~ZXQP0065_NO_ARGUMENTS"
#define ZED_ZXQD0004_NON_NEGATIVE "~ZXQD0004_NON_NEGATIVE"
#define ZED_ZXQD0004_NOT_WITHIN_RANGE "~ZXQD0004_NOT_WITHIN_RANGE"
#define ZED_ZDST0027_NO_KEY_TYPE_DECL "~ZDST0027_NO_KEY_TYPE_DECL"
@@ -215,10 +218,9 @@
#define ZED_FACET_VIOLATION_BadKey_23o "~FACET_VIOLATION_BadKey_23o"
#define ZED_FACET_VIOLATION_BadValue_23o "~FACET_VIOLATION_BadValue_23o"
#define ZED_TYPE_VIOLATION_UnionMemberType "~TYPE_VIOLATION_UnionMemberType"
-#define ZED_ZWST0005_RETURN_TYPE "~ZWST0005_RETURN_TYPE"
-#define ZED_ZWST0005_PARAM_TYPE "~ZWST0005_PARAM_TYPE"
#define ZED_ZWST0005_UPDATING "~ZWST0005_UPDATING"
#define ZED_ZWST0005_VARIADIC "~ZWST0005_VARIADIC"
+#define ZED_ZWST0005_SEQUENTIAL "~ZWST0005_SEQUENTIAL"
#define ZED_ZWST0009_JSON_OBJECT_LOOKUP "~ZWST0009_JSON_OBJECT_LOOKUP"
#define ZED_ZWST0009_CONTEXT_ITEM_EXPR "~ZWST0009_CONTEXT_ITEM_EXPR"
#define ZED_ZWST0009_CHAR_REF "~ZWST0009_CHAR_REF"
@@ -245,6 +247,7 @@
#define ZED_MISSING_VALUE_EmptyHeader "~MISSING_VALUE_EmptyHeader"
#define ZED_AllMatchesHasExcludes "~AllMatchesHasExcludes"
#define ZED_AlreadySpecified "~AlreadySpecified"
+#define ZED_AppendStringValue "~AppendStringValue"
#define ZED_AppliedAt "~AppliedAt"
#define ZED_ArithOpNotDefinedBetween_23 "~ArithOpNotDefinedBetween_23"
#define ZED_AtomizationHasMoreThanOneValue "~AtomizationHasMoreThanOneValue"
=== modified file 'src/functions/CMakeLists.txt'
--- src/functions/CMakeLists.txt 2013-06-27 00:05:25 +0000
+++ src/functions/CMakeLists.txt 2014-04-17 12:18:12 +0000
@@ -61,6 +61,7 @@
LIST(APPEND FUNCTIONS_SRCS
function.cpp
+ cacheable_function.cpp
udf.cpp
external_function.cpp
library.cpp
=== added file 'src/functions/cacheable_function.cpp'
--- src/functions/cacheable_function.cpp 1970-01-01 00:00:00 +0000
+++ src/functions/cacheable_function.cpp 2014-04-17 12:18:12 +0000
@@ -0,0 +1,329 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stdafx.h"
+#include "functions/cacheable_function.h"
+#include "functions/function_impl.h"
+
+#include "annotations/annotations.h"
+
+#include "diagnostics/xquery_warning.h"
+#include "diagnostics/assert.h"
+
+#include "types/typeops.h"
+
+#include "zorbaserialization/serialize_template_types.h"
+#include "zorbaserialization/serialize_zorba_types.h"
+
+#include "zorbautils/hashmap_itemh_strict.h"
+
+#include "runtime/base/plan_iterator.h"
+#include "context/dynamic_context.h"
+
+namespace zorba
+{
+
+/*******************************************************************************
+********************************************************************************/
+bool FunctionCache::ensureCacheValidity(PlanState& aPlanState)
+{
+ if (!theAcrossSnapshots)
+ {
+ uint64_t lCurrentSnapshot = aPlanState.theGlobalDynCtx->getSnapshotID();
+ if (theSnapshotID != lCurrentSnapshot)
+ {
+ theSnapshotID = lCurrentSnapshot;
+ clear();
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+FunctionCache::iterator FunctionCache::find(const store::Item_t& item, PlanState& aPlanState)
+{
+ if (!ensureCacheValidity(aPlanState) || empty())
+ return end();
+ else
+ return FunctionCacheBaseMap::find(item);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool FunctionCache::insert(const store::Item_t& item, std::vector<store::Item_t>& value, PlanState& aPlanState)
+{
+ ensureCacheValidity(aPlanState);
+ return FunctionCacheBaseMap::insert(item, value);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool FunctionCache::insert(const store::Item_t& item, const store::Item_t& value, PlanState& aPlanState)
+{
+ std::vector<store::Item_t> lVector;
+ lVector.push_back(value);
+ return insert(item, lVector, aPlanState);
+}
+
+SERIALIZABLE_CLASS_VERSIONS(cacheable_function)
+
+
+/*******************************************************************************
+********************************************************************************/
+cacheable_function::cacheable_function(
+ const signature& aSig,
+ FunctionConsts::FunctionKind aKind,
+ bool aIsBuiltin,
+ const QueryLoc& aLoc,
+ TypeManager* aTypeManager):
+ function(aSig, aKind, aIsBuiltin),
+ theLoc(aLoc),
+ theTypeManager(aTypeManager),
+ theCacheResults(false),
+ theCacheAcrossSnapshots(false),
+ theCacheComputed(false),
+ theIsCacheAutomatic(false)
+
+{
+
+}
+
+/*******************************************************************************
+********************************************************************************/
+cacheable_function::cacheable_function(::zorba::serialization::Archiver& ar):
+ function(ar)
+{
+
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::serialize(::zorba::serialization::Archiver& ar)
+{
+ serialize_baseclass(ar, (function*)this);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+FunctionCache* cacheable_function::getCache()
+{
+ return &theCache;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::cacheResults() const
+{
+ return theCacheResults;
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::cacheAcrossSnapshots() const
+{
+ return theCacheAcrossSnapshots;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+TypeManager* cacheable_function::getTypeManager()
+{
+ ZORBA_ASSERT(false);
+ return nullptr;
+}
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::computeResultCaching(XQueryDiagnostics* aDiag)
+{
+ if (theCacheComputed)
+ return;
+
+ if (!theTypeManager)
+ theTypeManager = getTypeManager();
+
+ ZORBA_ASSERT(theTypeManager);
+
+ if (!theAnnotationList)
+ useDefaultCachingSettings();
+ else if (theAnnotationList->contains(AnnotationInternal::zann_cache))
+ useZorbaCache(aDiag);
+ else if (theAnnotationList->contains(AnnotationInternal::zann_strictlydeterministic))
+ useStrictlyDeterministicCache(aDiag);
+ else if (theAnnotationList->contains(AnnotationInternal::zann_deterministic))
+ theCacheResults = false;
+ else
+ useDefaultCachingSettings();
+
+ theCacheComputed = true;
+ theCache.setAcrossSnapshots(theCacheAcrossSnapshots);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::useDefaultCachingSettings()
+{
+ if (isVariadic() || isUpdating() || isSequential() || !isDeterministic())
+ {
+ theCacheResults = false;
+ }
+ else
+ {
+ if (!haveAtomicArgumentsAndReturnType())
+ {
+ theCacheResults = false;
+ }
+ else
+ {
+ theCacheResults = true;
+ theIsCacheAutomatic = true;
+ theCacheAcrossSnapshots = false;
+ }
+ }
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::haveAtomicArgumentsAndReturnType() const
+{
+ // parameters are subtype of xs:anyAtomicType
+ csize lArity = theSignature.paramCount();
+ for (csize i = 0; i < lArity; ++i)
+ {
+ if (!isAtomicSequence(theSignature[i]))
+ return false;
+ }
+ // return type is subtype of xs:anyAtomicType
+ if (!isAtomicSequence(theSignature.returnType()))
+ return false;
+
+ return true;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::isAtomicSequence(const xqtref_t& aType) const
+{
+ return
+ (
+ TypeOps::is_subtype(theTypeManager, *aType, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_ONE, theLoc) ||
+ TypeOps::is_subtype(theTypeManager, *aType, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_PLUS, theLoc) ||
+ TypeOps::is_subtype(theTypeManager, *aType, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_QUESTION, theLoc) ||
+ TypeOps::is_subtype(theTypeManager, *aType, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_STAR, theLoc)
+ );
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::haveAllArgumentOneCardinality() const
+{
+ // parameters are subtype of xs:anyAtomicType
+ csize lArity = theSignature.paramCount();
+ for (csize i = 0; i < lArity; ++i)
+ {
+ if (theSignature[i]->card() != 1)
+ return false;
+ }
+ // return type is subtype of xs:anyAtomicType
+ if (theSignature.returnType()->card() != 1)
+ return false;
+
+ return true;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::useZorbaCache(XQueryDiagnostics* aDiag)
+{
+ if (isUpdating() || isVariadic())
+ {
+ if (aDiag)
+ {
+ aDiag->add_warning(
+ NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
+ WARN_PARAMS(getName()->getStringValue(), isUpdating() ? ZED(ZWST0005_UPDATING) : ZED(ZWST0005_VARIADIC)),
+ WARN_LOC(theLoc)));
+ }
+ theCacheResults = false;
+ return;
+ }
+ if (isSequential() || !isDeterministic())
+ {
+ if (aDiag)
+ {
+ aDiag->add_warning(
+ NEW_XQUERY_WARNING(zwarn::ZWST0006_CACHING_MIGHT_NOT_BE_INTENDED,
+ WARN_PARAMS(getName()->getStringValue(), (isSequential() ? "sequential" : "non-deterministic")),
+ WARN_LOC(theLoc)));
+ }
+ }
+ theCacheResults = true;
+ theIsCacheAutomatic = false;
+ theCacheAcrossSnapshots = true;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::useStrictlyDeterministicCache(XQueryDiagnostics* aDiag)
+{
+ if (isUpdating() || isSequential() || isVariadic())
+ {
+ if (aDiag)
+ {
+ aDiag->add_warning(
+ NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
+ WARN_PARAMS(getName()->getStringValue(),
+ isUpdating() ? ZED(ZWST0005_UPDATING) :
+ (isSequential() ? ZED(ZWST0005_SEQUENTIAL) : ZED(ZWST0005_VARIADIC))),
+ WARN_LOC(theLoc)));
+ }
+ theCacheResults = false;
+ }
+ else
+ {
+ theCacheResults = true;
+ theIsCacheAutomatic = false;
+ theCacheAcrossSnapshots = false;
+ }
+}
+
+bool cacheable_function::disableAutomaticCaching()
+{
+ if (theIsCacheAutomatic)
+ {
+ theCacheResults = false;
+ theCache.clear();
+ return true;
+ }
+ return false;
+}
+
+}
=== added file 'src/functions/cacheable_function.h'
--- src/functions/cacheable_function.h 1970-01-01 00:00:00 +0000
+++ src/functions/cacheable_function.h 2014-04-17 12:18:12 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2006-2013 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+#ifndef ZORBA_CACHEABLE_FUNCTION
+#define ZORBA_CACHEABLE_FUNCTION
+
+#include "functions/function.h"
+#include "zorbautils/hashmap_itemh_strict.h"
+#include "store/api/item_handle.h"
+
+namespace zorba
+{
+class expr;
+
+typedef typename zorba::ItemHandleStrictHashMap< std::vector<store::Item_t> > FunctionCacheBaseMap;
+
+class FunctionCache : public FunctionCacheBaseMap
+{
+
+public:
+ typedef typename FunctionCacheBaseMap::iterator iterator;
+
+ FunctionCache() :
+ theAcrossSnapshots(false),
+ theSnapshotID(0) {}
+
+ void setAcrossSnapshots(bool aAcrossSnapshots) {theAcrossSnapshots = aAcrossSnapshots;}
+
+ FunctionCache::iterator find(const store::Item_t& aKey, PlanState& aPlanState);
+
+ bool insert(const store::Item_t& aKey, std::vector<store::Item_t>& aValue, PlanState& aPlanState);
+
+ bool insert(const store::Item_t& aKey, const store::Item_t& aValue, PlanState& aPlanState);
+
+private:
+ bool ensureCacheValidity(PlanState& aPlanState);
+
+public:
+ bool theAcrossSnapshots;
+ uint64_t theSnapshotID;
+
+};
+
+
+/*******************************************************************************
+ theCache:
+ ---------
+ Maps the arg values of an invocation to the result of that invocation.
+ If an invocation uses the same arg values as a previous invocation, the cached
+ result is simply returned without re-evaluating the udf.
+
+ theCacheResults:
+ ----------------
+ Tells whether caching should be done for this udf or not.
+
+ theCacheComputed:
+ -----------------
+ Tells whether theCacheResults has been computed already or not.
+ theCacheResults is computed by the computeResultCaching() method, which is
+ invoked during codegen every time a udf call is encountered. The same udf may
+ be invoked multiple times, but the computation of theCacheResults needs to
+ be done only once. So, during the 1st invcocation of computeResultCaching(),
+ theCacheComputed is set to true, and subsequent invocations are noops.
+********************************************************************************/
+class cacheable_function : public function
+{
+protected:
+ QueryLoc theLoc;
+ TypeManager* theTypeManager;
+ FunctionCache theCache;
+ bool theCacheResults;
+ bool theCacheAcrossSnapshots;
+ bool theCacheComputed;
+ bool theIsCacheAutomatic;
+
+public:
+ SERIALIZABLE_CLASS(cacheable_function)
+ cacheable_function(::zorba::serialization::Archiver& ar);
+ void serialize(::zorba::serialization::Archiver& ar);
+
+public:
+ const QueryLoc& getLoc() const { return theLoc; }
+ cacheable_function(
+ const signature& aSig,
+ FunctionConsts::FunctionKind aKkind,
+ bool aIsBuiltin,
+ const QueryLoc& aLoc,
+ TypeManager* aTypeManager);
+ FunctionCache* getCache();
+ bool cacheResults() const;
+ bool cacheAcrossSnapshots() const;
+
+ virtual void computeResultCaching(XQueryDiagnostics* aDiag);
+ virtual void useDefaultCachingSettings();
+ virtual bool haveAtomicArgumentsAndReturnType() const;
+ virtual bool isAtomicSequence(const xqtref_t& aType) const;
+ virtual bool haveAllArgumentOneCardinality() const;
+ virtual void useZorbaCache(XQueryDiagnostics* aDiag);
+ virtual void useStrictlyDeterministicCache(XQueryDiagnostics* aDiag);
+ virtual bool disableAutomaticCaching();
+
+ virtual TypeManager* getTypeManager();
+};
+
+
+} /* namespace zorba */
+#endif
+
=== modified file 'src/functions/external_function.cpp'
--- src/functions/external_function.cpp 2013-09-26 09:37:30 +0000
+++ src/functions/external_function.cpp 2014-04-17 12:18:12 +0000
@@ -22,10 +22,11 @@
#include "diagnostics/util_macros.h"
+#include "types/typeops.h"
+
#include "zorbaserialization/serialize_template_types.h"
#include "zorbaserialization/serialize_zorba_types.h"
-
namespace zorba
{
@@ -41,10 +42,10 @@
const zstring& ns,
const signature& sig,
unsigned short scriptingType,
- ExternalFunction* impl)
+ ExternalFunction* impl,
+ XQueryDiagnostics* diag)
:
- function(sig, FunctionConsts::FN_UNKNOWN, false),
- theLoc(loc),
+ cacheable_function(sig, FunctionConsts::FN_UNKNOWN, false, loc, modSctx->get_typemanager()),
theNamespace(ns),
theScriptingKind(scriptingType),
theImpl(impl)
@@ -60,7 +61,6 @@
{
zorba::serialization::serialize_baseclass(ar, (function*)this);
- ar & theLoc;
ar & theNamespace;
ar & theScriptingKind;
@@ -68,6 +68,7 @@
zstring lLocalName;
if (ar.is_serializing_out())
{
+ computeResultCaching(NULL);
ZORBA_ASSERT(theImpl);
lLocalName = Unmarshaller::getInternalString(theImpl->getLocalName());
}
@@ -95,6 +96,16 @@
ERROR_PARAMS(BUILD_STRING( '{', theNamespace, '}', lLocalName)));
}
}
+
+ ar & theLoc;
+ ar & theCacheResults;
+ ar & theCacheAcrossSnapshots;
+ ar & theCacheComputed;
+ ar & theIsCacheAutomatic;
+
+ if (!ar.is_serializing_out())
+ theCache.setAcrossSnapshots(theCacheAcrossSnapshots);
+
}
@@ -174,7 +185,6 @@
return true;
}
-
/*******************************************************************************
********************************************************************************/
@@ -188,12 +198,13 @@
return new ExtFunctionCallIterator(sctx,
loc,
argv,
+ this,
theImpl,
isUpdating(),
+ isSequential(),
theNamespace,
theModuleSctx);
}
-
} // namespace zorba
/* vim:set et sw=2 ts=2: */
=== modified file 'src/functions/external_function.h'
--- src/functions/external_function.h 2013-02-07 17:24:36 +0000
+++ src/functions/external_function.h 2014-04-17 12:18:12 +0000
@@ -22,7 +22,7 @@
#include "common/shared_types.h"
-#include "functions/function.h"
+#include "functions/cacheable_function.h"
namespace zorba
{
@@ -35,17 +35,18 @@
theImpl : The user-provided c++ class that implements the external
function.
********************************************************************************/
-class external_function : public function
+class external_function : public cacheable_function
{
protected:
- QueryLoc theLoc;
- zstring theNamespace;
- unsigned short theScriptingKind;
+ QueryLoc theLoc;
+ zstring theNamespace;
+ unsigned short theScriptingKind;
ExternalFunction * theImpl;
+
public:
SERIALIZABLE_CLASS(external_function)
- SERIALIZABLE_CLASS_CONSTRUCTOR2(external_function, function)
+ SERIALIZABLE_CLASS_CONSTRUCTOR2(external_function, cacheable_function)
void serialize(::zorba::serialization::Archiver& ar);
public:
@@ -55,9 +56,10 @@
const zstring& ns,
const signature& sig,
unsigned short scriptingType,
- ExternalFunction* internal);
+ ExternalFunction* internal,
+ XQueryDiagnostics* diag);
- ~external_function() { }
+ ~external_function() {}
unsigned short getScriptingKind() const { return theScriptingKind; }
=== modified file 'src/functions/function.h'
--- src/functions/function.h 2013-09-26 09:38:51 +0000
+++ src/functions/function.h 2014-04-17 12:18:12 +0000
@@ -51,7 +51,7 @@
class function : public SimpleRCObject
{
protected:
- signature theSignature;
+ signature theSignature;
FunctionConsts::FunctionKind theKind;
uint32_t theFlags;
AnnotationList * theAnnotationList;
=== modified file 'src/functions/library.cpp'
--- src/functions/library.cpp 2013-11-06 00:34:34 +0000
+++ src/functions/library.cpp 2014-04-17 12:18:12 +0000
@@ -35,6 +35,7 @@
#include "functions/func_context.h"
#include "functions/func_csv.h"
#include "functions/func_datetime.h"
+#include "functions/func_dctx.h"
#include "functions/func_documents.h"
#include "functions/func_durations_dates_times.h"
#include "functions/func_durations_dates_times_impl.h"
@@ -123,6 +124,7 @@
populate_context_context(sctx);
populate_context_csv(sctx);
populate_context_datetime(sctx);
+ populate_context_dctx(sctx);
populate_context_durations_dates_times(sctx);
populate_context_durations_dates_times_impl(sctx);
populate_context_errors_and_diagnostics(sctx);
=== added file 'src/functions/pregenerated/func_dctx.cpp'
--- src/functions/pregenerated/func_dctx.cpp 1970-01-01 00:00:00 +0000
+++ src/functions/pregenerated/func_dctx.cpp 2014-04-17 12:18:12 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ******************************************
+// * *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME *
+// * *
+// ******************************************
+
+
+
+#include "stdafx.h"
+#include "runtime/dctx/dctx.h"
+#include "functions/func_dctx.h"
+
+
+namespace zorba{
+
+
+
+PlanIter_t fn_zorba_dctx_snapshot_id::codegen(
+ CompilerCB*,
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& argv,
+ expr& ann) const
+{
+ return new DctxSnapshotIdIterator(sctx, loc, argv);
+}
+
+void populate_context_dctx(static_context* sctx)
+{
+
+
+ {
+ DECL_WITH_KIND(sctx, fn_zorba_dctx_snapshot_id,
+ (createQName("http://zorba.io/modules/dctx","","snapshot-id"),
+ GENV_TYPESYSTEM.UNSIGNED_LONG_TYPE_ONE),
+ FunctionConsts::FN_ZORBA_DCTX_SNAPSHOT_ID_0);
+
+ }
+
+}
+
+
+}
+
+
+
=== added file 'src/functions/pregenerated/func_dctx.h'
--- src/functions/pregenerated/func_dctx.h 1970-01-01 00:00:00 +0000
+++ src/functions/pregenerated/func_dctx.h 2014-04-17 12:18:12 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ******************************************
+// * *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME *
+// * *
+// ******************************************
+
+
+
+#ifndef ZORBA_FUNCTIONS_DCTX_H
+#define ZORBA_FUNCTIONS_DCTX_H
+
+
+#include "common/shared_types.h"
+#include "functions/function_impl.h"
+
+
+namespace zorba {
+
+
+void populate_context_dctx(static_context* sctx);
+
+
+
+
+//fn-zorba-dctx:snapshot-id
+class fn_zorba_dctx_snapshot_id : public function
+{
+public:
+ fn_zorba_dctx_snapshot_id(const signature& sig, FunctionConsts::FunctionKind kind)
+ :
+ function(sig, kind)
+ {
+
+ }
+
+ bool accessesDynCtx() const { return true; }
+
+ CODEGEN_DECL();
+};
+
+
+} //namespace zorba
+
+
+#endif
+/*
+ * Local variables:
+ * mode: c++
+ * End:
+ */
=== modified file 'src/functions/pregenerated/function_enum.h'
--- src/functions/pregenerated/function_enum.h 2014-01-31 21:47:54 +0000
+++ src/functions/pregenerated/function_enum.h 2014-04-17 12:18:12 +0000
@@ -130,6 +130,7 @@
FN_ZORBA_DATETIME_PARSE_TIME_3,
FN_ZORBA_DATETIME_TIMESTAMP_0,
FN_ZORBA_DATETIME_UTC_OFFSET_0,
+ FN_ZORBA_DCTX_SNAPSHOT_ID_0,
FN_YEARS_FROM_DURATION_1,
FN_MONTHS_FROM_DURATION_1,
FN_DAYS_FROM_DURATION_1,
=== modified file 'src/functions/udf.cpp'
--- src/functions/udf.cpp 2013-07-02 21:32:23 +0000
+++ src/functions/udf.cpp 2014-04-17 12:18:12 +0000
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006-2008 The FLWOR Foundation.
*
@@ -14,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
#include "stdafx.h"
#include "runtime/core/fncall_iterator.h"
@@ -43,9 +43,6 @@
#include "util/hashmap32.h"
-#include "store/api/index.h" // needed for destruction of the cache
-
-
namespace zorba
{
@@ -62,18 +59,14 @@
unsigned short scriptingKind,
CompilerCB* ccb)
:
-function(sig, FunctionConsts::FN_UNKNOWN, false),
+cacheable_function(sig, FunctionConsts::FN_UNKNOWN, false, loc, NULL),
theCCB(ccb),
- theLoc(loc),
theScriptingKind(scriptingKind),
theBodyExpr(expr_body),
theIsExiting(false),
theIsLeaf(true),
theIsOptimized(false),
- thePlanStateSize(0),
- theCache(0),
- theCacheResults(false),
- theCacheComputed(false)
+ thePlanStateSize(0)
{
setFlag(FunctionConsts::isUDF);
setPrivate(false);
@@ -85,7 +78,7 @@
********************************************************************************/
user_function::user_function(::zorba::serialization::Archiver& ar)
:
- function(ar)
+ cacheable_function(ar)
{
setFlag(FunctionConsts::isUDF);
resetFlag(FunctionConsts::isBuiltin);
@@ -181,8 +174,14 @@
ar & thePlanStateSize;
ar & theArgVarsRefs;
+ ar & theLoc;
ar & theCacheResults;
+ ar & theCacheAcrossSnapshots;
ar & theCacheComputed;
+ ar & theIsCacheAutomatic;
+
+ if (!ar.is_serializing_out())
+ theCache.setAcrossSnapshots(theCacheAcrossSnapshots);
}
@@ -231,8 +230,15 @@
void user_function::setBody(expr* body)
{
theBodyExpr = body;
+ if (body)
+ theTypeManager = body->get_sctx()->get_typemanager();
}
+TypeManager* user_function::getTypeManager()
+{
+ ZORBA_ASSERT(theBodyExpr);
+ return theBodyExpr->get_sctx()->get_typemanager();
+}
/*******************************************************************************
@@ -577,158 +583,13 @@
return theArgVarsRefs;
}
-
-/*******************************************************************************
-
-********************************************************************************/
-store::Index* user_function::getCache() const
-{
- return theCache.getp();
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void user_function::setCache(store::Index* aCache)
-{
- theCache = aCache;
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-bool user_function::cacheResults() const
-{
- return theCacheResults;
-}
-
-
-/*******************************************************************************
- only cache recursive (non-sequential, non-updating, deterministic)
- functions with singleton atomic input and output
-********************************************************************************/
-void user_function::computeResultCaching(XQueryDiagnostics* diag)
-{
- if (theCacheComputed)
- {
- return;
- }
-
- struct OnExit
- {
- private:
- bool& theResult;
- bool& theCacheComputed;
-
- public:
- OnExit(bool& aResult, bool& aCacheComputed)
- :
- theResult(aResult),
- theCacheComputed(aCacheComputed) {}
-
- void cache() { theResult = true; }
-
- ~OnExit()
- {
- theCacheComputed = true;
- }
- };
-
- // will be destroyed when the function is exited
- // set caching to true if cache() is called
- OnExit lExit(theCacheResults, theCacheComputed);
-
- // check necessary conditions
- // %ann:cache or not %ann:no-cache
- if (theAnnotationList &&
- theAnnotationList->contains(AnnotationInternal::zann_nocache))
- {
- return;
- }
-
- // was the %ann:cache annotation given explicitly by the user
- bool explicitCacheRequest =
- (theAnnotationList ?
- theAnnotationList->contains(AnnotationInternal::zann_cache) :
- false);
-
- if (isVariadic())
- {
- if (explicitCacheRequest)
- {
- diag->add_warning(
- NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
- WARN_PARAMS(getName()->getStringValue(), ZED(ZWST0005_VARIADIC)),
- WARN_LOC(theLoc)));
- }
- return;
- }
-
- TypeManager* tm = theBodyExpr->get_sctx()->get_typemanager();
-
- // parameter and return types are subtype of xs:anyAtomicType
- csize lArity = theSignature.paramCount();
- for (csize i = 0; i < lArity; ++i)
- {
- const xqtref_t& lArg = theSignature[i];
- if (!TypeOps::is_subtype(tm,
- *lArg,
- *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_ONE,
- theLoc))
- {
- if (explicitCacheRequest)
- {
- diag->add_warning(
- NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
- WARN_PARAMS(getName()->getStringValue(),
- ZED(ZWST0005_PARAM_TYPE),
- i+1,
- lArg->toString()),
- WARN_LOC(theLoc)));
- }
- return;
- }
- }
-
- // function updating?
- if (isUpdating())
- {
- if (explicitCacheRequest)
- {
- diag->add_warning(
- NEW_XQUERY_WARNING(zwarn::ZWST0005_CACHING_NOT_POSSIBLE,
- WARN_PARAMS(getName()->getStringValue(), ZED(ZWST0005_UPDATING)),
- WARN_LOC(theLoc)));
- }
- return;
- }
-
- if (isSequential() || !isDeterministic())
- {
- if (explicitCacheRequest)
- {
- diag->add_warning(
- NEW_XQUERY_WARNING(zwarn::ZWST0006_CACHING_MIGHT_NOT_BE_INTENDED,
- WARN_PARAMS(getName()->getStringValue(),
- (isSequential()?"sequential":"non-deterministic")),
- WARN_LOC(theLoc)));
-
- lExit.cache();
- }
- return;
- }
-
- // optimization is prerequisite before invoking isRecursive
- if (!explicitCacheRequest && isOptimized() && !isRecursive())
- {
- return;
- }
-
- lExit.cache();
-}
-
+void user_function::useDefaultCachingSettings()
+{
+ if (isOptimized() && !isRecursive())
+ theCacheResults = false;
+ else
+ cacheable_function::useDefaultCachingSettings();
+}
}
=== modified file 'src/functions/udf.h'
--- src/functions/udf.h 2014-02-18 03:40:00 +0000
+++ src/functions/udf.h 2014-04-17 12:18:12 +0000
@@ -17,23 +17,16 @@
#ifndef ZORBA_FUNCTIONS_UDF
#define ZORBA_FUNCTIONS_UDF
-#include "functions/function.h"
+#include "functions/cacheable_function.h"
+#include "store/api/item_handle.h"
//#include "compiler/expression/expr_base.h"
namespace zorba
{
-
class expr;
- namespace store
- {
- class Index;
- typedef rchandle<Index> Index_t;
- }
-
-
/*******************************************************************************
A udf with params $x1, $x2, ..., $xn and a body_expr is translated into a
flwor expr:
@@ -87,26 +80,8 @@
at most one of the references will actually be reached during each particular
execution of the body.
- theCache:
- ---------
- Maps the arg values of an invocation to the result of that invocation.
- If an invocation uses the same arg values as a previous invocation, the cached
- result is simply returned without re-evaluating the udf.
-
- theCacheResults:
- ----------------
- Tells whether caching should be done for this udf or not.
-
- theCacheComputed:
- -----------------
- Tells whether theCacheResults has been computed already or not.
- theCacheResults is computed by the computeResultCaching() method, which is
- invoked during codegen every time a udf call is encountered. The same udf may
- be invoked multiple times, but the computation of theCacheResults needs to
- be done only once. So, during the 1st invcocation of computeResultCaching(),
- theCacheComputed is set to true, and subsequent invocations are noops.
********************************************************************************/
-class user_function : public function
+class user_function : public cacheable_function
{
public:
typedef std::vector<LetVarIter_t> ArgVarRefs;
@@ -114,8 +89,6 @@
private:
CompilerCB * theCCB;
- QueryLoc theLoc;
-
unsigned short theScriptingKind;
expr * theBodyExpr;
@@ -138,10 +111,6 @@
uint32_t thePlanStateSize;
std::vector<ArgVarRefs> theArgVarsRefs;
- store::Index_t theCache;
- bool theCacheResults;
- bool theCacheComputed;
-
public:
SERIALIZABLE_CLASS(user_function)
user_function(::zorba::serialization::Archiver& ar);
@@ -159,8 +128,6 @@
//xqtref_t getUDFReturnType(static_context* sctx) const;
- const QueryLoc& getLoc() const { return theLoc; }
-
bool isExiting() const { return theIsExiting; }
void setExiting(bool v) { theIsExiting = v; }
@@ -173,6 +140,8 @@
expr* getBody() const;
+ virtual TypeManager* getTypeManager();
+
void setScriptingKind(unsigned short k);
csize numArgs() const { return theArgVars.size(); }
@@ -237,13 +206,7 @@
const std::vector<ArgVarRefs>& getArgVarsRefs() const;
- store::Index* getCache() const;
-
- void setCache(store::Index* aCache);
-
- bool cacheResults() const;
-
- void computeResultCaching(XQueryDiagnostics* diag);
+ virtual void useDefaultCachingSettings();
};
=== modified file 'src/runtime/api/plan_iterator_wrapper.cpp'
--- src/runtime/api/plan_iterator_wrapper.cpp 2013-08-23 11:15:04 +0000
+++ src/runtime/api/plan_iterator_wrapper.cpp 2014-04-17 12:18:12 +0000
@@ -43,6 +43,11 @@
return PlanIterator::consumeNext(result, theIterator, *theStateBlock);
}
+void PlanIteratorWrapper::reset()
+{
+ theIterator->reset(*theStateBlock);
+}
+
#ifndef NDEBUG
std::string PlanIteratorWrapper::toString() const
=== modified file 'src/runtime/api/plan_iterator_wrapper.h'
--- src/runtime/api/plan_iterator_wrapper.h 2013-08-23 11:15:04 +0000
+++ src/runtime/api/plan_iterator_wrapper.h 2014-04-17 12:18:12 +0000
@@ -49,7 +49,7 @@
bool next(store::Item_t&);
- void reset() {}
+ void reset();
void close() {}
=== modified file 'src/runtime/core/apply_updates.cpp'
--- src/runtime/core/apply_updates.cpp 2014-02-12 02:25:45 +0000
+++ src/runtime/core/apply_updates.cpp 2014-04-17 12:18:12 +0000
@@ -41,6 +41,8 @@
#include "diagnostics/util_macros.h"
#include "zorba/internal/system_diagnostic.h"
+#include "context/dynamic_context.h"
+
namespace zorba
{
@@ -241,6 +243,8 @@
set_source( e, loc );
throw;
}
+ if (!pul->isTransform())
+ gdctx->changeSnapshot();
}
=== modified file 'src/runtime/core/fncall_iterator.cpp'
--- src/runtime/core/fncall_iterator.cpp 2014-04-15 19:35:58 +0000
+++ src/runtime/core/fncall_iterator.cpp 2014-04-17 12:18:12 +0000
@@ -14,15 +14,13 @@
* limitations under the License.
*/
#include "stdafx.h"
-
#include "runtime/core/fncall_iterator.h"
-#include <map>
-
-#include <zorba/item.h>
-#include <zorba/item_sequence.h>
-#include <zorba/iterator.h>
-#include <zorba/function.h>
+#include "zorba/item.h"
+#include "zorba/item_sequence.h"
+#include "zorba/iterator.h"
+#include "zorba/function.h"
+#include "zorba/vector_item_sequence.h"
#include "diagnostics/xquery_diagnostics.h"
#include "diagnostics/user_exception.h"
@@ -35,9 +33,11 @@
#include "compiler/api/compilercb.h"
#include "functions/udf.h"
+#include "functions/external_function.h"
#include "runtime/core/var_iterators.h"
#include "runtime/util/flowctl_exception.h" // for ExitException
+#include "runtime/util/item_iterator.h"
#include "runtime/api/plan_iterator_wrapper.h"
#include "runtime/visitors/planiter_visitor.h"
#include "runtime/visitors/printer_visitor.h"
@@ -55,12 +55,11 @@
#include "store/api/store.h"
#include "store/api/temp_seq.h"
-
#ifdef ZORBA_WITH_DEBUGGER
#include "debugger/debugger_commons.h"
-#define DEBUGGER_COMMONS state->thePlanState->theDebuggerCommons
+#define DEBUGGER_COMMONS lState->thePlanState->theDebuggerCommons
#define DEBUGGER_PUSH_FRAME \
/* if the debugger is turned on, push the current frame */ \
if (DEBUGGER_COMMONS) { \
@@ -95,10 +94,7 @@
SERIALIZABLE_CLASS_VERSIONS(ExtFunctionCallIterator)
-
-
/*******************************************************************************
-
********************************************************************************/
UDFunctionCallIteratorState::UDFunctionCallIteratorState()
:
@@ -108,20 +104,23 @@
thePlanState(NULL),
thePlanOpen(false),
thePlanStateSize(0),
- theCache(0)
+ theCache(0),
+ theCacheKeySnapshot(0)
{
}
/*******************************************************************************
-
********************************************************************************/
UDFunctionCallIteratorState::~UDFunctionCallIteratorState()
{
if (thePlanOpen)
thePlan->close(*thePlanState);
- delete thePlanState;
- if (theIsLocalDCtxOwner)
+
+ if (thePlanState != NULL)
+ delete thePlanState;
+
+ if (theLocalDCtx != NULL && theIsLocalDCtxOwner)
delete theLocalDCtx;
}
@@ -175,7 +174,6 @@
/*******************************************************************************
-
********************************************************************************/
void UDFunctionCallIteratorState::reset(PlanState& planState)
{
@@ -189,7 +187,6 @@
/*******************************************************************************
-
********************************************************************************/
UDFunctionCallIterator::UDFunctionCallIterator(
static_context* sctx,
@@ -205,13 +202,14 @@
}
+/*******************************************************************************
+********************************************************************************/
UDFunctionCallIterator::~UDFunctionCallIterator()
{
}
/*******************************************************************************
-
********************************************************************************/
void UDFunctionCallIterator::serialize(::zorba::serialization::Archiver& ar)
{
@@ -237,18 +235,14 @@
}
}
-
/*******************************************************************************
-
********************************************************************************/
zstring UDFunctionCallIterator::getNameAsString() const
{
return theUDF->getName()->getStringValue();
}
-
/*******************************************************************************
-
********************************************************************************/
bool UDFunctionCallIterator::isUpdating() const
{
@@ -257,128 +251,99 @@
/*******************************************************************************
-
********************************************************************************/
bool UDFunctionCallIterator::isCached() const
{
return theUDF->cacheResults();
}
-
-/*******************************************************************************
-
-********************************************************************************/
-void UDFunctionCallIterator::createCache(
- PlanState& planState,
- UDFunctionCallIteratorState* state)
-{
- if (theUDF->cacheResults())
+/*******************************************************************************
+********************************************************************************/
+bool UDFunctionCallIterator::isCacheAcrossSnapshots() const
+{
+ return theUDF->cacheAcrossSnapshots();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void UDFunctionCallIterator::initCache(
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState)
+{
+ if (!aState->theCache && theUDF->cacheResults())
{
- store::Index_t index = theUDF->getCache();
-
+ aState->theCache = theUDF->getCache();
csize numArgs = theChildren.size();
-
- if (!index)
- {
- const signature& sig = theUDF->getSignature();
-
- store::IndexSpecification lSpec;
- lSpec.theNumKeyColumns = numArgs;
- lSpec.theKeyTypes.resize(numArgs);
- lSpec.theCollations.resize(numArgs);
- lSpec.theIsTemp = true;
- lSpec.theIsUnique = false;
-
- for (csize i = 0; i < numArgs; ++i)
- {
- lSpec.theKeyTypes[i] = sig[i]->getBaseBuiltinType()->getQName().getp();
- }
-
- index = GENV_STORE.createIndex(theUDF->getName(), lSpec, 0);
-
- theUDF->setCache(index.getp()); // cache the cache in the function itself
-
- state->theArgValues.reserve(numArgs);
- }
-
- state->theCache = index.getp();
- state->theCacheCond = index->createCondition(store::IndexCondition::POINT_VALUE);
- state->theCacheProbeIte = GENV_ITERATOR_FACTORY->createIndexProbeIterator(index);
- state->theArgValues.resize(numArgs);
-
+ aState->theArgValues.resize(numArgs);
for (csize i = 0; i < numArgs; ++i)
- {
- state->theArgValues[i] = new SingleItemIterator();
- }
+ aState->theArgValues[i] = new ItemIterator();
}
}
/*******************************************************************************
-
********************************************************************************/
bool UDFunctionCallIterator::probeCache(
- PlanState& planState,
- UDFunctionCallIteratorState* state,
- store::Item_t& result,
- std::vector<store::Item_t>& argValues) const
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState,
+ std::vector<std::vector <store::Item_t> >& aArguments) const
{
- assert(state->theCache);
-
- state->theCacheCond->clear();
-
- std::vector<store::Iterator_t>::iterator ite = state->theArgWrappers.begin();
-
- for (; ite != state->theArgWrappers.end(); ++ite)
+ assert(aState->theCache);
+
+ std::vector<store::Iterator_t>::iterator lIte = aState->theArgWrappers.begin();
+ std::vector<store::Item_t> lProbeKeys;
+ for (; lIte != aState->theArgWrappers.end(); ++lIte)
{
- store::Iterator_t& argWrapper = (*ite);
- store::Item_t argValue;
+ store::Iterator_t& lArgWrapper = (*lIte);
+ std::vector<store::Item_t> lArgSeq;
+ std::vector<store::Item_t> lKeySeq;
+ store::Item_t lArgItemValue;
- if (argWrapper) // might be 0 if argument is not used
+ if (lArgWrapper) // might be 0 if argument is not used
{
- argWrapper->next(argValue); // guaranteed to have exactly one result
+ while (lArgWrapper->next(lArgItemValue))
+ {
+ lArgItemValue->ensureSeekable();
+ lArgSeq.push_back(lArgItemValue);
+ lKeySeq.push_back(lArgItemValue);
+ }
}
- argValues.push_back(argValue);
-
- state->theCacheCond->pushItem(argValue);
- }
-
- state->theCacheProbeIte->init(state->theCacheCond);
- state->theCacheProbeIte->open();
-
- return state->theCacheProbeIte->next(result);
+ aArguments.push_back(lArgSeq);
+ lProbeKeys.push_back(store::Item_t(new simplestore::ItemVector(lKeySeq)));
+ }
+
+ aState->theCacheKey = store::Item_t(new simplestore::ItemVector(lProbeKeys));
+ if (!isCacheAcrossSnapshots())
+ aState->theCacheKeySnapshot = aPlanState.theGlobalDynCtx->getSnapshotID();
+
+ FunctionCache::iterator lIt = aState->theCache->find(aState->theCacheKey, aPlanState);
+ if (lIt == aState->theCache->end())
+ {
+ aState->theCachedResult.clear();
+ return false;
+ }
+
+ aState->theCachedResult = lIt.getValue();
+ return true;
}
-
/*******************************************************************************
-
********************************************************************************/
void UDFunctionCallIterator::insertCacheEntry(
- UDFunctionCallIteratorState* state,
- std::vector<store::Item_t>& argValues,
- const store::Item_t& udfResult) const
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState,
+ std::vector<store::Item_t>& aResult) const
{
- assert(state->theCache);
-
- state->theCacheKey = new store::IndexKey();
- state->theCacheKey->theItems.swap(argValues);
- store::Item_t tmp = udfResult;
-
- try
- {
- ZORBA_ASSERT(!state->theCache->insert(state->theCacheKey, tmp));
- }
- catch (...)
- {
- delete state->theCacheKey;
- throw;
+ assert(aState->theCache);
+ if (isCacheAcrossSnapshots() || aState->theCacheKeySnapshot == aPlanState.theGlobalDynCtx->getSnapshotID())
+ {
+ aState->theCache->insert(aState->theCacheKey, aResult, aPlanState);
}
}
-
/*******************************************************************************
-
********************************************************************************/
void UDFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
@@ -404,7 +369,7 @@
if (planState.theStackDepth + 1 > planState.theMaxStackDepth)
{
RAISE_ERROR(zerr::ZXQP0003_INTERNAL_ERROR, loc,
- ERROR_PARAMS(ZED(StackOverflow)));
+ ERROR_PARAMS(ZED(StackOverflow)));
}
// Create the plan for the udf body (if not done already) and allocate
@@ -414,7 +379,7 @@
// if the results of the function should be cached (prereq: atomic in and out)
// this functions stores an index in the dynamic context that contains
// the cached results. The name of the index is the name of the function.
- createCache(planState, state);
+ initCache(planState, state);
// Create a wrapper over each subplan that computes an argument expr, if the
// associated param is actually used anywhere in the function body.
@@ -436,7 +401,7 @@
if (!argVarRefs.empty())
{
if ((*argWrapsIte) == NULL)
- (*argWrapsIte) = new PlanIteratorWrapper((*argsIte), planState);
+ (*argWrapsIte) = new PlanIteratorWrapper((*argsIte), planState);
// Cannot do the arg bind here because the state->thePlan has not been
// opened yet, and as a result, state->thePlanState has not been
@@ -448,7 +413,6 @@
/*******************************************************************************
-
********************************************************************************/
void UDFunctionCallIterator::resetImpl(PlanState& planState) const
{
@@ -466,7 +430,6 @@
/*******************************************************************************
-
********************************************************************************/
void UDFunctionCallIterator::closeImpl(PlanState& planState)
{
@@ -484,156 +447,15 @@
/*******************************************************************************
-
********************************************************************************/
-bool UDFunctionCallIterator::nextImpl(store::Item_t& result, PlanState& planState) const
+bool UDFunctionCallIterator::nextImpl(store::Item_t& aResult, PlanState& aPlanState) const
{
try
{
- std::vector<store::Item_t> argValues;
- bool cacheHit;
- store::Item_t tmp;
-
- UDFunctionCallIteratorState* state;
- DEFAULT_STACK_INIT(UDFunctionCallIteratorState, state, planState);
-
- // Open the plan, if not done already. This cannot be done in the openImpl
- // method because in the case of recursive functions, we will get into an
- // infinite loop.
- if (!state->thePlanOpen)
- {
- uint32_t planOffset = 0;
- state->thePlan->open(*state->thePlanState, planOffset);
- state->thePlanOpen = true;
- }
-
- if (state->theCache)
- {
- // check if the result is already in the cache
- cacheHit = probeCache(planState, state, result, argValues);
-
- // if not in the cache, we bind the arguments to the function
- if (!cacheHit)
- {
- const std::vector<ArgVarRefs>& argsRefs = theUDF->getArgVarsRefs();
- const std::vector<store::Iterator_t>& argWraps = state->theArgWrappers;
-
- for (csize i = 0; i < argsRefs.size(); ++i)
- {
- if (argWraps[i] != NULL)
- {
- const ArgVarRefs& argVarRefs = argsRefs[i];
- store::Iterator_t argWrapper;
-
- store::Item_t argValue = argValues[i];
- state->theArgValues[i]->init(argValue);
- argWrapper = state->theArgValues[i];
-
- ArgVarRefs::const_iterator argVarRefsIte = argVarRefs.begin();
- ArgVarRefs::const_iterator argVarRefsEnd = argVarRefs.end();
-
- for (; argVarRefsIte != argVarRefsEnd; ++argVarRefsIte)
- {
- const LetVarIter_t& argRef = (*argVarRefsIte);
- assert(argRef != NULL);
-
- if (argRef != NULL)
- {
- argRef->bind(argWrapper, *state->thePlanState);
- }
- }
- }
- }
- }
-
- if (!cacheHit)
- {
- DEBUGGER_PUSH_FRAME;
-
- if (consumeNext(result, state->thePlan, *state->thePlanState))
- {
- insertCacheEntry(state, argValues, result);
-
- DEBUGGER_POP_FRAME;
- STACK_PUSH(true, state);
- DEBUGGER_PUSH_FRAME;
-
- while (consumeNext(result, state->thePlan, *state->thePlanState))
- {
- tmp = result;
- ZORBA_ASSERT(state->theCache->insert(state->theCacheKey, tmp));
-
- DEBUGGER_POP_FRAME;
- STACK_PUSH(true, state);
- DEBUGGER_PUSH_FRAME;
- }
- }
- else
- {
- insertCacheEntry(state, argValues, NULL);
- }
-
- DEBUGGER_POP_FRAME;
- }
- else // cache hit
- {
- if (result != NULL)
- {
- STACK_PUSH(true, state);
-
- while (state->theCacheProbeIte->next(result))
- {
- STACK_PUSH(true, state);
- }
- }
- }
- }
- else // no cache
- {
- {
- const std::vector<ArgVarRefs>& argsRefs = theUDF->getArgVarsRefs();
- const std::vector<store::Iterator_t>& argWraps = state->theArgWrappers;
-
- for (csize i = 0; i < argsRefs.size(); ++i)
- {
- if (argWraps[i] != NULL)
- {
- const ArgVarRefs& argVarRefs = argsRefs[i];
- store::Iterator_t argWrapper;
-
- if (i < argWraps.size())
- argWrapper = argWraps[i];
-
- ArgVarRefs::const_iterator argVarRefsIte = argVarRefs.begin();
- ArgVarRefs::const_iterator argVarRefsEnd = argVarRefs.end();
-
- for (; argVarRefsIte != argVarRefsEnd; ++argVarRefsIte)
- {
- const LetVarIter_t& argRef = (*argVarRefsIte);
- assert(argRef != NULL);
-
- if (argRef != NULL)
- {
- argRef->bind(argWrapper, *state->thePlanState);
- }
- }
- }
- }
- }
-
- DEBUGGER_PUSH_FRAME;
-
- while (consumeNext(result, state->thePlan, *state->thePlanState))
- {
- DEBUGGER_POP_FRAME;
- STACK_PUSH(true, state);
- DEBUGGER_PUSH_FRAME;
- }
-
- DEBUGGER_POP_FRAME;
- }
-
- STACK_END(state);
+ if (theUDF->cacheResults())
+ return nextImplCache(aResult, aPlanState);
+ else
+ return nextImplNoCache(aResult, aPlanState);
}
catch (ZorbaException& err)
{
@@ -647,9 +469,218 @@
}
-#if 0
-NARY_ACCEPT(UDFunctionCallIterator);
-#else
+/*******************************************************************************
+ ********************************************************************************/
+bool UDFunctionCallIterator::nextImplCache(store::Item_t& aResult, PlanState& aPlanState) const
+{
+ std::vector< std::vector <store::Item_t> > lArguments;
+ bool lSkipCache = false;
+ bool lCacheHit = false;
+
+ UDFunctionCallIteratorState* lState;
+ DEFAULT_STACK_INIT(UDFunctionCallIteratorState, lState, aPlanState);
+
+ // Open the plan, if not done already. This cannot be done in the openImpl
+ // method because in the case of recursive functions, we will get into an
+ // infinite loop.
+ if (!lState->thePlanOpen)
+ {
+ uint32_t planOffset = 0;
+ lState->thePlan->open(*lState->thePlanState, planOffset);
+ lState->thePlanOpen = true;
+ }
+
+
+ try
+ {
+ // check if the result is already in the cache
+ lCacheHit = probeCache(aPlanState, lState, lArguments);
+ }
+ catch (ZorbaException& err)
+ {
+ lSkipCache = true;
+ }
+
+ if (lSkipCache)
+ {
+ //Pulling the argument iterators eagerly raised an error
+ //Disable automatic caching
+ //Try to evaluate the function as if no cache is present
+ theUDF->disableAutomaticCaching();
+ bindArguments(lState, true);
+
+ DEBUGGER_PUSH_FRAME;
+
+ while (consumeNext(aResult, lState->thePlan, *lState->thePlanState))
+ {
+ DEBUGGER_POP_FRAME;
+ STACK_PUSH(true, lState);
+ DEBUGGER_PUSH_FRAME;
+ }
+
+ DEBUGGER_POP_FRAME;
+ }
+ else
+ {
+ // if not in the cache, we bind the arguments to the function
+ if (!lSkipCache && !lCacheHit)
+ {
+ const std::vector<ArgVarRefs>& lArgsRefs = theUDF->getArgVarsRefs();
+ const std::vector<store::Iterator_t>& lArgWraps = lState->theArgWrappers;
+
+ for (csize i = 0; i < lArgsRefs.size(); ++i)
+ {
+ if (lArgWraps[i] != NULL)
+ {
+ const ArgVarRefs& lArgVarRefs = lArgsRefs[i];
+ store::Iterator_t lArgWrapper;
+ lState->theArgValues[i]->init(lArguments[i]);
+ lArgWrapper = lState->theArgValues[i];
+
+ ArgVarRefs::const_iterator lArgVarRefsIte = lArgVarRefs.begin();
+ ArgVarRefs::const_iterator lArgVarRefsEnd = lArgVarRefs.end();
+
+ for (; lArgVarRefsIte != lArgVarRefsEnd; ++lArgVarRefsIte)
+ {
+ const LetVarIter_t& argRef = (*lArgVarRefsIte);
+ assert(argRef != NULL);
+
+ if (argRef != NULL)
+ {
+ argRef->bind(lArgWrapper, *lState->thePlanState);
+ }
+ }
+ }
+ }
+ }
+
+ if (!lCacheHit)
+ {
+ DEBUGGER_PUSH_FRAME;
+
+ if (consumeNext(aResult, lState->thePlan, *lState->thePlanState))
+ {
+ //We cannot insert directly into the cache, or different call iterators
+ //for the same function will see partial results in the cache.
+ //We cannot do a stack push here or self-recursive UDFs will not be
+ //cached
+ while (consumeNext(lState->theNextResult, lState->thePlan, *lState->thePlanState))
+ {
+ if (!aResult.isNull())
+ {
+ aResult->ensureSeekable();
+ lState->theCachedResult.push_back(aResult);
+
+ DEBUGGER_POP_FRAME;
+ STACK_PUSH(true, lState);
+ DEBUGGER_PUSH_FRAME;
+ }
+ aResult = lState->theNextResult;
+ }
+
+ if (!aResult.isNull())
+ {
+ aResult->ensureSeekable();
+ lState->theCachedResult.push_back(aResult);
+ insertCacheEntry(aPlanState, lState, lState->theCachedResult);
+
+ DEBUGGER_POP_FRAME;
+ STACK_PUSH(true, lState);
+ DEBUGGER_PUSH_FRAME;
+ }
+ }
+ else
+ {
+ insertCacheEntry(aPlanState, lState, lState->theCachedResult);
+ }
+
+ DEBUGGER_POP_FRAME;
+ }
+ else // cache hit
+ {
+ lState->theCachedResultIterator = lState->theCachedResult.begin();
+ while (lState->theCachedResultIterator != lState->theCachedResult.end())
+ {
+ aResult = *(lState->theCachedResultIterator++);
+ STACK_PUSH(true, lState);
+ }
+ }
+ }
+ STACK_END(lState);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool UDFunctionCallIterator::nextImplNoCache(store::Item_t& aResult, PlanState& aPlanState) const
+{
+ UDFunctionCallIteratorState* lState;
+ DEFAULT_STACK_INIT(UDFunctionCallIteratorState, lState, aPlanState);
+
+ // Open the plan, if not done already. This cannot be done in the openImpl
+ // method because in the case of recursive functions, we will get into an
+ // infinite loop.
+ if (!lState->thePlanOpen)
+ {
+ uint32_t planOffset = 0;
+ lState->thePlan->open(*lState->thePlanState, planOffset);
+ lState->thePlanOpen = true;
+ }
+
+ bindArguments(lState, false);
+
+ DEBUGGER_PUSH_FRAME;
+
+ while (consumeNext(aResult, lState->thePlan, *lState->thePlanState))
+ {
+ DEBUGGER_POP_FRAME;
+ STACK_PUSH(true, lState);
+ DEBUGGER_PUSH_FRAME;
+ }
+
+ DEBUGGER_POP_FRAME;
+
+ STACK_END(lState);
+}
+
+/*******************************************************************************
+********************************************************************************/
+void UDFunctionCallIterator::bindArguments(UDFunctionCallIteratorState* aState, bool aReset) const
+{
+ const std::vector<ArgVarRefs>& lArgsRefs = theUDF->getArgVarsRefs();
+ const std::vector<store::Iterator_t>& lArgWraps = aState->theArgWrappers;
+
+ for (csize i = 0; i < lArgsRefs.size(); ++i)
+ {
+ if (lArgWraps[i] != NULL)
+ {
+ const ArgVarRefs& lArgVarRefs = lArgsRefs[i];
+ store::Iterator_t lArgWrapper;
+
+ if (i < lArgWraps.size())
+ {
+ lArgWrapper = lArgWraps[i];
+ if (aReset)
+ lArgWrapper->reset();
+ }
+
+ ArgVarRefs::const_iterator lArgVarRefsIte = lArgVarRefs.begin();
+ ArgVarRefs::const_iterator lArgVarRefsEnd = lArgVarRefs.end();
+
+ for (; lArgVarRefsIte != lArgVarRefsEnd; ++lArgVarRefsIte)
+ {
+ const LetVarIter_t& lArgRef = (*lArgVarRefsIte);
+ assert(lArgRef != NULL);
+
+ if (lArgRef != NULL)
+ {
+ lArgRef->bind(lArgWrapper, *aState->thePlanState);
+ }
+ }
+ }
+ }
+}
+
//
// We specialize accept() to descend into the separate plan for the UDF, but
// only for a PrinterVisitor and no other kind of visitor.
@@ -678,7 +709,6 @@
}
v.endVisit( *this );
}
-#endif
/////////////////////////////////////////////////////////////////////////////////
@@ -689,7 +719,6 @@
/*******************************************************************************
-
********************************************************************************/
class ExtFuncArgItemSequence : public ItemSequence
{
@@ -767,14 +796,20 @@
return new InternalIterator(this);
}
+
+ virtual void reset()
+ {
+ theChild->reset(thePlanState);
+ }
};
/*******************************************************************************
-
********************************************************************************/
-ExtFunctionCallIteratorState::ExtFunctionCallIteratorState():
- theIsEvaluated(false)
+ExtFunctionCallIteratorState::ExtFunctionCallIteratorState() :
+ theIsEvaluated(false),
+ theCache(0),
+ theCacheKeySnapshot(0)
{
}
@@ -802,32 +837,39 @@
/*******************************************************************************
-
********************************************************************************/
ExtFunctionCallIterator::ExtFunctionCallIterator(
static_context* sctx,
const QueryLoc& loc,
std::vector<PlanIter_t>& args,
+ const external_function* functionDef,
const ExternalFunction* function,
bool isUpdating,
+ bool isSequential,
const zstring& ns,
static_context* moduleSctx)
:
NaryBaseIterator<ExtFunctionCallIterator,
ExtFunctionCallIteratorState>(sctx, loc, args),
+ theFunctionDef(const_cast<external_function*>(functionDef)),
theFunction(function),
theIsUpdating(isUpdating),
+ theIsSequential(isSequential),
theNamespace(ns),
theModuleSctx(moduleSctx)
{
}
+/*******************************************************************************
+********************************************************************************/
ExtFunctionCallIterator::~ExtFunctionCallIterator()
{
}
+/*******************************************************************************
+********************************************************************************/
zstring ExtFunctionCallIterator::getNameAsString() const {
String const uri( theFunction->getURI() );
String const local( theFunction->getLocalName() );
@@ -836,7 +878,8 @@
return name;
}
-
+/*******************************************************************************
+********************************************************************************/
void ExtFunctionCallIterator::serialize(serialization::Archiver& ar)
{
ar.dont_allow_delay_for_plan_sctx = true;
@@ -845,6 +888,9 @@
ExtFunctionCallIterator,
ExtFunctionCallIteratorState>*>(this));
ar.dont_allow_delay_for_plan_sctx = false;
+
+ ar & theFunctionDef;
+
if (ar.is_serializing_out())
{
// serialize out: serialize prefix and localname of the function
@@ -891,6 +937,8 @@
}
+/*******************************************************************************
+********************************************************************************/
void ExtFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
NaryBaseIterator<ExtFunctionCallIterator,
@@ -899,80 +947,72 @@
ExtFunctionCallIteratorState* state =
StateTraitsImpl<ExtFunctionCallIteratorState>::getState(planState,
theStateOffset);
+
+ initCache(planState, state);
+
ulong n = (ulong)theChildren.size();
state->m_extArgs.resize(n);
for(ulong i = 0; i < n; ++i)
{
state->m_extArgs[i] = new ExtFuncArgItemSequence(theChildren[i], planState);
- // the iterator does not have exlcusive ownership over the sequences
+ // the iterator does not have exclusive ownership over the sequences
state->m_extArgs[i]->addReference();
}
}
bool ExtFunctionCallIterator::count( store::Item_t &result,
PlanState &planState ) const {
- ItemSequence_t api_seq;
+ int64_t count = 0;
ExtFunctionCallIteratorState *state;
DEFAULT_STACK_INIT( ExtFunctionCallIteratorState, state, planState );
- try {
- if ( theFunction->isContextual() ) {
- ContextualExternalFunction const *const f =
- dynamic_cast<ContextualExternalFunction const*>( theFunction );
- ZORBA_ASSERT( f );
- StaticContextImpl sctx(
- theModuleSctx,
- planState.theQuery ?
- planState.theQuery->getRegisteredDiagnosticHandlerNoSync() :
- nullptr
- );
- DynamicContextImpl dctx(
- nullptr, planState.theGlobalDynCtx, theModuleSctx
- );
- api_seq = f->evaluate( state->m_extArgs, &sctx, &dctx );
- } else {
- NonContextualExternalFunction const *const f =
- dynamic_cast<NonContextualExternalFunction const*>( theFunction );
- ZORBA_ASSERT( f );
- api_seq = f->evaluate( state->m_extArgs );
- }
- if ( !!api_seq ) {
- Iterator_t api_iter( api_seq->getIterator() );
- api_iter->open();
- int64_t const count = api_iter->count();
- api_iter->close();
- GENV_ITEMFACTORY->createInteger( result, xs_integer( count ) );
+ try
+ {
+ evaluate(planState, state, state->m_extArgs);
+
+ if (!state->theResult.isNull())
+ {
+ count = state->theResultIter->count();
+ state->theResultIter->close();
}
}
- catch ( ZorbaException &e ) {
+ catch ( ZorbaException &e )
+ {
set_source( e, loc );
throw;
}
+ catch (std::exception const& e)
+ {
+ throw XQUERY_EXCEPTION(
+ zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR,
+ ERROR_PARAMS(e.what()),
+ ERROR_LOC(loc));
+ }
+
+ GENV_ITEMFACTORY->createInteger(result, xs_integer(count));
STACK_PUSH( true, state );
STACK_END( state );
}
-bool ExtFunctionCallIterator::skip(int64_t count, PlanState &planState) const
+bool ExtFunctionCallIterator::skip( int64_t count, PlanState &planState ) const
{
if (count == 0)
return true;
- ItemSequence_t api_seq;
- bool more_items;
+ bool more_items = false;
+
ExtFunctionCallIteratorState *state =
StateTraitsImpl<ExtFunctionCallIteratorState>::getState(planState, this->theStateOffset);
try
{
ZORBA_ASSERT(!state->theIsEvaluated);
- evaluate(state, planState);
+ evaluate(planState, state, state->m_extArgs);
- if ( !state->theResult.isNull() )
+ if (!state->theResult.isNull())
{
- state->theResultIter = state->theResult->getIterator();
- state->theResultIter->open();
- more_items = state->theResultIter->skip( count );
+ more_items = state->theResultIter->skip(count);
if (!more_items)
state->theResultIter->close();
}
@@ -992,103 +1032,252 @@
return more_items;
}
+/*******************************************************************************
+********************************************************************************/
bool ExtFunctionCallIterator::nextImpl(
- store::Item_t& result,
- PlanState& planState) const
+ store::Item_t& aResult,
+ PlanState& aPlanState) const
+{
+ try
+ {
+ if (isCached())
+ return nextImplCache(aResult, aPlanState);
+ else
+ return nextImplNoCache(aResult, aPlanState);
+ }
+ catch (ZorbaException& e)
+ {
+ set_source( e, loc );
+ throw;
+ }
+ catch (std::exception const& e)
+ {
+ throw XQUERY_EXCEPTION(
+ zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR,
+ ERROR_PARAMS(e.what()),
+ ERROR_LOC(loc));
+ }
+}
+
+
+/*******************************************************************************
+ ********************************************************************************/
+bool ExtFunctionCallIterator::nextImplCache(
+ store::Item_t& aResult,
+ PlanState& aPlanState) const
{
Item lOutsideItem;
-
- ExtFunctionCallIteratorState* state;
- DEFAULT_STACK_INIT(ExtFunctionCallIteratorState, state, planState);
-
- if (!state->theIsEvaluated)
+ std::vector<zorba::VectorItemSequence> lArgValues;
+ bool lCacheHit = false;
+ bool lSkipCache = false;
+ ExtFunctionCallIteratorState* lState;
+
+ DEFAULT_STACK_INIT(ExtFunctionCallIteratorState, lState, aPlanState);
+
+ if (!lState->theIsEvaluated)
{
try
{
- evaluate(state, planState);
-
- if (state->theResult.get() != NULL)
- {
- state->theResultIter = state->theResult->getIterator();
- state->theResultIter->open();
- }
- }
- catch (ZorbaException& e)
- {
- set_source( e, loc );
- throw;
- }
- catch (std::exception const& e)
- {
- throw XQUERY_EXCEPTION(
- zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR,
- ERROR_PARAMS(e.what()),
- ERROR_LOC(loc));
- }
- }
-
- if (!state->theResult.isNull() && //The external function returns zorba::ItemSequence_t(NULL)
- state->theResultIter->isOpen()) //The iterator has not been skipped past its end
- {
- while (true)
- {
- try
- {
- if (!state->theResultIter->next(lOutsideItem))
- {
- state->theResultIter->close();
- break;
- }
- }
- catch (XQueryException& e)
- {
- set_source( e, loc );
- throw;
- }
- catch (std::exception const& e)
- {
- throw XQUERY_EXCEPTION(
- zerr::ZXQP0001_DYNAMIC_RUNTIME_ERROR,
- ERROR_PARAMS(e.what()),
- ERROR_LOC(loc));
- }
-
- result = Unmarshaller::getInternalItem(lOutsideItem);
-
- if (theIsUpdating)
- {
- if (!result->isPul())
- throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc));
- }
- else
- {
- if (result->isPul())
- throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc));
- }
- STACK_PUSH(true, state);
- }
- }
- STACK_END (state);
-}
-
-void ExtFunctionCallIterator::evaluate(ExtFunctionCallIteratorState* state, PlanState& planState) const
-{
- if ( theFunction->isContextual() )
+ // check if the result is already in the cache
+ lCacheHit = probeCache(aPlanState, lState, lArgValues);
+ }
+ catch (ZorbaException& err)
+ {
+ lSkipCache = true;
+ }
+
+ if (lSkipCache)
+ {
+ //Pulling the argument iterators eagerly raised an error
+ //Disable automatic caching
+ //Try to evaluate the function as if no cache is present
+ theFunctionDef->disableAutomaticCaching();
+
+ for (unsigned int i=0; i< lState->m_extArgs.size(); ++i)
+ {
+ static_cast<ExtFuncArgItemSequence*>(lState->m_extArgs[i])->reset();
+ }
+
+ {
+ evaluate(aPlanState, lState, lState->m_extArgs);
+
+ if (!lState->theResult.isNull()) //The external function returns zorba::ItemSequence_t(NULL)
+ {
+ while (lState->theResultIter->next(lOutsideItem))
+ {
+ aResult = Unmarshaller::getInternalItem(lOutsideItem);
+
+ if (theIsUpdating && !aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc));
+ else if (!theIsUpdating && aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc));
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+
+ STACK_PUSH(true, lState);
+ }
+ lState->theResultIter->close();
+ }
+ }
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+ }
+ else
+ {
+ if (!lCacheHit) //The result is not in the cache, evaluate
+ {
+ std::vector<zorba::ItemSequence*> lArgs;
+ lArgs.resize(lArgValues.size());
+ for (unsigned int i = 0; i< lArgValues.size(); ++i)
+ lArgs[i] = (&lArgValues[i]);
+
+ evaluate(aPlanState, lState, lArgs);
+ }
+
+ if (!lCacheHit) //The result is not in the cache, iterate and save
+ {
+ if (lState->theResult.get() != NULL) //The external function returns zorba::ItemSequence_t(NULL)
+ {
+ while (lState->theResultIter->next(lOutsideItem))
+ {
+ aResult = Unmarshaller::getInternalItem(lOutsideItem);
+
+ if (theIsUpdating && !aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc));
+ else if (!theIsUpdating && aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc));
+
+ if (!aResult.isNull())
+ {
+ aResult->ensureSeekable();
+ lState->theCachedResult.push_back(aResult);
+ }
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+
+ STACK_PUSH(true, lState);
+ }
+ lState->theResultIter->close();
+
+ insertCacheEntry(aPlanState, lState, lState->theCachedResult);
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+ }
+ else //The result is zorba::ItemSequence_t(NULL)
+ {
+ insertCacheEntry(aPlanState, lState, lState->theCachedResult);
+ }
+ }
+ else //The result is in the cache
+ {
+ lState->theCachedResultIterator = lState->theCachedResult.begin();
+ while (lState->theCachedResultIterator != lState->theCachedResult.end())
+ {
+ aResult = *(lState->theCachedResultIterator++);
+ STACK_PUSH(true, lState);
+ }
+ }
+ }
+ }
+ else //The function has already been partly evaluated by skip, we cannot cache
+ //some items of the return iterator have already been consumed
+ {
+ if (!lState->theResult.isNull() && //The external function returns zorba::ItemSequence_t(NULL)
+ lState->theResultIter->isOpen()) //The iterator has not been skipped past its end
+ {
+ while (lState->theResultIter->next(lOutsideItem))
+ {
+ aResult = Unmarshaller::getInternalItem(lOutsideItem);
+
+ if (theIsUpdating && !aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc));
+ else if (!theIsUpdating && aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc));
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+
+ STACK_PUSH(true, lState);
+ }
+ lState->theResultIter->close();
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+ }
+
+
+ }
+ STACK_END(lState);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool ExtFunctionCallIterator::nextImplNoCache(
+ store::Item_t& aResult,
+ PlanState& aPlanState) const
+{
+ Item lOutsideItem;
+ ExtFunctionCallIteratorState* lState;
+
+ DEFAULT_STACK_INIT(ExtFunctionCallIteratorState, lState, aPlanState);
+
+ {
+ if (!lState->theIsEvaluated)
+ evaluate(aPlanState, lState, lState->m_extArgs);
+
+ if (!lState->theResult.isNull() && //The external function returns zorba::ItemSequence_t(NULL)
+ lState->theResultIter->isOpen()) //The iterator has not been skipped past its end
+ {
+ while (lState->theResultIter->next(lOutsideItem))
+ {
+ aResult = Unmarshaller::getInternalItem(lOutsideItem);
+
+ if (theIsUpdating && !aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0019, ERROR_LOC(loc));
+ else if (!theIsUpdating && aResult->isPul())
+ throw XQUERY_EXCEPTION(err::XUDY0018, ERROR_LOC(loc));
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+
+ STACK_PUSH(true, lState);
+ }
+ lState->theResultIter->close();
+ }
+ }
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+
+ STACK_END(lState);
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void ExtFunctionCallIterator::evaluate(PlanState& aPlanState, ExtFunctionCallIteratorState* aState, std::vector<zorba::ItemSequence*>& aArguments) const
+{
+ if (theFunction->isContextual())
{
ContextualExternalFunction const *const lFunction =
dynamic_cast<ContextualExternalFunction const*>( theFunction );
ZORBA_ASSERT( lFunction );
StaticContextImpl lSctx(theModuleSctx,
- planState.theQuery ?
- planState.theQuery->getRegisteredDiagnosticHandlerNoSync():
+ aPlanState.theQuery ?
+ aPlanState.theQuery->getRegisteredDiagnosticHandlerNoSync():
nullptr);
DynamicContextImpl lDctx(nullptr,
- planState.theGlobalDynCtx,
- theModuleSctx);
+ aPlanState.theGlobalDynCtx,
+ theModuleSctx);
- state->theResult = lFunction->evaluate( state->m_extArgs, &lSctx, &lDctx );
+ aState->theResult = lFunction->evaluate(aArguments, &lSctx, &lDctx);
}
else
{
@@ -1096,13 +1285,115 @@
dynamic_cast<NonContextualExternalFunction const*>( theFunction );
ZORBA_ASSERT( lFunction );
- state->theResult = lFunction->evaluate( state->m_extArgs );
- }
- state->theIsEvaluated = true;
+ aState->theResult = lFunction->evaluate( aArguments );
+ }
+
+ aState->theIsEvaluated = true;
+ if (!aState->theResult.isNull())
+ {
+ aState->theResultIter = aState->theResult->getIterator();
+ aState->theResultIter->open();
+ }
+
+ if (isSequential())
+ aPlanState.theGlobalDynCtx->changeSnapshot();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool ExtFunctionCallIterator::isCached() const
+{
+ return theFunctionDef->cacheResults();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool ExtFunctionCallIterator::isCacheAcrossSnapshots() const
+{
+ return theFunctionDef->cacheAcrossSnapshots();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void ExtFunctionCallIterator::initCache(
+ PlanState& aPlanState,
+ ExtFunctionCallIteratorState* aState)
+{
+ if (!aState->theCache && isCached())
+ {
+ aState->theCache = theFunctionDef->getCache();
+ }
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool ExtFunctionCallIterator::probeCache(
+ PlanState& aPlanState,
+ ExtFunctionCallIteratorState* aState,
+ std::vector<zorba::VectorItemSequence>& aArguments) const
+{
+ assert(aState->theCache);
+
+ std::vector<store::Item_t> probeKeys;
+ for (unsigned int i=0; i< aState->m_extArgs.size(); ++i)
+ {
+ zorba::ItemSequence* lArgWrapper = aState->m_extArgs[i];
+ zorba::Iterator_t lIterator = lArgWrapper->getIterator();
+ std::vector<zorba::Item> lArgSeq;
+ std::vector<store::Item_t> lIntArgSeq;
+
+ zorba::Item lArgItem;
+ store::Item_t lIntArgItem;
+ lIterator->open();
+ while (lIterator->next(lArgItem))
+ {
+ lIntArgItem = Unmarshaller::getInternalItem(lArgItem);
+ lIntArgItem->ensureSeekable();
+
+ lArgSeq.push_back(lArgItem);
+ lIntArgSeq.push_back(lIntArgItem);
+ }
+ lIterator->close();
+
+ aArguments.push_back(zorba::VectorItemSequence(lArgSeq));
+ probeKeys.push_back(new simplestore::ItemVector(lIntArgSeq));
+ }
+
+ aState->theCacheKey = store::Item_t(new simplestore::ItemVector(probeKeys));
+ if (!isCacheAcrossSnapshots())
+ aState->theCacheKeySnapshot = aPlanState.theGlobalDynCtx->getSnapshotID();
+
+ FunctionCache::iterator lIt = aState->theCache->find(aState->theCacheKey, aPlanState);
+ if (lIt == aState->theCache->end())
+ {
+ aState->theCachedResult.clear();
+ return false;
+ }
+
+ aState->theCachedResult = lIt.getValue();
+ return true;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void ExtFunctionCallIterator::insertCacheEntry(
+ PlanState& aPlanState,
+ ExtFunctionCallIteratorState* aState,
+ std::vector<store::Item_t>& aResult) const
+{
+ assert(aState->theCache);
+ if (isCacheAcrossSnapshots() || aState->theCacheKeySnapshot == aPlanState.theGlobalDynCtx->getSnapshotID())
+ {
+ aState->theCache->insert(aState->theCacheKey, aResult, aPlanState);
+ }
}
NARY_ACCEPT(ExtFunctionCallIterator);
-
} // namespace zorba
/* vim:set et sw=2 ts=2: */
=== modified file 'src/runtime/core/fncall_iterator.h'
--- src/runtime/core/fncall_iterator.h 2014-04-15 19:35:58 +0000
+++ src/runtime/core/fncall_iterator.h 2014-04-17 12:18:12 +0000
@@ -28,11 +28,15 @@
#include "context/static_context.h"
-
namespace zorba {
class StaticContextImpl;
+class external_function;
+
+class VectorItemSequence;
+
+class FunctionCache;
/*******************************************************************************
@@ -93,21 +97,25 @@
class UDFunctionCallIteratorState : public PlanIteratorState
{
public:
- dynamic_context * theLocalDCtx;
- bool theIsLocalDCtxOwner;
-
- PlanIter_t thePlan;
- PlanState * thePlanState;
- bool thePlanOpen;
- uint32_t thePlanStateSize;
-
- std::vector<store::Iterator_t> theArgWrappers;
-
- store::Index * theCache;
- store::IndexKey * theCacheKey;
- store::IndexCondition_t theCacheCond;
- store::IndexProbeIterator_t theCacheProbeIte;
- std::vector<SingleItemIterator_t> theArgValues;
+ dynamic_context* theLocalDCtx;
+ bool theIsLocalDCtxOwner;
+
+ PlanIter_t thePlan;
+ PlanState* thePlanState;
+ bool thePlanOpen;
+ uint32_t thePlanStateSize;
+
+ std::vector<ItemIterator_t> theArgValues;
+ std::vector<store::Iterator_t> theArgWrappers;
+
+ FunctionCache* theCache;
+
+ store::Item_t theCacheKey;
+ uint64_t theCacheKeySnapshot;
+
+ store::Item_t theNextResult;
+ std::vector<store::Item_t> theCachedResult;
+ std::vector<store::Item_t>::const_iterator theCachedResultIterator;
UDFunctionCallIteratorState();
@@ -178,6 +186,8 @@
bool isCached() const;
+ bool isCacheAcrossSnapshots() const;
+
void accept(PlanIterVisitor& v) const;
void openImpl(PlanState& planState, uint32_t& offset);
@@ -186,23 +196,29 @@
void closeImpl(PlanState& planState);
- bool nextImpl(store::Item_t& result, PlanState& planState) const;
+ bool nextImpl(store::Item_t& aResult, PlanState& aPlanState) const;
+
+private:
+ bool nextImplCache(store::Item_t& aResult, PlanState& aPlanState) const;
+
+ bool nextImplNoCache(store::Item_t& aResult, PlanState& aPlanState) const;
+
+ void bindArguments(UDFunctionCallIteratorState* aState, bool aReset) const;
protected:
- void createCache(
- PlanState& planState,
- UDFunctionCallIteratorState* state);
+ void initCache(
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState);
bool probeCache(
- PlanState& planState,
- UDFunctionCallIteratorState* state,
- store::Item_t& result,
- std::vector<store::Item_t>& argValues) const;
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState,
+ std::vector< std::vector <store::Item_t> >& aArguments) const;
void insertCacheEntry(
- UDFunctionCallIteratorState* state,
- std::vector<store::Item_t>& argValues,
- const store::Item_t& udfResult) const;
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState,
+ std::vector<store::Item_t>& aResult) const;
};
@@ -217,6 +233,14 @@
Iterator_t theResultIter;
bool theIsEvaluated;
+ FunctionCache* theCache;
+
+ zorba::store::Item_t theCacheKey;
+ uint64_t theCacheKeySnapshot;
+
+ std::vector<store::Item_t> theCachedResult;
+ std::vector<store::Item_t>::const_iterator theCachedResultIterator;
+
ExtFunctionCallIteratorState();
~ExtFunctionCallIteratorState();
@@ -229,8 +253,10 @@
ExtFunctionCallIteratorState>
{
protected:
+ external_function * theFunctionDef;
const ExternalFunction * theFunction;
bool theIsUpdating;
+ bool theIsSequential;
zstring theNamespace;
static_context * theModuleSctx;
@@ -248,8 +274,10 @@
static_context* sctx,
const QueryLoc& loc,
std::vector<PlanIter_t>& args,
+ const external_function* functionDef,
const ExternalFunction* function,
bool isUpdating,
+ bool isSequential,
const zstring& ns,
static_context* moduleSctx);
@@ -259,18 +287,42 @@
virtual bool isUpdating() const { return theIsUpdating; }
+ virtual bool isSequential() const { return theIsSequential; }
+
void accept(PlanIterVisitor& v) const;
void openImpl(PlanState& planState, uint32_t& offset);
- bool nextImpl(store::Item_t& result, PlanState& planState) const;
-
bool count(store::Item_t& result, PlanState& planState) const;
bool skip(int64_t count, PlanState &planState) const;
-private:
- void evaluate(ExtFunctionCallIteratorState* state, PlanState& planState) const;
+ bool nextImpl(store::Item_t& aResult, PlanState& aPlanState) const;
+
+ bool nextImplCache(store::Item_t& aResult, PlanState& aPlanState) const;
+
+ bool nextImplNoCache(store::Item_t& aResult, PlanState& aPlanState) const;
+
+ void evaluate(PlanState& aPlanState, ExtFunctionCallIteratorState* aState, std::vector<zorba::ItemSequence*>& aArguments) const;
+
+ bool isCached() const;
+
+ bool isCacheAcrossSnapshots() const;
+
+protected:
+ void initCache(
+ PlanState& aPlanState,
+ ExtFunctionCallIteratorState* aState);
+
+ bool probeCache(
+ PlanState& aPlanState,
+ ExtFunctionCallIteratorState* aState,
+ std::vector<zorba::VectorItemSequence>& aArguments) const;
+
+ void insertCacheEntry(
+ PlanState& aPlanState,
+ ExtFunctionCallIteratorState* aState,
+ std::vector<store::Item_t>& aResult) const;
};
}
=== modified file 'src/runtime/core/var_iterators.cpp'
--- src/runtime/core/var_iterators.cpp 2014-02-12 02:25:45 +0000
+++ src/runtime/core/var_iterators.cpp 2014-04-17 12:18:12 +0000
@@ -201,6 +201,8 @@
planState.theGlobalDynCtx->set_variable(theVarId, theVarName, loc, planIter);
}
+ planState.theGlobalDynCtx->changeSnapshot();
+
STACK_END (state);
}
=== added directory 'src/runtime/dctx'
=== added file 'src/runtime/dctx/dctx_impl.cpp'
--- src/runtime/dctx/dctx_impl.cpp 1970-01-01 00:00:00 +0000
+++ src/runtime/dctx/dctx_impl.cpp 2014-04-17 12:18:12 +0000
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "stdafx.h"
+
+#include "runtime/dctx/dctx.h"
+
+#include "system/globalenv.h"
+
+#include "runtime/visitors/planiter_visitor.h"
+
+#include "context/dynamic_context.h"
+#include "context/static_context.h"
+
+#include "store/api/item_factory.h"
+#include "zorbatypes/integer.h"
+
+
+namespace zorba
+{
+bool
+DctxSnapshotIdIterator::nextImpl(store::Item_t& result, PlanState& planState) const
+{
+ PlanIteratorState *state;
+ DEFAULT_STACK_INIT( PlanIteratorState, state, planState );
+ GENV_ITEMFACTORY->createUnsignedLong( result, xs_unsignedLong(planState.theGlobalDynCtx->getSnapshotID()) );
+ STACK_PUSH( true, state );
+ STACK_END( state );
+}
+
+}/* namespace zorba */
+/* vim:set et sw=2 ts=2: */
=== added directory 'src/runtime/dctx/pregenerated'
=== added file 'src/runtime/dctx/pregenerated/dctx.cpp'
--- src/runtime/dctx/pregenerated/dctx.cpp 1970-01-01 00:00:00 +0000
+++ src/runtime/dctx/pregenerated/dctx.cpp 2014-04-17 12:18:12 +0000
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ******************************************
+// * *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME *
+// * *
+// ******************************************
+
+
+#include "stdafx.h"
+#include "zorbatypes/rchandle.h"
+#include "zorbatypes/zstring.h"
+#include "runtime/visitors/planiter_visitor.h"
+#include "runtime/dctx/dctx.h"
+#include "system/globalenv.h"
+
+
+
+namespace zorba {
+
+// <DctxSnapshotIdIterator>
+SERIALIZABLE_CLASS_VERSIONS(DctxSnapshotIdIterator)
+
+void DctxSnapshotIdIterator::serialize(::zorba::serialization::Archiver& ar)
+{
+ serialize_baseclass(ar,
+ (NaryBaseIterator<DctxSnapshotIdIterator, PlanIteratorState>*)this);
+}
+
+
+void DctxSnapshotIdIterator::accept(PlanIterVisitor& v) const
+{
+ v.beginVisit(*this);
+
+ std::vector<PlanIter_t>::const_iterator lIter = theChildren.begin();
+ std::vector<PlanIter_t>::const_iterator lEnd = theChildren.end();
+ for ( ; lIter != lEnd; ++lIter ){
+ (*lIter)->accept(v);
+ }
+
+ v.endVisit(*this);
+}
+
+DctxSnapshotIdIterator::~DctxSnapshotIdIterator() {}
+
+
+zstring DctxSnapshotIdIterator::getNameAsString() const {
+ return "fn-zorba-dctx:snapshot-id";
+}
+// </DctxSnapshotIdIterator>
+
+
+
+}
+
+
=== added file 'src/runtime/dctx/pregenerated/dctx.h'
--- src/runtime/dctx/pregenerated/dctx.h 1970-01-01 00:00:00 +0000
+++ src/runtime/dctx/pregenerated/dctx.h 2014-04-17 12:18:12 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2006-2012 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ******************************************
+// * *
+// * THIS IS A GENERATED FILE. DO NOT EDIT! *
+// * SEE .xml FILE WITH SAME NAME *
+// * *
+// ******************************************
+
+#ifndef ZORBA_RUNTIME_DCTX_DCTX_H
+#define ZORBA_RUNTIME_DCTX_DCTX_H
+
+
+#include "common/shared_types.h"
+
+
+
+#include "runtime/base/narybase.h"
+
+
+namespace zorba {
+
+/**
+ *
+ * Author:
+ */
+class DctxSnapshotIdIterator : public NaryBaseIterator<DctxSnapshotIdIterator, PlanIteratorState>
+{
+public:
+ SERIALIZABLE_CLASS(DctxSnapshotIdIterator);
+
+ SERIALIZABLE_CLASS_CONSTRUCTOR2T(DctxSnapshotIdIterator,
+ NaryBaseIterator<DctxSnapshotIdIterator, PlanIteratorState>);
+
+ void serialize( ::zorba::serialization::Archiver& ar);
+
+ DctxSnapshotIdIterator(
+ static_context* sctx,
+ const QueryLoc& loc,
+ std::vector<PlanIter_t>& children)
+ :
+ NaryBaseIterator<DctxSnapshotIdIterator, PlanIteratorState>(sctx, loc, children)
+ {}
+
+ virtual ~DctxSnapshotIdIterator();
+
+ zstring getNameAsString() const;
+
+ void accept(PlanIterVisitor& v) const;
+
+ bool nextImpl(store::Item_t& result, PlanState& aPlanState) const;
+};
+
+
+}
+#endif
+/*
+ * Local variables:
+ * mode: c++
+ * End:
+ */
=== modified file 'src/runtime/pregenerated/iterator_enum.h'
--- src/runtime/pregenerated/iterator_enum.h 2014-01-31 21:47:54 +0000
+++ src/runtime/pregenerated/iterator_enum.h 2014-04-17 12:18:12 +0000
@@ -84,6 +84,7 @@
TYPE_ParseTime,
TYPE_Timestamp,
TYPE_UTCOffset,
+ TYPE_DctxSnapshotIdIterator,
TYPE_DebugIterator,
TYPE_YearsFromDurationIterator,
TYPE_MonthsFromDurationIterator,
=== modified file 'src/runtime/scripting/scripting.cpp'
--- src/runtime/scripting/scripting.cpp 2014-02-12 02:25:45 +0000
+++ src/runtime/scripting/scripting.cpp 2014-04-17 12:18:12 +0000
@@ -25,6 +25,8 @@
#include "store/api/item_factory.h"
#include "store/api/copymode.h"
+#include "context/dynamic_context.h"
+
#include "system/globalenv.h"
#include "diagnostics/util_macros.h"
@@ -306,6 +308,8 @@
}
}
+ planState.theGlobalDynCtx->changeSnapshot();
+
STACK_END(state);
}
=== added directory 'src/runtime/spec/dctx'
=== added file 'src/runtime/spec/dctx/dctx.xml'
--- src/runtime/spec/dctx/dctx.xml 1970-01-01 00:00:00 +0000
+++ src/runtime/spec/dctx/dctx.xml 2014-04-17 12:18:12 +0000
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<zorba:iterators
+ xmlns:zorba="http://www.zorba-xquery.com"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.zorba-xquery.com ../runtime.xsd">
+
+<!--========================================================================-->
+
+<zorba:iterator name="DctxSnapshotIdIterator">
+ <zorba:function>
+ <zorba:signature localname="snapshot-id"
+ prefix="fn-zorba-dctx">
+ <zorba:output>xs:unsignedLong</zorba:output>
+ </zorba:signature>
+ <zorba:methods>
+ <zorba:accessesDynCtx returnValue="true"/>
+ </zorba:methods>
+ </zorba:function>
+</zorba:iterator>
+
+<!--========================================================================-->
+
+</zorba:iterators>
=== modified file 'src/runtime/spec/mappings.xml'
--- src/runtime/spec/mappings.xml 2013-11-22 01:03:46 +0000
+++ src/runtime/spec/mappings.xml 2014-04-17 12:18:12 +0000
@@ -97,6 +97,9 @@
<zorba:namespace uri="http://zorba.io/modules/sctx"
define="ZORBA_SCTX_FN_NS"
prefix="fn-zorba-sctx"/>
+ <zorba:namespace uri="http://zorba.io/modules/dctx"
+ define="ZORBA_DCTX_FN_NS"
+ prefix="fn-zorba-dctx"/>
<zorba:namespace uri="http://zorba.io/modules/reflection"
define="ZORBA_REFLECTION_FN_NS"
@@ -129,7 +132,7 @@
<zorba:namespace uri="http://zorba.io/modules/fetch"
define="ZORBA_FETCH_FN_NS"
prefix="fn-zorba-fetch"/>
-
+
<zorba:namespace uri="http://zorba.io/modules/node"
define="ZORBA_NODE_FN_NS"
prefix="fn-zorba-node"/>
=== modified file 'src/runtime/update/update.cpp'
--- src/runtime/update/update.cpp 2014-02-12 02:25:45 +0000
+++ src/runtime/update/update.cpp 2014-04-17 12:18:12 +0000
@@ -835,7 +835,7 @@
PlanIteratorState* aState;
DEFAULT_STACK_INIT(PlanIteratorState, aState, aPlanState);
- pul = GENV_ITEMFACTORY->createPendingUpdateList();
+ pul = GENV_ITEMFACTORY->createPendingUpdateList(true);
typePreserve = (theSctx->construction_mode() == StaticContextConsts::cons_preserve ?
true : false);
=== modified file 'src/runtime/util/item_iterator.cpp'
--- src/runtime/util/item_iterator.cpp 2013-06-15 07:01:57 +0000
+++ src/runtime/util/item_iterator.cpp 2014-04-17 12:18:12 +0000
@@ -27,13 +27,13 @@
}
-ItemIterator::ItemIterator(store::Item_t aItem)
+ItemIterator::ItemIterator(store::Item_t aItem)
{
theItems.push_back(aItem);
}
-ItemIterator::ItemIterator()
+ItemIterator::ItemIterator()
{
}
@@ -44,6 +44,12 @@
theIterator = theItems.begin();
}
+void ItemIterator::init(const std::vector<store::Item_t>& aItems)
+{
+ theItems = aItems;
+ reset();
+}
+
bool
ItemIterator::next(store::Item_t& result)
=== modified file 'src/runtime/util/item_iterator.h'
--- src/runtime/util/item_iterator.h 2013-06-15 07:01:57 +0000
+++ src/runtime/util/item_iterator.h 2014-04-17 12:18:12 +0000
@@ -37,6 +37,7 @@
virtual ~ItemIterator(){}
+ virtual void init(const std::vector<store::Item_t>& aItems);
virtual void open();
virtual bool next(store::Item_t&);
virtual void reset();
=== modified file 'src/runtime/visitors/pregenerated/planiter_visitor.h'
--- src/runtime/visitors/pregenerated/planiter_visitor.h 2014-01-31 21:47:54 +0000
+++ src/runtime/visitors/pregenerated/planiter_visitor.h 2014-04-17 12:18:12 +0000
@@ -157,6 +157,8 @@
class UTCOffset;
+ class DctxSnapshotIdIterator;
+
#ifdef ZORBA_WITH_DEBUGGER
class DebugIterator;
#endif
@@ -966,6 +968,9 @@
virtual void beginVisit ( const UTCOffset& ) = 0;
virtual void endVisit ( const UTCOffset& ) = 0;
+ virtual void beginVisit ( const DctxSnapshotIdIterator& ) = 0;
+ virtual void endVisit ( const DctxSnapshotIdIterator& ) = 0;
+
#ifdef ZORBA_WITH_DEBUGGER
virtual void beginVisit ( const DebugIterator& ) = 0;
virtual void endVisit ( const DebugIterator& ) = 0;
=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.cpp'
--- src/runtime/visitors/pregenerated/printer_visitor.cpp 2014-02-14 02:53:24 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.cpp 2014-04-17 12:18:12 +0000
@@ -44,6 +44,7 @@
#include "runtime/context/context.h"
#include "runtime/csv/csv.h"
#include "runtime/datetime/datetime.h"
+#include "runtime/dctx/dctx.h"
#include "runtime/debug/debug_iterator.h"
#include "runtime/durations_dates_times/durations_dates_times.h"
#include "runtime/errors_and_diagnostics/errors_and_diagnostics.h"
@@ -821,6 +822,20 @@
}
// </UTCOffset>
+
+// <DctxSnapshotIdIterator>
+void PrinterVisitor::beginVisit( const DctxSnapshotIdIterator& a) {
+ thePrinter.startBeginVisit("DctxSnapshotIdIterator", ++theId);
+ printCommons( &a, theId );
+ thePrinter.endBeginVisit( theId );
+}
+
+void PrinterVisitor::endVisit( const DctxSnapshotIdIterator& ) {
+ thePrinter.startEndVisit();
+ thePrinter.endEndVisit();
+}
+// </DctxSnapshotIdIterator>
+
#ifdef ZORBA_WITH_DEBUGGER
// <DebugIterator>
void PrinterVisitor::beginVisit( const DebugIterator& a) {
=== modified file 'src/runtime/visitors/pregenerated/printer_visitor.h'
--- src/runtime/visitors/pregenerated/printer_visitor.h 2014-02-18 03:40:00 +0000
+++ src/runtime/visitors/pregenerated/printer_visitor.h 2014-04-17 12:18:12 +0000
@@ -242,6 +242,9 @@
void beginVisit( const UTCOffset& );
void endVisit ( const UTCOffset& );
+ void beginVisit( const DctxSnapshotIdIterator& );
+ void endVisit ( const DctxSnapshotIdIterator& );
+
#ifdef ZORBA_WITH_DEBUGGER
void beginVisit( const DebugIterator& );
void endVisit ( const DebugIterator& );
=== modified file 'src/runtime/visitors/printer_visitor_impl.cpp'
--- src/runtime/visitors/printer_visitor_impl.cpp 2014-02-27 18:36:37 +0000
+++ src/runtime/visitors/printer_visitor_impl.cpp 2014-04-17 12:18:12 +0000
@@ -189,7 +189,6 @@
DEF_VISIT( EvalIterator )
DEF_VISIT( ExitCatcherIterator )
DEF_VISIT( ExitIterator )
-DEF_VISIT( ExtFunctionCallIterator )
DEF_VISIT( FlowCtlIterator )
DEF_VISIT( FnAdjustToTimeZoneIterator_1 )
DEF_VISIT( FnAdjustToTimeZoneIterator_2 )
@@ -568,10 +567,14 @@
void PrinterVisitor::beginVisit( UDFunctionCallIterator const &i ) {
thePrinter.startBeginVisit( "UDFunctionCallIterator", ++theId );
if ( i.isCached() )
- thePrinter.addAttribute( "cached", "true" );
- store::Item const *const name = i.theUDF->getSignature().getName();
- if ( name )
- thePrinter.addAttribute( "function", name->getStringValue().str() );
+ {
+ if (i.isCacheAcrossSnapshots())
+ thePrinter.addAttribute("cached-across-snapshots", "true");
+ else
+ thePrinter.addAttribute("cached", "true");
+ }
+ if ( i.theUDF->getSignature().getName() )
+ thePrinter.addAttribute( "function", i.theUDF->getSignature().getName()->getStringValue().str() );
else
thePrinter.addAttribute( "function", "inline function" );
printCommons( &i, theId );
@@ -579,6 +582,20 @@
}
DEF_END_VISIT( UDFunctionCallIterator )
+void PrinterVisitor::beginVisit( ExtFunctionCallIterator const &i ) {
+ thePrinter.startBeginVisit( "ExtFunctionCallIterator", ++theId );
+ if ( i.isCached() )
+ {
+ if (i.isCacheAcrossSnapshots())
+ thePrinter.addAttribute("cached-across-snapshots", "true");
+ else
+ thePrinter.addAttribute("cached", "true");
+ }
+ printCommons( &i, theId );
+ thePrinter.endBeginVisit( theId );
+}
+DEF_END_VISIT( ExtFunctionCallIterator )
+
////////// really special cases ///////////////////////////////////////////////
template<class T>
=== modified file 'src/store/api/item.h'
--- src/store/api/item.h 2013-08-05 11:54:06 +0000
+++ src/store/api/item.h 2014-04-17 12:18:12 +0000
@@ -975,6 +975,11 @@
*/
virtual bool isSeekable() const;
+ /*
+ * Ensures that the underlying stream is seekable.
+ */
+ virtual void ensureSeekable();
+
/**
* Gets an istream for the item's content.
*
=== modified file 'src/store/api/item_factory.h'
--- src/store/api/item_factory.h 2013-06-18 23:53:59 +0000
+++ src/store/api/item_factory.h 2014-04-17 12:18:12 +0000
@@ -786,7 +786,7 @@
/**
* Create a pending updates list.
*/
- virtual PUL* createPendingUpdateList() = 0;
+ virtual PUL* createPendingUpdateList(bool isTransform = false) = 0;
/**
* Create an ErrorItem encapsulating a pointer to a ZorbaException obj (or to
=== modified file 'src/store/api/pul.h'
--- src/store/api/pul.h 2013-06-15 02:57:08 +0000
+++ src/store/api/pul.h 2014-04-17 12:18:12 +0000
@@ -363,6 +363,8 @@
virtual store::SchemaValidator* getValidator() const = 0;
virtual void setICChecker(ICChecker* icChecker) = 0;
+
+ virtual bool isTransform() = 0;
};
=== modified file 'src/store/naive/atomic_items.cpp'
--- src/store/naive/atomic_items.cpp 2013-10-10 03:54:10 +0000
+++ src/store/naive/atomic_items.cpp 2014-04-17 12:18:12 +0000
@@ -882,6 +882,10 @@
theQName = qname;
}
+uint32_t NotationItem::hash(long timezone, const XQPCollator* aCollation) const
+{
+ return theQName->hash(timezone, aCollation);
+}
bool NotationItem::equals(
const store::Item* item,
@@ -1996,7 +2000,7 @@
bool seekable)
:
StringItem(t),
- theIstream(aStream),
+ theIstream(&aStream),
theIsMaterialized(false),
theIsConsumed(false),
theIsSeekable(seekable),
@@ -2010,7 +2014,7 @@
store::Item_t& aStreamableDependent)
:
StringItem(t),
- theIstream(aStreamableDependent->getStream()),
+ theIstream(&aStreamableDependent->getStream()),
theIsMaterialized(false),
theIsConsumed(false),
theIsSeekable(aStreamableDependent->isSeekable()),
@@ -2146,6 +2150,31 @@
return theIsSeekable;
}
+void StreamableStringItem::ensureSeekable()
+{
+ if (!theIsMaterialized && !theIsSeekable && theIsConsumed)
+ {
+ // a non-seekable stream can only be consumed once
+ // we raise an error if getStream is called twice
+ // if a query requires a stream to be consumed more than once,
+ // the query needs to make sure that the stream is explicitly
+ // materialized before
+ throw ZORBA_EXCEPTION( zerr::ZSTR0055_STREAMABLE_STRING_CONSUMED );
+ }
+ else if (!theIsMaterialized && !theIsSeekable)
+ {
+ std::stringstream* lStringStream = new std::stringstream();
+ (*lStringStream) << theIstream->rdbuf();
+ if (theStreamReleaser)
+ theStreamReleaser(theIstream);
+ if (!theStreamableDependent.isNull())
+ theStreamableDependent = nullptr;
+ theIstream = lStringStream;
+ theStreamReleaser = StreamableStringItem::streamReleaser;
+ theIsSeekable = true;
+ theIsConsumed = false;
+ }
+}
std::istream& StreamableStringItem::getStream()
{
@@ -2164,12 +2193,12 @@
// We are not using theIstream.seekg because the USER_ERROR that is thrown
// by Zorba is lost possibly in an internal try/catch of the seekg
std::streambuf * pbuf;
- pbuf = theIstream.rdbuf();
+ pbuf = theIstream->rdbuf();
pbuf->pubseekoff(0, std::ios::beg);
- theIstream.clear();
+ theIstream->clear();
}
theIsConsumed = true;
- return theIstream;
+ return *theIstream;
}
@@ -2194,7 +2223,7 @@
lSsi->theIsConsumed = true;
char lBuf[4096];
- while (theIstream)
+ while (!theIstream->fail())
{
lStream.read(lBuf, sizeof(lBuf));
lSsi->theValue.append(lBuf, static_cast<unsigned int>(lStream.gcount()));
@@ -3540,7 +3569,7 @@
/*******************************************************************************
- class StreamableStringItem
+ class StreamableBase64BinaryItem
********************************************************************************/
zstring StreamableBase64BinaryItem::getStringValue() const
{
@@ -3595,6 +3624,18 @@
return Base64BinaryItem::hash(timezone, aCollation);
}
+bool
+StreamableBase64BinaryItem::equals(store::Item const* aItem, long aTimezone,
+ XQPCollator const* aCollator) const
+{
+ if (!theIsMaterialized)
+ {
+ materialize();
+ }
+ return Base64BinaryItem::equals(aItem, aTimezone, aCollator);
+}
+
+
const char*
StreamableBase64BinaryItem::getBase64BinaryValue(size_t& s) const
@@ -3618,6 +3659,39 @@
return theIsSeekable;
}
+void StreamableBase64BinaryItem::ensureSeekable()
+{
+ if (!theIsMaterialized && !theIsSeekable && theIsConsumed)
+ {
+ // a non-seekable stream can only be consumed once
+ // we raise an error if getStream is called twice
+ // if a query requires a stream to be consumed more than once,
+ // the query needs to make sure that the stream is explicitly
+ // materialized before
+ throw ZORBA_EXCEPTION( zerr::ZSTR0055_STREAMABLE_STRING_CONSUMED );
+ }
+ else if (!theIsMaterialized && !theIsSeekable)
+ {
+ std::stringstream* lStringStream = new std::stringstream();
+ std::streambuf * pbuf;
+ pbuf = theIstream->rdbuf();
+ pbuf->pubseekoff(0, std::ios::beg);
+ theIstream->clear();
+
+ (*lStringStream) << pbuf;
+ if (theStreamReleaser)
+ theStreamReleaser(theIstream);
+ theIstream = lStringStream;
+ theStreamReleaser = StreamableBase64BinaryItem::streamReleaser;
+ theIsSeekable = true;
+ theIsConsumed = false;
+ }
+ else if (!theIsMaterialized)
+ {
+ materialize();
+ }
+}
+
StreamReleaser StreamableBase64BinaryItem::getStreamReleaser()
{
@@ -3648,12 +3722,12 @@
// We are not using theIstream.seekg because the USER_ERROR that is thrown
// by Zorba is lost possibly in an internal try/catch of the seekg
std::streambuf * pbuf;
- pbuf = theIstream.rdbuf();
+ pbuf = theIstream->rdbuf();
pbuf->pubseekoff(0, std::ios::beg);
- theIstream.clear();
+ theIstream->clear();
}
theIsConsumed = true;
- return theIstream;
+ return *theIstream;
}
@@ -3662,6 +3736,7 @@
StreamableBase64BinaryItem* const s
= const_cast<StreamableBase64BinaryItem*>(this);
std::istream& lStream = s->getStream();
+ lStream.clear();
s->theIsMaterialized = true;
s->theIsConsumed = true;
=== modified file 'src/store/naive/atomic_items.h'
--- src/store/naive/atomic_items.h 2013-06-26 10:59:37 +0000
+++ src/store/naive/atomic_items.h 2014-04-17 12:18:12 +0000
@@ -570,6 +570,8 @@
store::Item* getType() const;
+ uint32_t hash(long timezone = 0, const XQPCollator* aCollation = 0) const;
+
bool equals(
const store::Item* item,
long timezone = 0,
@@ -943,7 +945,7 @@
friend class BasicItemFactory;
protected:
- std::istream & theIstream;
+ std::istream * theIstream;
bool theIsMaterialized;
bool theIsConsumed;
@@ -982,6 +984,8 @@
bool isSeekable() const;
+ void ensureSeekable();
+
std::istream& getStream();
StreamReleaser getStreamReleaser();
@@ -992,7 +996,7 @@
{
if (theStreamReleaser)
{
- theStreamReleaser(&theIstream);
+ theStreamReleaser(theIstream);
}
}
@@ -1011,6 +1015,10 @@
store::Item_t& streamableDependent);
void materialize() const;
+
+private:
+ static void streamReleaser(std::istream* aStream) { delete aStream;}
+
};
@@ -2370,7 +2378,7 @@
friend class BasicItemFactory;
protected:
- std::istream & theIstream;
+ std::istream * theIstream;
bool theIsMaterialized;
bool theIsConsumed;
@@ -2387,7 +2395,7 @@
bool is_encoded = false)
:
Base64BinaryItem(t, is_encoded),
- theIstream(aStream),
+ theIstream(&aStream),
theIsMaterialized(false),
theIsConsumed(false),
theIsSeekable(seekable),
@@ -2402,7 +2410,7 @@
{
if (theStreamReleaser)
{
- theStreamReleaser(&theIstream);
+ theStreamReleaser(theIstream);
}
}
@@ -2410,6 +2418,8 @@
bool isSeekable() const;
+ void ensureSeekable();
+
std::istream& getStream();
StreamReleaser getStreamReleaser();
@@ -2420,6 +2430,9 @@
uint32_t hash(long timezone = 0, const XQPCollator* aCollation = 0) const;
+ bool equals(store::Item const *, long timezone = 0,
+ XQPCollator const* = 0) const;
+
zstring getStringValue() const;
void getStringValue2(zstring& val) const;
@@ -2427,6 +2440,9 @@
void appendStringValue(zstring& buf) const;
zstring show() const;
+
+private:
+ static void streamReleaser(std::istream* aStream) { delete aStream;}
};
=== modified file 'src/store/naive/hashmap_nodep.h'
--- src/store/naive/hashmap_nodep.h 2013-02-07 17:24:36 +0000
+++ src/store/naive/hashmap_nodep.h 2014-04-17 12:18:12 +0000
@@ -29,7 +29,7 @@
/***************************************************************************//**
- Class to privide the equality and hash functions for the NodePointerHashMap
+ Class to provide the equality and hash functions for the NodePointerHashMap
class defined below.
*******************************************************************************/
class NodePointerHashMapCmp
@@ -66,7 +66,7 @@
/***************************************************************************//**
- Class to privide the equality and hash functions for the NodePointerHashMap
+ Class to provide the equality and hash functions for the ItemPointerHashMap
class defined below.
*******************************************************************************/
class ItemPointerHashMapCmp
=== modified file 'src/store/naive/item.cpp'
--- src/store/naive/item.cpp 2013-08-05 11:54:06 +0000
+++ src/store/naive/item.cpp 2014-04-17 12:18:12 +0000
@@ -379,7 +379,7 @@
throw ZORBA_EXCEPTION(
zerr::ZSTR0040_TYPE_ERROR,
ERROR_PARAMS(
- ZED( OperationNotDef_23 ), ZED( EffectiveBooleanValue ),
+ ZED( OperationNotDef_23 ), ZED( AppendStringValue ),
getType()->getStringValue()
)
);
@@ -1454,6 +1454,11 @@
return false;
}
+void
+Item::ensureSeekable()
+{
+}
+
std::istream& Item::getStream()
{
throw ZORBA_EXCEPTION(
=== modified file 'src/store/naive/item_vector.cpp'
--- src/store/naive/item_vector.cpp 2013-05-31 14:34:43 +0000
+++ src/store/naive/item_vector.cpp 2014-04-17 12:18:12 +0000
@@ -104,10 +104,14 @@
{
std::ostringstream res;
res << "ItemVector size: " << size() << " [";
- for ( ulong i = 0; i < size(); i++)
- res << getItem(i)->show() << ", ";
- res << "]";
-
+ for ( ulong i = 0; i < size(); i++)
+ {
+ if (getItem(i))
+ res << getItem(i)->show() << ", ";
+ else
+ res << "NULL" << ",";
+ }
+ res << "]";
return res.str();
}
=== modified file 'src/store/naive/item_vector.h'
--- src/store/naive/item_vector.h 2013-02-07 17:24:36 +0000
+++ src/store/naive/item_vector.h 2014-04-17 12:18:12 +0000
@@ -23,7 +23,7 @@
/***************************************************************************//**
ItemVector is just internal to the store and implements a list/sequence of
- Items. It doesn't have a type assignet to it, the type is on the ellement
+ Items. It doesn't have a type assigned to it, the type is on the element
or attribute parent node.
********************************************************************************/
class ItemVector : public store::Item
=== modified file 'src/store/naive/json_items.cpp'
--- src/store/naive/json_items.cpp 2014-04-02 22:37:58 +0000
+++ src/store/naive/json_items.cpp 2014-04-17 12:18:12 +0000
@@ -1262,8 +1262,10 @@
zstring SimpleJSONArray::show() const
{
std::stringstream str;
- str << "[ ]";
-
+ str << "Array size: " << theContent.size() << " [";
+ for ( ulong i = 0; i < theContent.size(); i++)
+ str << theContent[i]->show() << ", ";
+ str << "]";
return str.str();
}
=== modified file 'src/store/naive/simple_item_factory.cpp'
--- src/store/naive/simple_item_factory.cpp 2014-03-06 19:06:43 +0000
+++ src/store/naive/simple_item_factory.cpp 2014-04-17 12:18:12 +0000
@@ -2146,9 +2146,9 @@
/*******************************************************************************
********************************************************************************/
-store::PUL* BasicItemFactory::createPendingUpdateList()
+store::PUL* BasicItemFactory::createPendingUpdateList(bool isTransform)
{
- return new PULImpl();
+ return new PULImpl(isTransform);
}
#if 0
=== modified file 'src/store/naive/simple_item_factory.h'
--- src/store/naive/simple_item_factory.h 2013-06-18 23:53:59 +0000
+++ src/store/naive/simple_item_factory.h 2014-04-17 12:18:12 +0000
@@ -394,7 +394,8 @@
zstring& prefix,
zstring& uri);
- store::PUL* createPendingUpdateList();
+ store::PUL* createPendingUpdateList(
+ bool isTransform = false);
bool createError(
store::Item_t& result,
=== modified file 'src/store/naive/simple_pul.cpp'
--- src/store/naive/simple_pul.cpp 2013-07-01 09:26:16 +0000
+++ src/store/naive/simple_pul.cpp 2014-04-17 12:18:12 +0000
@@ -106,14 +106,16 @@
/*******************************************************************************
********************************************************************************/
-PULImpl::PULImpl()
+PULImpl::PULImpl(bool isTransform)
:
PUL(),
theNoCollectionPul(NULL),
theLastPul(NULL),
theLastCollection(NULL),
+ theICChecker(NULL),
theValidator(NULL),
- theInheritNSBindings(false)
+ theInheritNSBindings(false),
+ theIsTransform(isTransform)
{
}
=== modified file 'src/store/naive/simple_pul.h'
--- src/store/naive/simple_pul.h 2013-06-15 02:57:08 +0000
+++ src/store/naive/simple_pul.h 2014-04-17 12:18:12 +0000
@@ -350,8 +350,10 @@
bool theInheritNSBindings;
+ bool theIsTransform;
+
public:
- PULImpl();
+ PULImpl(bool isTransform);
~PULImpl();
@@ -665,6 +667,8 @@
void checkIC(const store::Item* collName);
+ bool isTransform() { return theIsTransform; }
+
protected:
void mergeTargetedUpdateLists(
=== modified file 'src/types/typemanagerimpl.cpp'
--- src/types/typemanagerimpl.cpp 2013-09-23 09:11:02 +0000
+++ src/types/typemanagerimpl.cpp 2014-04-17 12:18:12 +0000
@@ -437,8 +437,8 @@
{
if (raiseError)
{
- RAISE_ERROR(err::XPTY0004, loc,
- ERROR_PARAMS(qname->getStringValue(), ZED(NotAmongInScopeSchemaTypes)));
+ RAISE_ERROR(err::XPTY0004, loc,
+ ERROR_PARAMS(qname->getStringValue(), ZED(NotAmongInScopeSchemaTypes)));
}
else
{
@@ -454,8 +454,8 @@
if (raiseError)
{
- RAISE_ERROR(err::XPTY0004, loc,
- ERROR_PARAMS(qname->getStringValue(), ZED(NotAmongInScopeSchemaTypes)));
+ RAISE_ERROR(err::XPTY0004, loc,
+ ERROR_PARAMS(qname->getStringValue(), ZED(NotAmongInScopeSchemaTypes)));
}
else
{
=== modified file 'src/zorbaserialization/archiver_consts.h'
--- src/zorbaserialization/archiver_consts.h 2013-09-09 08:32:50 +0000
+++ src/zorbaserialization/archiver_consts.h 2014-04-17 12:18:12 +0000
@@ -226,8 +226,9 @@
TYPE_GroupingSpec,
TYPE_GroupByIterator,
+ TYPE_function,
+ TYPE_cacheable_function,
TYPE_user_function,
- TYPE_function,
TYPE_external_function,
TYPE_signature,
TYPE_AnnotationInternal,
=== added file 'src/zorbautils/hashmap_itemh_strict.h'
--- src/zorbautils/hashmap_itemh_strict.h 1970-01-01 00:00:00 +0000
+++ src/zorbautils/hashmap_itemh_strict.h 2014-04-17 12:18:12 +0000
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2006-2008 The FLWOR Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HASHMAP_ITEMH_STRICT_H
+#define HASHMAP_ITEMH_STRICT_H
+
+#include "zorbautils/hashfun.h"
+#include "zorbautils/hashmap.h"
+
+#include "store/api/item.h"
+#include "store/naive/item_vector.h"
+
+namespace zorba
+{
+
+class ItemHandleStrictHashMapCmp
+{
+protected:
+ long theTimeZone;
+ XQPCollator * theCollator;
+
+public:
+ ItemHandleStrictHashMapCmp()
+ :
+ theTimeZone(0),
+ theCollator(NULL)
+ {
+ }
+
+ ItemHandleStrictHashMapCmp(long tmz, XQPCollator* collator)
+ :
+ theTimeZone(tmz),
+ theCollator(collator)
+ {
+ }
+
+ bool equal(const store::Item* t1, const store::Item* t2) const
+ {
+ if (t1 == NULL && t2 ==NULL)
+ return true;
+
+ if (t1 == NULL || t2 ==NULL)
+ return false;
+
+ store::Item::ItemKind lKind1 = t1->getKind();
+ store::Item::ItemKind lKind2 = t2->getKind();
+ if (lKind1 != lKind2)
+ return false;
+
+ const simplestore::ItemVector* lVector1;
+ const simplestore::ItemVector* lVector2;
+ switch (lKind1)
+ {
+ case store::Item::NODE:
+ case store::Item::OBJECT:
+ case store::Item::ARRAY:
+ {
+ return t1 == t2;
+ }
+ case store::Item::ATOMIC:
+ {
+ if (t1->getTypeCode() != t2->getTypeCode())
+ return false;
+ return t1->equals(t2, theTimeZone, theCollator);
+ }
+ case store::Item::LIST:
+ {
+ lVector1 = static_cast<const simplestore::ItemVector*>(t1);
+ lVector2 = static_cast<const simplestore::ItemVector*>(t2);
+
+ if (lVector1->size() != lVector2->size())
+ return false;
+
+ for (unsigned int i=0; i<lVector1->size(); ++i)
+ {
+ if (!equal(lVector1->getItem(i), lVector2->getItem(i)))
+ return false;
+ }
+ return true;
+ }
+ default:
+ {
+ /*
+ * The type of the item is one of:
+ * PUL, FUNCTION, ERROR_
+ */
+ return false;
+ }
+ }
+ }
+
+ uint32_t hash(const store::Item* t) const
+ {
+ if (t == NULL)
+ return FNV_32_INIT;
+
+ store::SchemaTypeCode lTypeCode;
+ uint32_t lInnerHash;
+ const simplestore::ItemVector* lVector;
+ store::Item::ItemKind lKind = t->getKind();
+ uint32_t lHash = hashfun::h32(&lKind, sizeof(store::Item::ItemKind), FNV_32_INIT);
+ switch (lKind)
+ {
+ case store::Item::NODE:
+ case store::Item::OBJECT:
+ case store::Item::ARRAY:
+ {
+ return hashfun::h32((void*)(&t), sizeof(t), lHash);
+ }
+ case store::Item::ATOMIC:
+ {
+ lTypeCode = t->getTypeCode();
+ lHash = hashfun::h32(&lTypeCode, sizeof(lTypeCode), lHash);
+ lInnerHash = t->hash(theTimeZone, theCollator);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::Item::LIST:
+ {
+ lVector = static_cast<const simplestore::ItemVector*>(t);
+ for (unsigned int i=0; i<lVector->size(); ++i)
+ {
+ lInnerHash = hash(lVector->getItem(i));
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ return lHash;
+ }
+ default:
+ {
+ /*
+ * The type of the item is one of:
+ * PUL, FUNCTION, ERROR_
+ */
+ return FNV_32_INIT;
+ }
+ }
+ }
+
+ long get_timezone() const { return theTimeZone; }
+
+ const XQPCollator* get_collator() const { return theCollator; }
+};
+
+
+/*******************************************************************************
+ A hash-based map mapping item handles to data items of type V. Equality is
+ based on pointer equality for Nodes, Arrays and Objects and on the
+ store::Item::equals() method for atomic. PULs, Function Items, and Error_s are
+ not supported and are always considered different.
+
+ NOTE: Although the map uses raw item pointers instead of rchandles, reference
+ counting is still done, but done manually (see insert, clear and erase
+ methods)
+********************************************************************************/
+template <class V>
+class ItemHandleStrictHashMap
+{
+public:
+ typedef typename HashMap<store::Item*, V, ItemHandleStrictHashMapCmp>::iterator iterator;
+
+private:
+ HashMap<store::Item*, V, ItemHandleStrictHashMapCmp> theMap;
+
+public:
+ ItemHandleStrictHashMap()
+ :
+ theMap(ItemHandleStrictHashMapCmp(), 8, false)
+ {
+ }
+
+ ItemHandleStrictHashMap(
+ ulong size,
+ bool sync)
+ :
+ theMap(ItemHandleStrictHashMapCmp(), size, sync)
+ {
+ }
+
+ ItemHandleStrictHashMap(
+ long timezone,
+ XQPCollator* collation,
+ ulong size,
+ bool sync)
+ :
+ theMap(ItemHandleStrictHashMapCmp(timezone, collation), size, sync)
+ {
+ }
+
+ ~ItemHandleStrictHashMap()
+ {
+ clear();
+ }
+
+ void clear()
+ {
+ SYNC_CODE(AutoMutex lock(theMap.get_mutex());)
+
+ iterator ite = this->begin();
+ iterator end = this->end();
+
+ for (; ite != end; ++ite)
+ {
+ (*ite).first->removeReference();
+ }
+
+ theMap.clearNoSync();
+ }
+
+ iterator begin() const { return theMap.begin(); }
+
+ iterator end() const { return theMap.end(); }
+
+ iterator find(const store::Item_t& item)
+ {
+ return theMap.find(item.getp());
+ }
+
+ bool insert(const store::Item_t& item, V& value)
+ {
+ bool inserted = theMap.insert(item.getp(), value);
+
+ if (inserted)
+ item->addReference();
+
+ return inserted;
+ }
+
+ bool erase(const store::Item_t& key)
+ {
+ bool found = theMap.erase(key.getp());
+
+ if (found)
+ key->removeReference();
+
+ return found;
+ }
+
+ csize size() const
+ {
+ return theMap.size();
+ }
+
+ bool empty() const
+ {
+ return theMap.size() == 0;
+ }
+
+};
+
+}
+
+#endif
=== added directory 'test/iterplans/zorba/caching'
=== added file 'test/iterplans/zorba/caching/annotations-inlining.iter'
--- test/iterplans/zorba/caching/annotations-inlining.iter 1970-01-01 00:00:00 +0000
+++ test/iterplans/zorba/caching/annotations-inlining.iter 2014-04-17 12:18:12 +0000
@@ -0,0 +1,28 @@
+<iterator-tree description="const-folded expr">
+ <FunctionTraceIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </FunctionTraceIterator>
+</iterator-tree>
+<iterator-tree description="const-folded expr">
+ <UDFunctionCallIterator cached="true" function="local:foo-sd">
+ <FnConcatIterator/>
+ </UDFunctionCallIterator>
+</iterator-tree>
+<iterator-tree description="local:foo-sd">
+ <SingletonIterator value="xs:integer(1)"/>
+</iterator-tree>
+<iterator-tree description="const-folded expr">
+ <UDFunctionCallIterator cached-across-snapshots="true" function="local:foo-c">
+ <FnConcatIterator/>
+ </UDFunctionCallIterator>
+</iterator-tree>
+<iterator-tree description="local:foo-c">
+ <SingletonIterator value="xs:integer(1)"/>
+</iterator-tree>
+<iterator-tree description="main query">
+ <FnConcatIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ </FnConcatIterator>
+</iterator-tree>
=== added file 'test/iterplans/zorba/caching/automatic-annotations.iter'
--- test/iterplans/zorba/caching/automatic-annotations.iter 1970-01-01 00:00:00 +0000
+++ test/iterplans/zorba/caching/automatic-annotations.iter 2014-04-17 12:18:12 +0000
@@ -0,0 +1,442 @@
+<iterator-tree description="const-folded expr">
+ <CastIterator type="xs:double">
+ <SingletonIterator value="xs:integer(0)"/>
+ </CastIterator>
+</iterator-tree>
+<iterator-tree description="const-folded expr">
+ <CastIterator type="xs:double">
+ <SingletonIterator value="xs:integer(0)"/>
+ </CastIterator>
+</iterator-tree>
+<iterator-tree description="main query">
+ <SequentialIterator>
+ <CtxVarDeclareIterator varid="4" varname="local:x">
+ <FnConcatIterator/>
+ </CtxVarDeclareIterator>
+ <SequentialIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-1"/>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-2">
+ <ElementIterator copyInputNodes="false">
+ <SingletonIterator value="xs:QName(,,x)"/>
+ </ElementIterator>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-3">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-4">
+ <JSONObjectIterator/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-5">
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-6">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-7">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-8">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-9">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-10">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-11">
+ <SingletonIterator value="xs:double(0)"/>
+ <SingletonIterator value="xs:integer(2)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator function="local:not-cached-12">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-1">
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-2">
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-3">
+ <FnConcatIterator/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-4">
+ <FnConcatIterator/>
+ <FnConcatIterator/>
+ <FnConcatIterator/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator cached-across-snapshots="true" function="local:cached-5">
+ <FnConcatIterator/>
+ <FnConcatIterator/>
+ <FnConcatIterator/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <ApplyIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-6">
+ <SingletonIterator value="xs:double(0)"/>
+ <SingletonIterator value="xs:integer(2)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ </UDFunctionCallIterator>
+ </ApplyIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </SequentialIterator>
+ </SequentialIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-1">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-1"/>
+ <FnConcatIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-2">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-2">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <JSONObjectIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-3">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-3">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <JSONObjectIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-4">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-4">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-5">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-5">
+ <LetVarIterator varname="x"/>
+ <LetVarIterator varname="y"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-6">
+ <FLWORIterator>
+ <ForVariable name="x">
+ <LetVarIterator varname="x"/>
+ </ForVariable>
+ <MaterializeClause>
+ <MaterializeForVariable inputVar="x : "/>
+ </MaterializeClause>
+ <ReturnClause>
+ <SequentialIterator>
+ <ApplyIterator>
+ <DeleteIterator>
+ <ElementIterator>
+ <SingletonIterator value="xs:QName(,,x)"/>
+ </ElementIterator>
+ </DeleteIterator>
+ </ApplyIterator>
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-6">
+ <ForVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+ </SequentialIterator>
+ </ReturnClause>
+ </FLWORIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-7">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-7">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-8">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-8">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-9">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-9">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <DeleteIterator>
+ <ElementIterator>
+ <SingletonIterator value="xs:QName(,,x)"/>
+ </ElementIterator>
+ </DeleteIterator>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-10">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-10">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <FnConcatIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-11">
+ <FLWORIterator>
+ <LetVariable name="v" materialize="true">
+ <LetVarIterator varname="v"/>
+ </LetVariable>
+ <ForVariable name="stride">
+ <LetVarIterator varname="stride"/>
+ </ForVariable>
+ <ForVariable name="remaining">
+ <LetVarIterator varname="remaining"/>
+ </ForVariable>
+ <ForVariable name="offset">
+ <LetVarIterator varname="offset"/>
+ </ForVariable>
+ <ReturnClause>
+ <IfThenElseIterator>
+ <TypedValueCompareIterator_INTEGER>
+ <ForVarIterator varname="remaining"/>
+ <ForVarIterator varname="stride"/>
+ </TypedValueCompareIterator_INTEGER>
+ <ElementIterator copyInputNodes="false">
+ <SingletonIterator value="xs:QName(,,a)"/>
+ </ElementIterator>
+ <FLWORIterator>
+ <ForVariable name="x">
+ <UDFunctionCallIterator function="local:not-cached-11">
+ <LetVarIterator varname="v"/>
+ <ForVarIterator varname="stride"/>
+ <SpecificNumArithIterator_SubtractOperation_INTEGER>
+ <ForVarIterator varname="remaining"/>
+ <ForVarIterator varname="stride"/>
+ </SpecificNumArithIterator_SubtractOperation_INTEGER>
+ <SpecificNumArithIterator_AddOperation_INTEGER>
+ <ForVarIterator varname="offset"/>
+ <ForVarIterator varname="stride"/>
+ </SpecificNumArithIterator_AddOperation_INTEGER>
+ </UDFunctionCallIterator>
+ </ForVariable>
+ <ReturnClause>
+ <GenericArithIterator_AddOperation>
+ <PromoteIterator type="xs:anyAtomicType">
+ <FnDataIterator>
+ <ForVarIterator varname="x"/>
+ </FnDataIterator>
+ </PromoteIterator>
+ <LetVarIterator varname="v">
+ <SpecificNumArithIterator_AddOperation_INTEGER>
+ <ForVarIterator varname="offset"/>
+ <ForVarIterator varname="p"/>
+ </SpecificNumArithIterator_AddOperation_INTEGER>
+ </LetVarIterator>
+ </GenericArithIterator_AddOperation>
+ </ReturnClause>
+ </FLWORIterator>
+ </IfThenElseIterator>
+ </ReturnClause>
+ </FLWORIterator>
+</iterator-tree>
+<iterator-tree description="local:not-cached-12">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator function="local:not-cached-12">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:cached-1">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-1">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <SingletonIterator value="xs:integer(1)"/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:cached-2">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-2">
+ <LetVarIterator varname="x"/>
+ <LetVarIterator varname="y"/>
+ <LetVarIterator varname="z"/>
+ </UDFunctionCallIterator>
+ <FnConcatIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:cached-3">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-3">
+ <LetVarIterator varname="x"/>
+ </UDFunctionCallIterator>
+ <FnConcatIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:cached-4">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator cached="true" function="local:cached-4">
+ <LetVarIterator varname="x"/>
+ <LetVarIterator varname="y"/>
+ <LetVarIterator varname="z"/>
+ </UDFunctionCallIterator>
+ <FnConcatIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:cached-5">
+ <IfThenElseIterator>
+ <FnBooleanIterator>
+ <CtxVarIterator varid="4" varname="local:x" varkind="global"/>
+ </FnBooleanIterator>
+ <UDFunctionCallIterator cached-across-snapshots="true" function="local:cached-5">
+ <LetVarIterator varname="x"/>
+ <LetVarIterator varname="y"/>
+ <LetVarIterator varname="z"/>
+ </UDFunctionCallIterator>
+ <FnConcatIterator/>
+ </IfThenElseIterator>
+</iterator-tree>
+<iterator-tree description="local:cached-6">
+ <FLWORIterator>
+ <LetVariable name="v" materialize="true">
+ <LetVarIterator varname="v"/>
+ </LetVariable>
+ <ForVariable name="stride">
+ <LetVarIterator varname="stride"/>
+ </ForVariable>
+ <ForVariable name="remaining">
+ <LetVarIterator varname="remaining"/>
+ </ForVariable>
+ <ForVariable name="offset">
+ <LetVarIterator varname="offset"/>
+ </ForVariable>
+ <ReturnClause>
+ <IfThenElseIterator>
+ <TypedValueCompareIterator_INTEGER>
+ <ForVarIterator varname="remaining"/>
+ <ForVarIterator varname="stride"/>
+ </TypedValueCompareIterator_INTEGER>
+ <LetVarIterator varname="v">
+ <SpecificNumArithIterator_AddOperation_INTEGER>
+ <ForVarIterator varname="offset"/>
+ <SingletonIterator value="xs:integer(1)"/>
+ </SpecificNumArithIterator_AddOperation_INTEGER>
+ </LetVarIterator>
+ <FLWORIterator>
+ <ForVariable name="x">
+ <UDFunctionCallIterator cached="true" function="local:cached-6">
+ <LetVarIterator varname="v"/>
+ <ForVarIterator varname="stride"/>
+ <SpecificNumArithIterator_SubtractOperation_INTEGER>
+ <ForVarIterator varname="remaining"/>
+ <ForVarIterator varname="stride"/>
+ </SpecificNumArithIterator_SubtractOperation_INTEGER>
+ <SpecificNumArithIterator_AddOperation_INTEGER>
+ <ForVarIterator varname="offset"/>
+ <ForVarIterator varname="stride"/>
+ </SpecificNumArithIterator_AddOperation_INTEGER>
+ </UDFunctionCallIterator>
+ </ForVariable>
+ <ReturnClause>
+ <SpecificNumArithIterator_AddOperation_DOUBLE>
+ <ForVarIterator varname="x"/>
+ <LetVarIterator varname="v">
+ <SpecificNumArithIterator_AddOperation_INTEGER>
+ <ForVarIterator varname="offset"/>
+ <ForVarIterator varname="p"/>
+ </SpecificNumArithIterator_AddOperation_INTEGER>
+ </LetVarIterator>
+ </SpecificNumArithIterator_AddOperation_DOUBLE>
+ </ReturnClause>
+ </FLWORIterator>
+ </IfThenElseIterator>
+ </ReturnClause>
+ </FLWORIterator>
+</iterator-tree>
=== modified file 'test/iterplans/zorba/xray/ppm_10.iter'
--- test/iterplans/zorba/xray/ppm_10.iter 2014-02-25 00:36:41 +0000
+++ test/iterplans/zorba/xray/ppm_10.iter 2014-04-17 12:18:12 +0000
@@ -1983,7 +1983,7 @@
<SingletonIterator value="xs:integer(0)"/>
</ReturnClause>
</FLWORIterator>
- <UDFunctionCallIterator function="vector:sum-internal">
+ <UDFunctionCallIterator cached="true" function="vector:sum-internal">
<LetVarIterator varname="v"/>
<LetVarIterator varname="stride"/>
<ForVarIterator varname="c"/>
@@ -2108,7 +2108,7 @@
</LetVarIterator>
<FLWORIterator>
<ForVariable name="x">
- <UDFunctionCallIterator function="vector:sum-internal">
+ <UDFunctionCallIterator cached="true" function="vector:sum-internal">
<LetVarIterator varname="v"/>
<ForVarIterator varname="stride"/>
<SpecificNumArithIterator_SubtractOperation_INTEGER>
=== added directory 'test/rbkt/ExpQueryResults/zorba/caching'
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/annotations-compatibility.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/annotations-compatibility.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/annotations-compatibility.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/annotations-inlining.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/annotations-inlining.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/annotations-inlining.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+1 1 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/argument-sequence-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/argument-sequence-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/argument-sequence-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+1<a/>{ "a" : 1 }[ 1 ] 1<a/>{ "a" : 1 }[ 1 ]
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/argument-sequence-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/argument-sequence-02.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/argument-sequence-02.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+1<a/>{ "a" : 1 }[ 1 ] 1<a/>{ "a" : 1 }[ 1 ]
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/automatic-annotations.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/automatic-annotations.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/automatic-annotations.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-cache.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-cache.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-cache.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with : CACHED
+ Called with 1: CACHED
+ Called with <a/>: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-sd-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-sd-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-sd-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with : CACHED
+ Called with 1: CACHED
+ Called with <a/>: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-sd-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-sd-02.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/key-match-ext-sd-02.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-cache.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-cache.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-cache.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with : CACHED
+ Called with 1: CACHED
+ Called with <a/>: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-sd-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-sd-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-sd-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with : CACHED
+ Called with 1: CACHED
+ Called with <a/>: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-sd-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-sd-02.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/key-match-udf-sd-02.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with : NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
+ Called with 1: NOT CACHED
+ Called with <a/>: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with [ 2 ]: NOT CACHED
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/lazy-parameters-ext.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/lazy-parameters-ext.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/lazy-parameters-ext.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+false false ERR ERR
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/lazy-parameters-udf.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/lazy-parameters-udf.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/lazy-parameters-udf.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+false false ERR ERR
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/simple-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/simple-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/simple-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,6 @@
+4
+
+ 4
+
+ 22 == 484
+ 22 == 484
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/simple-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/simple-02.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/simple-02.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,6 @@
+4
+
+ 4
+
+ 22 == 484
+ 22 == 484
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/simultaneous-partial-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/simultaneous-partial-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/simultaneous-partial-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+22 484[ 22, " == ", 484 ][ 484, " == ", 234256 ]
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/simultaneous-partial-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/simultaneous-partial-02.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/simultaneous-partial-02.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+22 484[ 22, " == ", 484 ][ 484, " == ", 234256 ]
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/snapshots-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/snapshots-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/snapshots-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+true true true true true
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/snapshots-02.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/snapshots-02.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/snapshots-02.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+true true true true true
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/snapshots-03.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/snapshots-03.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/snapshots-03.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+false false false false true
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/snapshots-04.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/snapshots-04.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/snapshots-04.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+true true true true true
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/snapshots-05.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/snapshots-05.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/snapshots-05.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+true true true true true
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/snapshots-06.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/snapshots-06.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/snapshots-06.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+false false false false true
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/streaming-ext-cache-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/streaming-ext-cache-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/streaming-ext-cache-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+streamable{ "key" : "streamable" }[ "streamable" ]<a xmlns="http://www.w3.org/2001/XMLSchema" xmlns:XXX="http://www.w3.org/2001/XMLSchema" XXX:a="streamable"/>streamable { "streamable" : "streamable" } streamable{ "key" : "streamable" }[ "streamable" ]<a xmlns="http://www.w3.org/2001/XMLSchema" xmlns:XXX="http://www.w3.org/2001/XMLSchema" XXX:a="streamable"/>streamable { "streamable" : "streamable" }
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/streaming-ext-sd-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/streaming-ext-sd-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/streaming-ext-sd-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+streamable{ "key" : "streamable" }[ "streamable" ]<a xmlns="http://www.w3.org/2001/XMLSchema" xmlns:XXX="http://www.w3.org/2001/XMLSchema" XXX:a="streamable"/>streamable { "streamable" : "streamable" } streamable{ "key" : "streamable" }[ "streamable" ]<a xmlns="http://www.w3.org/2001/XMLSchema" xmlns:XXX="http://www.w3.org/2001/XMLSchema" XXX:a="streamable"/>streamable { "streamable" : "streamable" }
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/streaming-udf-cache-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/streaming-udf-cache-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/streaming-udf-cache-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+streamable{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" }streamable { "streamable" : "streamable" } streamable{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" }streamable { "streamable" : "streamable" } streamable{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" }{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" } 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/streaming-udf-sd-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/streaming-udf-sd-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/streaming-udf-sd-01.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+streamable{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" }streamable { "streamable" : "streamable" } streamable{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" }streamable { "streamable" : "streamable" } streamable{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" }{ "media-type" : "text/plain", "content" : "Method: GET\nQuery: \nPost: \n" } 1
\ No newline at end of file
=== added directory 'test/rbkt/ExpQueryResults/zorba/dctx'
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/copy-modify-return.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/copy-modify-return.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/copy-modify-return.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 0
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/exit-expression.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/exit-expression.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/exit-expression.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 0 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/external-sequential-function-call.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/external-sequential-function-call.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/external-sequential-function-call.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 2
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/external-updating-function-call.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/external-updating-function-call.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/external-updating-function-call.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/global-variables.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/global-variables.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/global-variables.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/local-variables.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/local-variables.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/local-variables.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 0 1 3 5
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/non-sequential-concat.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/non-sequential-concat.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/non-sequential-concat.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 0 0
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/pul-application.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/pul-application.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/pul-application.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/updating-function-call.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/updating-function-call.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/updating-function-call.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/variable-declaration.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/variable-declaration.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/variable-declaration.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 1 0
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/dctx/while-expression.xml.res'
--- test/rbkt/ExpQueryResults/zorba/dctx/while-expression.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/dctx/while-expression.xml.res 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+0 3
\ No newline at end of file
=== added directory 'test/rbkt/Queries/zorba/caching'
=== added file 'test/rbkt/Queries/zorba/caching/annotations-compatibility.xq'
--- test/rbkt/Queries/zorba/caching/annotations-compatibility.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-compatibility.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,26 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:foo($x as xs:integer)
+{
+};
+
+declare function local:foo-det($x as xs:integer)
+{
+ local:foo($x)
+};
+
+declare %an:nondeterministic function local:foo-nondet($x as xs:integer)
+{
+ local:foo($x)
+};
+
+declare %an:sequential function local:foo-seq($x as xs:integer)
+{
+ local:foo($x)
+};
+
+declare %an:sequential %an:strictlydeterministic function local:foo-1($x as xs:integer)
+{
+};
+
+1
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-incompatibility-01.spec'
--- test/rbkt/Queries/zorba/caching/annotations-incompatibility-01.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-incompatibility-01.spec 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:XQST0106
=== added file 'test/rbkt/Queries/zorba/caching/annotations-incompatibility-01.xq'
--- test/rbkt/Queries/zorba/caching/annotations-incompatibility-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-incompatibility-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,7 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:cache %an:strictlydeterministic function local:foo($x as xs:integer)
+{
+};
+
+1
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-incompatibility-02.spec'
--- test/rbkt/Queries/zorba/caching/annotations-incompatibility-02.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-incompatibility-02.spec 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:XQST0106
=== added file 'test/rbkt/Queries/zorba/caching/annotations-incompatibility-02.xq'
--- test/rbkt/Queries/zorba/caching/annotations-incompatibility-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-incompatibility-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,7 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:deterministic %an:strictlydeterministic function local:foo($x as xs:integer)
+{
+};
+
+1
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-incompatibility-03.spec'
--- test/rbkt/Queries/zorba/caching/annotations-incompatibility-03.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-incompatibility-03.spec 2014-04-17 12:18:12 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:XQST0106
=== added file 'test/rbkt/Queries/zorba/caching/annotations-incompatibility-03.xq'
--- test/rbkt/Queries/zorba/caching/annotations-incompatibility-03.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-incompatibility-03.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,7 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:nondeterministic %an:strictlydeterministic function local:foo($x as xs:integer)
+{
+};
+
+1
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-inlining.xq'
--- test/rbkt/Queries/zorba/caching/annotations-inlining.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-inlining.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:foo-sd($x)
+{
+ 1
+};
+
+declare %an:cache function local:foo-c($x)
+{
+ 1
+};
+
+declare function local:foo($x)
+{
+ 1
+};
+
+local:foo(()),
+local:foo-sd(()),
+local:foo-c(())
+
=== added file 'test/rbkt/Queries/zorba/caching/argument-sequence-01.xq'
--- test/rbkt/Queries/zorba/caching/argument-sequence-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/argument-sequence-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,11 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:test-02-cache($arg)
+{
+ serialize($arg),
+ debug:uuid()
+};
+
+local:test-02-cache((xs:integer(1), <a/>, {"a" : 1}, [1]))[1],
+local:test-02-cache((xs:integer(1), <a/>, {"a" : 1}, [1]))[1]
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/argument-sequence-02.xq'
--- test/rbkt/Queries/zorba/caching/argument-sequence-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/argument-sequence-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,4 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+debug:test-02-cache((xs:integer(1), <a/>, {"a" : 1}, [1]))[1],
+debug:test-02-cache((xs:integer(1), <a/>, {"a" : 1}, [1]))[1]
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/automatic-annotations.xq'
--- test/rbkt/Queries/zorba/caching/automatic-annotations.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/automatic-annotations.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,125 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare variable $local:x := ();
+
+declare function local:not-cached-1()
+{
+ if ($local:x) then local:not-cached-1() else ()
+};
+
+declare function local:not-cached-2($x as node()) as object()
+{
+ if ($local:x) then local:not-cached-2($x) else {||}
+};
+
+declare function local:not-cached-3($x as xs:integer) as object()
+{
+ if ($local:x) then local:not-cached-3($x) else {||}
+};
+
+declare function local:not-cached-4($x as object()) as xs:integer
+{
+ if ($local:x) then local:not-cached-4($x) else 1
+};
+
+declare function local:not-cached-5($x as xs:integer, $y) as xs:integer
+{
+ if ($local:x) then local:not-cached-5($x,$y) else 1
+};
+
+declare %an:sequential function local:not-cached-6($x as xs:integer) as xs:integer
+{
+ delete node <x/>;
+ if ($local:x) then local:not-cached-6($x) else 1
+};
+
+declare %an:nondeterministic function local:not-cached-7($x as xs:integer) as xs:integer
+{
+ if ($local:x) then local:not-cached-7($x) else 1
+};
+
+declare %an:deterministic function local:not-cached-8($x as xs:integer) as xs:integer
+{
+ if ($local:x) then local:not-cached-8($x) else 1
+};
+
+declare updating function local:not-cached-9($x as xs:integer)
+{
+ if ($local:x) then local:not-cached-9($x) else delete node <x/>
+};
+
+declare updating function local:not-cached-10($x as xs:integer)
+{
+ if ($local:x) then local:not-cached-10($x) else ()
+};
+
+(: The return type is item :)
+declare function local:not-cached-11($v as xs:double*, $stride as xs:integer, $remaining as xs:integer, $offset as xs:integer)
+{
+ if ($remaining le $stride)
+ then <a/>
+ else
+ for $x at $p in local:not-cached-11($v, $stride, $remaining - $stride, $offset + $stride)
+ return $x + $v[$offset + $p]
+};
+
+declare %an:variadic function local:not-cached-12($x as xs:integer) as xs:integer
+{
+ if ($local:x) then local:not-cached-12($x) else 1
+};
+
+declare function local:cached-1($x as xs:integer) as xs:integer
+{
+ if ($local:x) then local:cached-1($x) else 1
+};
+
+declare function local:cached-2($x as xs:integer?, $y as xs:integer+, $z as xs:integer*) as xs:integer?
+{
+ if ($local:x) then local:cached-2($x,$y,$z) else ()
+};
+
+declare function local:cached-3($x as empty-sequence()) as empty-sequence()
+{
+ if ($local:x) then local:cached-3($x) else ()
+};
+
+declare %an:strictlydeterministic function local:cached-4($x, $y, $z)
+{
+ if ($local:x) then local:cached-4($x,$y,$z) else ()
+};
+
+declare %an:cache function local:cached-5($x, $y, $z)
+{
+ if ($local:x) then local:cached-5($x,$y,$z) else ()
+};
+
+(: The return type can be statically determined as atomic :)
+declare function local:cached-6($v as xs:double*, $stride as xs:integer, $remaining as xs:integer, $offset as xs:integer)
+{
+ if ($remaining le $stride)
+ then subsequence($v, $offset + 1)
+ else
+ for $x at $p in local:cached-6($v, $stride, $remaining - $stride, $offset + $stride)
+ return $x + $v[$offset + $p]
+};
+
+local:not-cached-1();
+local:not-cached-2(<x/>);
+local:not-cached-3(1);
+local:not-cached-4({||});
+local:not-cached-5(1,1);
+local:not-cached-6(1);
+local:not-cached-7(1);
+local:not-cached-8(1);
+local:not-cached-9(1);
+local:not-cached-10(1);
+local:not-cached-11(xs:double(0), 2, 1, 1);
+local:not-cached-12(1);
+local:cached-1(1);
+local:cached-2(1, 1, 1);
+local:cached-3(());
+local:cached-4((),(),());
+local:cached-5((),(),());
+local:cached-6(xs:double(0), 2, 1, 1);
+
+1
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/key-match-ext-cache.xq'
--- test/rbkt/Queries/zorba/caching/key-match-ext-cache.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/key-match-ext-cache.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,60 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+declare function local:is-cached($uuids, $old-uuids)
+{
+ if ($uuids = $old-uuids)
+ then "CACHED"
+ else "NOT CACHED"
+};
+
+
+variable $node := <a/>;
+variable $object := {"a" : 1};
+variable $array := [1];
+variable $array-2 := [2];
+
+let $old :=
+(
+ debug:test-02-cache(()),
+ debug:test-02-cache(xs:int(1)),
+ debug:test-02-cache(xs:integer(1)),
+ debug:test-02-cache($node),
+ debug:test-02-cache($object),
+ debug:test-02-cache($array),
+ debug:test-02-cache($node),
+ debug:test-02-cache($object),
+ debug:test-02-cache($array),
+ debug:test-02-cache($array-2)
+)
+let $old-values := (for $i in (1 to 10) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 10) return $old[$i * 2])
+let $equal :=
+(
+ debug:test-02-cache(()),
+ debug:test-02-cache(xs:integer(1)),
+ debug:test-02-cache($node),
+ debug:test-02-cache($object),
+ debug:test-02-cache($array),
+ debug:test-02-cache($array-2)
+)
+let $expected-old-values := (for $i in (1 to 6) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 6) return $equal[$i * 2])
+let $re-evaluated :=
+(
+ debug:test-02-cache(xs:long(1)),
+ debug:test-02-cache(<a/>),
+ debug:test-02-cache({"a" : 1}),
+ debug:test-02-cache([1]),
+ debug:test-02-cache([2])
+)
+let $expected-new-values := (for $i in (1 to 5) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 5) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 10)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 6)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 5)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/key-match-ext-sd-01.xq'
--- test/rbkt/Queries/zorba/caching/key-match-ext-sd-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/key-match-ext-sd-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,60 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+declare function local:is-cached($uuids, $old-uuids)
+{
+ if ($uuids = $old-uuids)
+ then "CACHED"
+ else "NOT CACHED"
+};
+
+
+variable $node := <a/>;
+variable $object := {"a" : 1};
+variable $array := [1];
+variable $array-2 := [2];
+
+let $old :=
+(
+ debug:test-02-sd(()),
+ debug:test-02-sd(xs:int(1)),
+ debug:test-02-sd(xs:integer(1)),
+ debug:test-02-sd($node),
+ debug:test-02-sd($object),
+ debug:test-02-sd($array),
+ debug:test-02-sd($node),
+ debug:test-02-sd($object),
+ debug:test-02-sd($array),
+ debug:test-02-sd($array-2)
+)
+let $old-values := (for $i in (1 to 10) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 10) return $old[$i * 2])
+let $equal :=
+(
+ debug:test-02-sd(()),
+ debug:test-02-sd(xs:integer(1)),
+ debug:test-02-sd($node),
+ debug:test-02-sd($object),
+ debug:test-02-sd($array),
+ debug:test-02-sd($array-2)
+)
+let $expected-old-values := (for $i in (1 to 6) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 6) return $equal[$i * 2])
+let $re-evaluated :=
+(
+ debug:test-02-sd(xs:long(1)),
+ debug:test-02-sd(<a/>),
+ debug:test-02-sd({"a" : 1}),
+ debug:test-02-sd([1]),
+ debug:test-02-sd([2])
+)
+let $expected-new-values := (for $i in (1 to 5) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 5) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 10)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 6)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 5)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/key-match-ext-sd-02.xq'
--- test/rbkt/Queries/zorba/caching/key-match-ext-sd-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/key-match-ext-sd-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,57 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+declare function local:is-cached($uuids, $old-uuids)
+{
+ if ($uuids = $old-uuids)
+ then "CACHED"
+ else "NOT CACHED"
+};
+
+
+variable $node := <a/>;
+variable $object := {"a" : 1};
+variable $array := [1];
+variable $array-2 := [2];
+
+variable $old :=
+(
+ debug:test-02-sd(()),
+ debug:test-02-sd(xs:int(1)),
+ debug:test-02-sd(xs:integer(1)),
+ debug:test-02-sd($node),
+ debug:test-02-sd($object),
+ debug:test-02-sd($array),
+ debug:test-02-sd($node),
+ debug:test-02-sd($object),
+ debug:test-02-sd($array),
+ debug:test-02-sd($array-2)
+);
+variable $old-values := (for $i in (1 to 10) return $old[$i * 2 - 1]);
+variable $old-uuids := (for $i in (1 to 10) return $old[$i * 2]);
+
+variable $advance := <x/>;
+rename node $advance as "y";
+
+variable $re-evaluated :=
+(
+ debug:test-02-sd(()),
+ debug:test-02-sd(xs:integer(1)),
+ debug:test-02-sd($node),
+ debug:test-02-sd($object),
+ debug:test-02-sd($array),
+ debug:test-02-sd($array-2),
+ debug:test-02-sd(xs:long(1)),
+ debug:test-02-sd(<a/>),
+ debug:test-02-sd({"a" : 1}),
+ debug:test-02-sd([1]),
+ debug:test-02-sd([2])
+);
+variable $expected-new-values := (for $i in (1 to 11) return $re-evaluated[$i * 2 - 1]);
+variable $expected-new-uuids := (for $i in (1 to 11) return $re-evaluated[$i * 2]);
+
+(
+ for $i in (1 to 10)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 11)
+ return "Called with " || $expected-new-values[$j] || ": " || local:is-cached($expected-new-uuids[$j], $old-uuids) || " "
+)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/key-match-udf-cache.xq'
--- test/rbkt/Queries/zorba/caching/key-match-udf-cache.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/key-match-udf-cache.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,68 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+import module namespace random = "http://zorba.io/modules/random";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:cache %an:nondeterministic function local:test-02-cache($arg)
+{
+ serialize($arg),
+ random:uuid()
+};
+
+declare function local:is-cached($uuids, $old-uuids)
+{
+ if ($uuids = $old-uuids)
+ then "CACHED"
+ else "NOT CACHED"
+};
+
+
+variable $node := <a/>;
+variable $object := {"a" : 1};
+variable $array := [1];
+variable $array-2 := [2];
+
+let $old :=
+(
+ local:test-02-cache(()),
+ local:test-02-cache(xs:int(1)),
+ local:test-02-cache(xs:integer(1)),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($array-2)
+)
+let $old-values := (for $i in (1 to 10) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 10) return $old[$i * 2])
+let $equal :=
+(
+ local:test-02-cache(()),
+ local:test-02-cache(xs:integer(1)),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($array-2)
+)
+let $expected-old-values := (for $i in (1 to 6) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 6) return $equal[$i * 2])
+let $re-evaluated :=
+(
+ local:test-02-cache(xs:long(1)),
+ local:test-02-cache(<a/>),
+ local:test-02-cache({"a" : 1}),
+ local:test-02-cache([1]),
+ local:test-02-cache([2])
+)
+let $expected-new-values := (for $i in (1 to 5) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 5) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 10)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 6)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 5)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/key-match-udf-sd-01.xq'
--- test/rbkt/Queries/zorba/caching/key-match-udf-sd-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/key-match-udf-sd-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,68 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:test-02-cache($arg)
+{
+ serialize($arg),
+ debug:uuid()
+};
+
+declare function local:is-cached($uuids, $old-uuids)
+{
+ if ($uuids = $old-uuids)
+ then "CACHED"
+ else "NOT CACHED"
+};
+
+
+variable $node := <a/>;
+variable $object := {"a" : 1};
+variable $array := [1];
+variable $array-2 := [2];
+
+let $old :=
+(
+ local:test-02-cache(()),
+ local:test-02-cache(xs:int(1)),
+ local:test-02-cache(xs:integer(1)),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($array-2)
+)
+let $old-values := (for $i in (1 to 10) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 10) return $old[$i * 2])
+let $equal :=
+(
+ local:test-02-cache(()),
+ local:test-02-cache(xs:integer(1)),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($array-2)
+)
+let $expected-old-values := (for $i in (1 to 6) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 6) return $equal[$i * 2])
+let $re-evaluated :=
+(
+ local:test-02-cache(xs:long(1)),
+ local:test-02-cache(<a/>),
+ local:test-02-cache({"a" : 1}),
+ local:test-02-cache([1]),
+ local:test-02-cache([2])
+)
+let $expected-new-values := (for $i in (1 to 5) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 5) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 10)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 6)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 5)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/key-match-udf-sd-02.xq'
--- test/rbkt/Queries/zorba/caching/key-match-udf-sd-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/key-match-udf-sd-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,72 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:test-02-cache($arg)
+{
+ serialize($arg),
+ debug:uuid()
+};
+
+declare function local:is-cached($uuids, $old-uuids)
+{
+ if ($uuids = $old-uuids)
+ then "CACHED"
+ else "NOT CACHED"
+};
+
+
+variable $node := <a/>;
+variable $object := {"a" : 1};
+variable $array := [1];
+variable $array-2 := [2];
+
+variable $old :=
+(
+ local:test-02-cache(()),
+ local:test-02-cache(xs:int(1)),
+ local:test-02-cache(xs:integer(1)),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($array-2)
+);
+variable $old-values := (for $i in (1 to 10) return $old[$i * 2 - 1]);
+variable $old-uuids := (for $i in (1 to 10) return $old[$i * 2]);
+
+variable $advance := <x/>;
+rename node $advance as "y";
+
+variable $equal :=
+(
+ local:test-02-cache(()),
+ local:test-02-cache(xs:integer(1)),
+ local:test-02-cache($node),
+ local:test-02-cache($object),
+ local:test-02-cache($array),
+ local:test-02-cache($array-2)
+);
+variable $expected-old-values := (for $i in (1 to 6) return $equal[$i * 2 -1]);
+variable $expected-old-uuids := (for $i in (1 to 6) return $equal[$i * 2]);
+variable $re-evaluated :=
+(
+ local:test-02-cache(xs:long(1)),
+ local:test-02-cache(<a/>),
+ local:test-02-cache({"a" : 1}),
+ local:test-02-cache([1]),
+ local:test-02-cache([2])
+);
+variable $expected-new-values := (for $i in (1 to 5) return $re-evaluated[$i * 2 - 1]);
+variable $expected-new-uuids := (for $i in (1 to 5) return $re-evaluated[$i * 2]);
+
+(
+ for $i in (1 to 10)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 6)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 5)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/lazy-parameters-ext.xq'
--- test/rbkt/Queries/zorba/caching/lazy-parameters-ext.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/lazy-parameters-ext.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,7 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+debug:test-05-cache(false, error(xs:QName("debug:ERR"), "ERR")),
+debug:test-05-sd(false, error(xs:QName("debug:ERR"), "ERR")),
+try {debug:test-05-cache(true, error(xs:QName("debug:ERR"), "ERR"))} catch * {"ERR"},
+try {debug:test-05-sd(true, error(xs:QName("debug:ERR"), "ERR"))} catch * {"ERR"}
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/lazy-parameters-udf.xq'
--- test/rbkt/Queries/zorba/caching/lazy-parameters-udf.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/lazy-parameters-udf.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,20 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:cache function local:test-05-cache($x as xs:boolean, $y)
+{
+ if ($x)
+ then $y
+ else $x
+};
+
+declare %an:strictlydeterministic function local:test-05-sd($x as xs:boolean, $y)
+{
+ if ($x)
+ then $y
+ else $x
+};
+
+local:test-05-cache(false, error(xs:QName("local:ERR"), "ERR")),
+local:test-05-sd(false, error(xs:QName("local:ERR"), "ERR")),
+try {local:test-05-cache(true, error(xs:QName("local:ERR"), "ERR"))} catch * {"ERR"},
+try {local:test-05-sd(true, error(xs:QName("local:ERR"), "ERR"))} catch * {"ERR"}
=== added file 'test/rbkt/Queries/zorba/caching/simple-01.xq'
--- test/rbkt/Queries/zorba/caching/simple-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/simple-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,36 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare function local:dummy()
+{
+ ()
+};
+
+
+declare %an:cache function local:test-01-cache($x as xs:integer)
+{
+ if ($x < 10)
+ then $x * $x
+ else if ($x < 20)
+ then local:dummy()
+ else ($x, " == ", $x * $x)
+};
+
+
+local:test-01-cache(2),
+"
+",
+local:test-01-cache(12),
+"
+",
+local:test-01-cache(2),
+"
+",
+local:test-01-cache(12),
+"
+",
+local:test-01-cache(22),
+"
+",
+local:test-01-cache(22),
+"
+"
=== added file 'test/rbkt/Queries/zorba/caching/simple-02.xq'
--- test/rbkt/Queries/zorba/caching/simple-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/simple-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,20 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+debug:test-01-cache(2),
+"
+",
+debug:test-01-cache(12),
+"
+",
+debug:test-01-cache(2),
+"
+",
+debug:test-01-cache(12),
+"
+",
+debug:test-01-cache(22),
+"
+",
+debug:test-01-cache(22),
+"
+"
=== added file 'test/rbkt/Queries/zorba/caching/simultaneous-partial-01.xq'
--- test/rbkt/Queries/zorba/caching/simultaneous-partial-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/simultaneous-partial-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,27 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare function local:dummy()
+{
+ ()
+};
+
+
+declare %an:cache function local:test-01-cache($x as xs:integer)
+{
+ if ($x < 10)
+ then $x * $x
+ else if ($x < 20)
+ then local:dummy()
+ else ($x, " == ", $x * $x)
+};
+
+(
+for $i in local:test-01-cache(22)
+where string($i) =
+ string(
+ local:test-01-cache(try {xs:integer($i)} catch * {22})
+ [1])
+return $i
+),
+[local:test-01-cache(22)],
+[local:test-01-cache(484)]
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/simultaneous-partial-02.xq'
--- test/rbkt/Queries/zorba/caching/simultaneous-partial-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/simultaneous-partial-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,13 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+(
+for $i in debug:test-01-cache(22)
+where string($i) =
+ string(
+ debug:test-01-cache(try {xs:integer($i)} catch * {22})
+ [1])
+return $i
+
+),
+[debug:test-01-cache(22)],
+[debug:test-01-cache(484)]
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/snapshots-01.xq'
--- test/rbkt/Queries/zorba/caching/snapshots-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/snapshots-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,21 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:test-03-sd()
+{
+ { "a" : 1 },
+ [1],
+ <a/>,
+ 1
+};
+
+variable $x := (local:test-03-sd(), local:test-03-sd());
+
+
+replace value of json $x[1]("a") with 2;
+append json (2) into $x[2];
+
+fn:deep-equal($x[1], $x[5]),
+fn:deep-equal($x[2], [1,2]),
+fn:deep-equal($x[2], $x[6]),
+($x[3] is $x[7]),
+fn:deep-equal($x[4], $x[8])
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/snapshots-02.xq'
--- test/rbkt/Queries/zorba/caching/snapshots-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/snapshots-02.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,22 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:cache function local:test-03-cache()
+{
+ { "a" : 1 },
+ [1],
+ <a/>,
+ 1
+};
+
+variable $x := local:test-03-cache();
+
+replace value of json $x[1]("a") with 2;
+append json (2) into $x[2];
+
+variable $y := local:test-03-cache();
+
+fn:deep-equal($x[1], $y[1]),
+fn:deep-equal($x[2], [1,2]),
+fn:deep-equal($x[2], $y[2]),
+($x[3] is $y[3]),
+fn:deep-equal($x[4], $y[4])
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/snapshots-03.xq'
--- test/rbkt/Queries/zorba/caching/snapshots-03.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/snapshots-03.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,24 @@
+import module namespace doc = "http://zorba.io/modules/store/documents";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic function local:test-03-sd()
+{
+ { "a" : 1 },
+ [1],
+ <a/>,
+ 1
+};
+
+variable $x := local:test-03-sd();
+doc:put("advance", document { <snapshot/> });
+variable $y := local:test-03-sd();
+
+
+replace value of json $x[1]("a") with 2;
+append json (2) into $x[2];
+
+fn:deep-equal($x[1], $y[1]),
+fn:deep-equal($y[2], [1,2]),
+fn:deep-equal($x[2], $y[2]),
+($x[3] is $y[3]),
+fn:deep-equal($x[4], $y[4])
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/snapshots-04.xq'
--- test/rbkt/Queries/zorba/caching/snapshots-04.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/snapshots-04.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,13 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+variable $x := (debug:test-03-sd(), debug:test-03-sd());
+
+
+replace value of json $x[1]("a") with 2;
+append json (2) into $x[2];
+
+fn:deep-equal($x[1], $x[5]),
+fn:deep-equal($x[2], [1,2]),
+fn:deep-equal($x[2], $x[6]),
+($x[3] is $x[7]),
+fn:deep-equal($x[4], $x[8])
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/snapshots-05.xq'
--- test/rbkt/Queries/zorba/caching/snapshots-05.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/snapshots-05.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,14 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+variable $x := debug:test-03-cache();
+
+replace value of json $x[1]("a") with 2;
+append json (2) into $x[2];
+
+variable $y := debug:test-03-cache();
+
+fn:deep-equal($x[1], $y[1]),
+fn:deep-equal($x[2], [1,2]),
+fn:deep-equal($x[2], $y[2]),
+($x[3] is $y[3]),
+fn:deep-equal($x[4], $y[4])
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/snapshots-06.xq'
--- test/rbkt/Queries/zorba/caching/snapshots-06.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/snapshots-06.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,16 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+import module namespace doc = "http://zorba.io/modules/store/documents";
+
+variable $x := debug:test-03-sd();
+doc:put("advance", document { <snapshot/> });
+variable $y := debug:test-03-sd();
+
+
+replace value of json $x[1]("a") with 2;
+append json (2) into $x[2];
+
+fn:deep-equal($x[1], $y[1]),
+fn:deep-equal($y[2], [1,2]),
+fn:deep-equal($x[2], $y[2]),
+($x[3] is $y[3]),
+fn:deep-equal($x[4], $y[4])
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/streaming-ext-cache-01.xq'
--- test/rbkt/Queries/zorba/caching/streaming-ext-cache-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/streaming-ext-cache-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,5 @@
+declare namespace ann = "http://zorba.io/annotations";
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+debug:test-04-cache(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()}),
+debug:test-04-cache(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()})
=== added file 'test/rbkt/Queries/zorba/caching/streaming-ext-sd-01.xq'
--- test/rbkt/Queries/zorba/caching/streaming-ext-sd-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/streaming-ext-sd-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,5 @@
+declare namespace ann = "http://zorba.io/annotations";
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+debug:test-04-sd(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()}),
+debug:test-04-sd(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()})
=== added file 'test/rbkt/Queries/zorba/caching/streaming-udf-cache-01.xq'
--- test/rbkt/Queries/zorba/caching/streaming-udf-cache-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/streaming-udf-cache-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,15 @@
+declare namespace an = "http://zorba.io/annotations";
+import module namespace debug = "http://zorba.io/modules/util-tests";
+import module namespace http = "http://zorba.io/modules/http-client";
+
+declare %an:cache function local:test-04-cache($x, $y)
+{
+ debug:non-seeakable-streamable-string(),
+ http:send-deterministic-request({ "href": "http://zorbatest.lambda.nu:8080/cgi-bin/test-text"})("body"),
+ serialize($x),
+ serialize($y)
+};
+
+local:test-04-cache(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()}),
+local:test-04-cache(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()}),
+local:test-04-cache(http:send-deterministic-request({ "href": "http://zorbatest.lambda.nu:8080/cgi-bin/test-text"})("body"), 1)
=== added file 'test/rbkt/Queries/zorba/caching/streaming-udf-sd-01.xq'
--- test/rbkt/Queries/zorba/caching/streaming-udf-sd-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/streaming-udf-sd-01.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,15 @@
+declare namespace an = "http://zorba.io/annotations";
+import module namespace debug = "http://zorba.io/modules/util-tests";
+import module namespace http = "http://zorba.io/modules/http-client";
+
+declare %an:strictlydeterministic function local:test-04-cache($x, $y)
+{
+ debug:non-seeakable-streamable-string(),
+ http:send-deterministic-request({ "href": "http://zorbatest.lambda.nu:8080/cgi-bin/test-text"})("body"),
+ serialize($x),
+ serialize($y)
+};
+
+local:test-04-cache(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()}),
+local:test-04-cache(debug:non-seeakable-streamable-string(), {debug:non-seeakable-streamable-string() : debug:non-seeakable-streamable-string()}),
+local:test-04-cache(http:send-deterministic-request({ "href": "http://zorbatest.lambda.nu:8080/cgi-bin/test-text"})("body"), 1)
=== removed file 'test/rbkt/Queries/zorba/collections/.DS_Store'
Binary files test/rbkt/Queries/zorba/collections/.DS_Store 2012-12-10 16:52:21 +0000 and test/rbkt/Queries/zorba/collections/.DS_Store 1970-01-01 00:00:00 +0000 differ
=== added directory 'test/rbkt/Queries/zorba/dctx'
=== added file 'test/rbkt/Queries/zorba/dctx/copy-modify-return.xq'
--- test/rbkt/Queries/zorba/dctx/copy-modify-return.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/copy-modify-return.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,8 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+variable $x := <x/>;
+variable $y := dctx:snapshot-id();
+variable $z :=
+ copy $copy := $x
+ modify rename node $copy as "y"
+ return $copy;
+$y, dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/exit-expression.xq'
--- test/rbkt/Queries/zorba/dctx/exit-expression.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/exit-expression.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,9 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:sequential function local:test()
+{
+ exit returning dctx:snapshot-id();
+};
+
+dctx:snapshot-id(), local:test(), dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/external-sequential-function-call.xq'
--- test/rbkt/Queries/zorba/dctx/external-sequential-function-call.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/external-sequential-function-call.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,6 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+import module namespace file = "http://expath.org/ns/file";
+
+variable $y := dctx:snapshot-id();
+file:write-text("test.txt", "test");
+$y, dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/external-updating-function-call.xq'
--- test/rbkt/Queries/zorba/dctx/external-updating-function-call.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/external-updating-function-call.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,6 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+import module namespace doc = "http://zorba.io/modules/store/documents";
+
+variable $y := dctx:snapshot-id();
+doc:put("foo", document { <foo>bar</foo> });
+$y, dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/global-variables.xq'
--- test/rbkt/Queries/zorba/dctx/global-variables.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/global-variables.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,6 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+
+declare variable $x := 0;
+variable $y := dctx:snapshot-id();
+$x := 1;
+$y, dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/local-variables.xq'
--- test/rbkt/Queries/zorba/dctx/local-variables.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/local-variables.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,11 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+
+variable $a := dctx:snapshot-id();
+variable $x1 := 0;
+$a := ($a, dctx:snapshot-id());
+variable $x2;
+$a := ($a, dctx:snapshot-id());
+$x1:=1;
+$a := ($a, dctx:snapshot-id());
+$x2:=1;
+($a, dctx:snapshot-id())
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/non-sequential-concat.xq'
--- test/rbkt/Queries/zorba/dctx/non-sequential-concat.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/non-sequential-concat.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,3 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+
+(dctx:snapshot-id(),0, dctx:snapshot-id())
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/pul-application.xq'
--- test/rbkt/Queries/zorba/dctx/pul-application.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/pul-application.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,5 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+variable $x := <x/>;
+variable $y := dctx:snapshot-id();
+rename node $x as "y";
+$y, dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/updating-function-call.xq'
--- test/rbkt/Queries/zorba/dctx/updating-function-call.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/updating-function-call.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,11 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+
+declare variable $x := <x/>;
+declare updating function local:update()
+{
+ rename node $x as "y"
+};
+
+variable $y := dctx:snapshot-id();
+local:update();
+$y, dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/variable-declaration.xq'
--- test/rbkt/Queries/zorba/dctx/variable-declaration.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/variable-declaration.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,9 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+
+declare function local:foo()
+{
+ variable $a;
+ 1
+};
+
+dctx:snapshot-id(), local:foo(), dctx:snapshot-id()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/dctx/while-expression.xq'
--- test/rbkt/Queries/zorba/dctx/while-expression.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/dctx/while-expression.xq 2014-04-17 12:18:12 +0000
@@ -0,0 +1,9 @@
+import module namespace dctx = "http://zorba.io/modules/dctx";
+
+variable $x := dctx:snapshot-id();
+variable $i := 0;
+while($i < 3)
+{
+ $i := $i + 1;
+};
+$x, dctx:snapshot-id()
\ No newline at end of file
=== modified file 'test/rbkt/Queries/zorba/updates/upd14.xq'
--- test/rbkt/Queries/zorba/updates/upd14.xq 2013-08-09 08:27:30 +0000
+++ test/rbkt/Queries/zorba/updates/upd14.xq 2014-04-17 12:18:12 +0000
@@ -2,7 +2,7 @@
declare namespace an = "http://zorba.io/annotations";
-declare %an:no-cache %an:sequential function local:test2()
+declare %an:sequential function local:test2()
{
variable $form := validate strict {
<f:form>
References