zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #26980
[Merge] lp:~zorba-coders/zorba/feature-function-caching into lp:zorba
Federico Cavalieri has proposed merging lp:~zorba-coders/zorba/feature-function-caching into lp:zorba.
Requested reviews:
Federico Cavalieri (fcavalieri)
Matthias Brantner (matthias-brantner)
For more details, see:
https://code.launchpad.net/~zorba-coders/zorba/feature-function-caching/+merge/217487
--
https://code.launchpad.net/~zorba-coders/zorba/feature-function-caching/+merge/217487
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-28 18:08:46 +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-28 18:08:46 +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-04-18 18:19:13 +0000
+++ modules/CMakeLists.txt 2014-04-28 18:08:46 +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(sleep)
ADD_SUBDIRECTORY(store)
=== 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +0000
@@ -0,0 +1,250 @@
+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;
+
+(:~
+ : Equivalent to:
+ : declare %an:cache %an:exclude-from-cache-key(2) function local:test-06-cache($x as xs:integer, $y as xs:integer) as xs:integer
+ : {
+ : $x + $y
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:cache %an:exclude-from-cache-key(2) function tests:test-06-cache($x as xs:integer, $y as xs:integer) as xs:integer external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic %an:exclude-from-cache-key(2) function local:test-06-sd($x as xs:integer, $y as xs:integer) as xs:integer
+ : {
+ : $x + $y
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:strictlydeterministic %an:exclude-from-cache-key(2) function tests:test-06-sd($x as xs:integer, $y as xs:integer) as xs:integer external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic %an:compare-with-deep-equal(2) function local:test-07-cache($x as item()*, $y as item()*)
+ : {
+ : serialize({"x" : $x, "y" : $y}),
+ : tests:uuid()
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:cache %an:compare-with-deep-equal(2) function tests:test-07-cache($x as item()*, $y as item()*) external;
+
+(:~
+ : Equivalent to:
+ : declare %an:strictlydeterministic %an:compare-with-deep-equal(2) function local:test-07-sd($x as item()*, $y as item()*)
+ : {
+ : serialize({"x" : $x, "y" : $y}),
+ : tests:uuid()
+ : };
+ :
+ : @param $x as described above
+ : @param $y as described above
+ : @return as described above
+ :)
+declare %an:strictlydeterministic %an:compare-with-deep-equal(2) function tests:test-07-sd($x as item()*, $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-28 18:08:46 +0000
@@ -0,0 +1,433 @@
+/*
+ * 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
+UtilTestsModule::test06(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+{
+ zorba::ItemFactory* lFactory = zorba::Zorba::getInstance(0)->getItemFactory();
+ zorba::Item lX = getOneItemArgument(aArgs, 0);
+ zorba::Item lY = getOneItemArgument(aArgs, 1);
+ zorba::Item lRet = lFactory->createInteger(atoi(lX.getStringValue().str().c_str()) + atoi(lY.getStringValue().str().c_str()));
+
+ return zorba::ItemSequence_t(
+ new zorba::SingletonItemSequence(
+ lRet
+ )
+ );
+}
+
+zorba::ItemSequence_t
+UtilTestsModule::test07(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::vector<std::pair<Item, Item> > lPairs;
+ lPairs.push_back(std::pair<Item, Item>(lFactory->createString("x"), getOneItemArgument(aArgs, 0)));
+ lPairs.push_back(std::pair<Item, Item>(lFactory->createString("y"), getOneItemArgument(aArgs, 1)));
+ Item lObj = lFactory->createJSONObject(lPairs);
+ std::stringstream lSerializedObj;
+ zorba::SingletonItemSequence lSeq(lObj);
+ lSerializer->serialize(lSeq.getIterator(), lSerializedObj);
+ lResult.push_back(lFactory->createString(lSerializedObj.str()));
+
+
+ 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
+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("test-06-cache") == 0)
+ lFunc = new Test06CacheFunction(this);
+ else if (aLocalname.compare("test-06-sd") == 0)
+ lFunc = new Test06SDFunction(this);
+ else if (aLocalname.compare("test-07-cache") == 0)
+ lFunc = new Test07CacheFunction(this);
+ else if (aLocalname.compare("test-07-sd") == 0)
+ lFunc = new Test07SDFunction(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-28 18:08:46 +0000
@@ -0,0 +1,463 @@
+/*
+ * 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;
+
+ zorba::ItemSequence_t
+ test06(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const;
+
+ zorba::ItemSequence_t
+ test07(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 Test06CacheFunction : public TestFunction
+{
+public:
+ Test06CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test06CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-06-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test06(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test06SDFunction : public TestFunction
+{
+public:
+ Test06SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test06SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-06-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test06(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test07CacheFunction : public TestFunction
+{
+public:
+ Test07CacheFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test07CacheFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-07-cache"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test07(aArgs, aSctx, aDctx);
+ }
+};
+
+/******************************************************************************
+ *****************************************************************************/
+class Test07SDFunction : public TestFunction
+{
+public:
+ Test07SDFunction(const UtilTestsModule* aModule) :
+ TestFunction(aModule) {};
+
+ virtual ~Test07SDFunction() {}
+
+ virtual zorba::String
+ getLocalName() const { return "test-07-sd"; }
+
+ zorba::ItemSequence_t
+ evaluate(const Arguments_t& aArgs,
+ const zorba::StaticContext* aSctx,
+ const zorba::DynamicContext* aDctx) const
+ {
+ return theModule->test07(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-28 18:08:46 +0000
@@ -44,7 +44,10 @@
AnnotationInternal::theAnnotName2IdMap(0, NULL, 64, false);
std::vector<AnnotationInternal::RuleBitSet>
-AnnotationInternal::theRuleSet;
+AnnotationInternal::theConflictRuleSet;
+
+std::vector<AnnotationInternal::AnnotationRequirement>
+AnnotationInternal::theRequiredRuleSet;
/*******************************************************************************
@@ -78,12 +81,19 @@
//
- // Zorba annotations - deterministic/nondeterministic
+ // Zorba annotations - strictlydeterministic/deterministic/nondeterministic
//
+ ZANN(strictlydeterministic, strictlydeterministic);
ZANN(deterministic, deterministic);
ZANN(nondeterministic, nondeterministic);
//
+ // Zorba annotations - caching behaviour
+ //
+ ZANN(exclude-from-cache-key, exclude_from_cache_key);
+ ZANN(compare-with-deep-equal, compare_with_deep_equal);
+
+ //
// Zorba annotations - xquery scripting
//
ZANN(assignable, assignable);
@@ -106,7 +116,6 @@
ZANN(streamable, streamable);
ZANN(cache, cache);
- ZANN(no-cache, nocache);
//
// Zorba annotations - xqddf
@@ -135,69 +144,82 @@
#undef ZANN
- // create a set of rules to detect conflicts between annotations
#define ZANN(a) \
( 1 << static_cast<uint64_t>(AnnotationInternal::a) )
- theRuleSet.push_back(
+ // create a set of rules to detect conflicts between annotations
+ theConflictRuleSet.push_back(
ZANN(zann_unique) |
ZANN(zann_nonunique));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_value_equality) |
ZANN(zann_general_equality) |
ZANN(zann_value_range) |
ZANN(zann_general_range));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_automatic) |
ZANN(zann_manual));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_mutable) |
ZANN(zann_queue) |
ZANN(zann_append_only) |
ZANN(zann_const));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_ordered) |
ZANN(zann_unordered));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_assignable) |
ZANN(zann_nonassignable));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
+ ZANN(zann_strictlydeterministic) |
ZANN(zann_deterministic) |
ZANN(zann_nondeterministic));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
+ ZANN(zann_strictlydeterministic) |
+ ZANN(zann_cache));
+
+ theConflictRuleSet.push_back(
ZANN(zann_sequential) |
ZANN(zann_nonsequential));
- theRuleSet.push_back(
- ZANN(zann_cache) |
- ZANN(zann_nocache));
-
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(fn_private) |
ZANN(fn_public));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_unordered) |
ZANN(zann_queue));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_unordered) |
ZANN(zann_append_only));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_queue) |
ZANN(zann_append_only));
- theRuleSet.push_back(
+ theConflictRuleSet.push_back(
ZANN(zann_read_only_nodes) |
ZANN(zann_mutable_nodes));
+
+ // create a set of rules to detect missing requirements between annotations
+ theRequiredRuleSet.push_back(AnnotationRequirement(
+ zann_exclude_from_cache_key,
+ ZANN(zann_cache) | ZANN(zann_strictlydeterministic)
+ ));
+
+ theRequiredRuleSet.push_back(AnnotationRequirement(
+ zann_compare_with_deep_equal,
+ ZANN(zann_cache) | ZANN(zann_strictlydeterministic)
+ ));
+
#undef ZANN
}
@@ -404,13 +426,22 @@
/*******************************************************************************
Called from translator to detect duplicates and conflicting declarations
********************************************************************************/
-void AnnotationList::checkConflictingDeclarations(
+void AnnotationList::checkDeclarations(
DeclarationKind declKind,
const QueryLoc& loc) const
{
// make sure we don't have more annotations then max 64 bit
assert(AnnotationInternal::zann_end < 64);
+ RuleBitSet lDeclaredAnnotations = checkDuplicateDeclarations(declKind, loc);
+ checkConflictingDeclarations(lDeclaredAnnotations, declKind, loc);
+ checkRequiredDeclarations(lDeclaredAnnotations, declKind, loc);
+}
+
+AnnotationList::RuleBitSet AnnotationList::checkDuplicateDeclarations(
+ DeclarationKind declKind,
+ const QueryLoc& loc) const
+{
RuleBitSet lCurrAnn;
// mark and detect duplicates
@@ -435,19 +466,25 @@
ERROR_PARAMS(ZED(XQST0106_Duplicate), qname->getStringValue()));
}
}
-
lCurrAnn.set(id);
}
+ return lCurrAnn;
+}
+void AnnotationList::checkConflictingDeclarations(
+ RuleBitSet currAnn,
+ DeclarationKind declKind,
+ const QueryLoc& loc) const
+{
// check rules
- std::vector<RuleBitSet>::const_iterator ite = AnnotationInternal::theRuleSet.begin();
- std::vector<RuleBitSet>::const_iterator end = AnnotationInternal::theRuleSet.end();
+ std::vector<RuleBitSet>::const_iterator ite = AnnotationInternal::theConflictRuleSet.begin();
+ std::vector<RuleBitSet>::const_iterator end = AnnotationInternal::theConflictRuleSet.end();
for (; ite != end; ++ite)
{
const RuleBitSet& lCurrSet = *ite;
- if ((lCurrAnn & lCurrSet).count() > 1)
+ if ((currAnn & lCurrSet).count() > 1)
{
// build error string to return set of conflicting annotations
std::ostringstream lProblems;
@@ -477,6 +514,52 @@
}
}
+void AnnotationList::checkRequiredDeclarations(
+ RuleBitSet declaredAnn,
+ DeclarationKind declKind,
+ const QueryLoc& loc) const
+{
+ // check rules
+ std::vector<AnnotationRequirement>::const_iterator ite = AnnotationInternal::theRequiredRuleSet.begin();
+ std::vector<AnnotationRequirement>::const_iterator end = AnnotationInternal::theRequiredRuleSet.end();
+
+ for (; ite != end; ++ite)
+ {
+ const AnnotationId& lCurrAnn = ite->first;
+ const RuleBitSet& lCurrSet = ite->second;
+
+ if (declaredAnn.test(lCurrAnn) && (declaredAnn & lCurrSet).count() == 0)
+ {
+ // build error string to return set of required annotations
+ std::ostringstream lProblems;
+ for (csize i = 0, j = 0; i < AnnotationInternal::zann_end; ++i)
+ {
+ if (lCurrSet.test(i))
+ {
+ AnnotationId id = static_cast<AnnotationId>(i);
+ lProblems << AnnotationInternal::lookup(id)->getStringValue()
+ << ((j == lCurrSet.count() - 1) ? "" : ", ");
+ ++j;
+ }
+ }
+
+ if (declKind == var_decl)
+ {
+ RAISE_ERROR(err::XQST0116, loc,
+ ERROR_PARAMS(ZED(XQST0116_Requirement),
+ AnnotationInternal::lookup(lCurrAnn)->getStringValue(),
+ lProblems.str()));
+ }
+ else
+ {
+ RAISE_ERROR(err::XQST0106, loc,
+ ERROR_PARAMS(ZED(XQST0106_Requirement),
+ AnnotationInternal::lookup(lCurrAnn)->getStringValue(),
+ lProblems.str()));
+ }
+ }
+ }
+}
} /* namespace zorba */
/* vim:set et sw=2 ts=2: */
=== modified file 'src/annotations/annotations.h'
--- src/annotations/annotations.h 2013-10-01 03:25:43 +0000
+++ src/annotations/annotations.h 2014-04-28 18:08:46 +0000
@@ -59,6 +59,9 @@
{
fn_public = 0,
fn_private,
+ zann_strictlydeterministic,
+ zann_exclude_from_cache_key,
+ zann_compare_with_deep_equal,
zann_deterministic,
zann_nondeterministic,
zann_assignable,
@@ -68,7 +71,6 @@
zann_propagates_input_nodes,
zann_must_copy_input_nodes,
zann_cache,
- zann_nocache,
zann_variadic,
zann_streamable,
zann_unique,
@@ -94,13 +96,20 @@
protected:
typedef std::bitset<static_cast<int>(zann_end) + 1> RuleBitSet;
+ typedef std::pair<AnnotationId, RuleBitSet> AnnotationRequirement;
protected:
- static std::vector<store::Item_t> theAnnotId2NameMap;
-
- static ItemHandleHashMap<AnnotationId> theAnnotName2IdMap;
-
- static std::vector<RuleBitSet> theRuleSet;
+ static std::vector<store::Item_t> theAnnotId2NameMap;
+ static ItemHandleHashMap<AnnotationId> theAnnotName2IdMap;
+
+ //A conflict is present if for a rule (bitset) 2 or more annotations
+ //are declared
+ static std::vector<RuleBitSet> theConflictRuleSet;
+
+ //A conflict is present if for a rule (pair of annotation and bitset)
+ //the annotation is present and none of the annotations in the bitset
+ //are declared
+ static std::vector<AnnotationRequirement> theRequiredRuleSet;
protected:
AnnotationId theId;
@@ -159,11 +168,10 @@
public:
typedef AnnotationInternal::RuleBitSet RuleBitSet;
-
+ typedef AnnotationInternal::AnnotationRequirement AnnotationRequirement;
typedef AnnotationInternal::AnnotationId AnnotationId;
typedef std::vector<AnnotationInternal*> Annotations;
-
typedef Annotations::size_type size_type;
protected:
@@ -191,7 +199,12 @@
const store::Item_t& qname,
const std::vector<const_expr*>& literals);
- void checkConflictingDeclarations(DeclarationKind k, const QueryLoc& loc) const;
+ void checkDeclarations(DeclarationKind k, const QueryLoc& loc) const;
+
+private:
+ RuleBitSet checkDuplicateDeclarations(DeclarationKind k, const QueryLoc& loc) const;
+ void checkConflictingDeclarations(RuleBitSet bs, DeclarationKind k, const QueryLoc& loc) const;
+ void checkRequiredDeclarations(RuleBitSet bs, DeclarationKind k, const QueryLoc& loc) const;
};
=== modified file 'src/api/dynamiccontextimpl.cpp'
--- src/api/dynamiccontextimpl.cpp 2014-04-25 23:54:56 +0000
+++ src/api/dynamiccontextimpl.cpp 2014-04-28 18:08:46 +0000
@@ -906,7 +906,5 @@
return false;
}
-
-
} // namespace zorba
/* vim:set et sw=2 ts=2: */
=== modified file 'src/api/dynamiccontextimpl.h'
--- src/api/dynamiccontextimpl.h 2014-04-25 23:54:56 +0000
+++ src/api/dynamiccontextimpl.h 2014-04-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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"
@@ -2522,9 +2523,15 @@
}
else if (func->isUdf())
{
- // need to computeResultCaching here for iterprint to work
+ // need to computeCacheSettings here for iterprint to work
user_function* udf = static_cast<user_function*>(func);
- udf->computeResultCaching(theCCB->theXQueryDiagnostics);
+ udf->computeCacheSettings(theCCB->theXQueryDiagnostics);
+ }
+ else if (func->isExternal())
+ {
+ // need to computeCacheSettings here for iterprint to work
+ external_function* extf = static_cast<external_function*>(func);
+ extf->computeCacheSettings(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-28 18:08:46 +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-28 18:08:46 +0000
@@ -1740,6 +1740,7 @@
// Create the inline udf obj.
std::unique_ptr<user_function> inlineUDF(
new user_function(loc,
+ theRootSctx,
signature(function_item_expr::create_inline_fname(loc),
funcType->get_param_types(),
returnType),
@@ -3962,7 +3963,7 @@
if (theAnnotations.get())
{
theAnnotations->
- checkConflictingDeclarations(AnnotationList::var_decl, loc);
+ checkDeclarations(AnnotationList::var_decl, loc);
if (ZANN_CONTAINS(fn_private))
{
@@ -4025,7 +4026,7 @@
annotations->accept(*this);
theAnnotations->
- checkConflictingDeclarations(AnnotationList::func_decl, loc);
+ checkDeclarations(AnnotationList::func_decl, loc);
}
const QueryLoc& loc = func_decl->get_location();
@@ -4204,13 +4205,14 @@
qnameItem->getNamespace(),
sig,
scriptKind,
- ef);
+ ef,
+ theCCB->theXQueryDiagnostics);
}
else
{
// It's a UDF (non-external) function declaration. Create a user_function
// obj with no body for now.
- func = new user_function(loc, sig, NULL, scriptKind, theCCB);
+ func = new user_function(loc, theRootSctx, sig, NULL, scriptKind, theCCB);
}
func->setAnnotations(theAnnotations.get());
@@ -5104,7 +5106,7 @@
}
theAnnotations->
- checkConflictingDeclarations(AnnotationList::collection_decl, loc);
+ checkDeclarations(AnnotationList::collection_decl, loc);
// compute (redundant) enum values and assign
// default annotations if no annotation for a group
@@ -5260,7 +5262,7 @@
if (theAnnotations.get())
{
theAnnotations->
- checkConflictingDeclarations(AnnotationList::index_decl, loc);
+ checkDeclarations(AnnotationList::index_decl, loc);
if (ZANN_CONTAINS(zann_general_equality) ||
ZANN_CONTAINS(zann_general_range))
@@ -6626,7 +6628,7 @@
if (theAnnotations.get())
{
theAnnotations->
- checkConflictingDeclarations(AnnotationList::var_decl, loc);
+ checkDeclarations(AnnotationList::var_decl, loc);
if (ZANN_CONTAINS(zann_assignable))
{
@@ -12720,6 +12722,7 @@
expr* body = CREATE(cast)(theRootSctx, theUDF, loc, argVar, type, false);
udf.reset(new user_function(loc,
+ theRootSctx,
signature(qnameItem, theRTM.ITEM_TYPE_QUESTION, type),
body,
SIMPLE_EXPR,
@@ -12754,6 +12757,7 @@
FunctionConsts::FunctionKind fkind = func->getKind();
udf.reset(new user_function(loc,
+ theRootSctx,
func->getSignature(),
NULL, // no body for now
func->getScriptingKind(),
@@ -13132,6 +13136,7 @@
// Create the udf obj.
std::unique_ptr<user_function> udf(
new user_function(loc,
+ theRootSctx,
signature(function_item_expr::create_inline_fname(loc),
paramTypes,
returnType),
=== 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +0000
@@ -914,6 +914,10 @@
<entry key="Conflicting">
<value>$2: conflicting annotations in declaration</value>
</entry>
+
+ <entry key="Requirement">
+ <value>$2: annotation requires one of the following annotations: $3</value>
+ </entry>
</diagnostic>
<diagnostic code="XQST0111">
@@ -955,6 +959,10 @@
<entry key="Conflicting">
<value>$2: conflicting annotations in declaration</value>
</entry>
+
+ <entry key="Requirement">
+ <value>$2: annotation requires one of the following annotations: $3</value>
+ </entry>
</diagnostic>
<diagnostic code="XQST0120">
@@ -2436,7 +2444,26 @@
<diagnostic code="ZXQP0061" name="DISABLE_HTTP_OPTION_IN_QUERY">
<value>"$1": this option cannot be specified in a query, it must be set via C++ API or command-line parameter</value>
</diagnostic>
-
+
+ <diagnostic code="ZXQP0062" name="MISSING_ANNOTATION_LITERALS">
+ <value>"$1": annotation requires at least one literal</value>
+ </diagnostic>
+
+ <diagnostic code="ZXQP0063" name="INVALID_ANNOTATION_LITERAL_TYPE">
+ <value>"$1": is not a valid annotation literal for annotation "$2", literal has type $3, whereas the allowed types are: $4</value>
+ </diagnostic>
+
+ <diagnostic code="ZXQP0064" name="INVALID_ARGUMENT_INDEX">
+ <value>"$1": is not a valid argument index for function "$2", valid indexes are in the range [1-$3]</value>
+ </diagnostic>
+
+ <diagnostic code="ZXQP0065" name="INVALID_ANNOTATION">
+ <value>"$1": is not a valid annotation for function "$2", $3</value>
+ <entry key="NO_ARGUMENTS">
+ <value>function has no arguments</value>
+ </entry>
+ </diagnostic>
+
<diagnostic code="ZXQP8401" name="THESAURUS_VERSION_MISMATCH"
if="!defined(ZORBA_NO_FULL_TEXT)">
<comment>
@@ -3675,23 +3702,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 +3918,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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +0000
@@ -0,0 +1,463 @@
+/*
+ * 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 "diagnostics/util_macros.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
+{
+
+/*******************************************************************************
+********************************************************************************/
+FunctionCache::FunctionCache(
+ static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual,
+ bool aAcrossSnapshots):
+ FunctionCacheBaseMap(aSctx, aExcludeFromCacheKey, aCompareWithDeepEqual),
+ theAcrossSnapshots(aAcrossSnapshots),
+ theSnapshotID(0)
+{
+}
+
+/*******************************************************************************
+********************************************************************************/
+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),
+ theHasCache(false),
+ theCacheAcrossSnapshots(false),
+ theIsCacheAutomatic(false),
+ theAreCacheSettingsComputed(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.get();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::hasCache() const
+{
+ return theHasCache;
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::cacheAcrossSnapshots() const
+{
+ return theCacheAcrossSnapshots;
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+TypeManager* cacheable_function::getTypeManager()
+{
+ ZORBA_ASSERT(false);
+ return nullptr;
+}
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::computeCacheSettings(XQueryDiagnostics* aDiag)
+{
+ if (theAreCacheSettingsComputed)
+ return;
+
+ theExcludeFromCacheKey = boost::dynamic_bitset<>(theSignature.paramCount());
+ theCompareWithDeepEqual = boost::dynamic_bitset<>(theSignature.paramCount());
+
+ if (!theTypeManager)
+ theTypeManager = getTypeManager();
+
+ ZORBA_ASSERT(theTypeManager);
+
+ if (!theAnnotationList)
+ useDefaultCachingSettings();
+ else if (theAnnotationList->contains(AnnotationInternal::zann_cache))
+ useLegacyCache(aDiag);
+ else if (theAnnotationList->contains(AnnotationInternal::zann_strictlydeterministic))
+ useStrictlyDeterministicCache(aDiag);
+ else if (theAnnotationList->contains(AnnotationInternal::zann_deterministic))
+ theHasCache = false;
+ else
+ useDefaultCachingSettings();
+
+ theAreCacheSettingsComputed = true;
+ theCache.reset(new FunctionCache(
+ theModuleSctx,
+ theExcludeFromCacheKey,
+ theCompareWithDeepEqual,
+ theCacheAcrossSnapshots));
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::useDefaultCachingSettings()
+{
+ if (isVariadic() || isUpdating() || isSequential() || !isDeterministic())
+ {
+ theHasCache = false;
+ }
+ else
+ {
+ if (!haveAtomicArgumentsAndReturnType())
+ {
+ theHasCache = false;
+ }
+ else
+ {
+ theHasCache = 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::useLegacyCache(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)));
+ }
+ theHasCache = 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)));
+ }
+ }
+
+ parseCachingAnnotations(aDiag);
+ theHasCache = 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)));
+ }
+ theHasCache = false;
+ }
+ else
+ {
+ parseCachingAnnotations(aDiag);
+ theHasCache = true;
+ theIsCacheAutomatic = false;
+ theCacheAcrossSnapshots = false;
+ }
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool cacheable_function::disableAutomaticCaching()
+{
+ if (theIsCacheAutomatic)
+ {
+ theHasCache = false;
+ theCache->clear();
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::parseCachingAnnotations(XQueryDiagnostics* aDiag)
+{
+ parseCachingAnnotation(
+ theAnnotationList->get(AnnotationInternal::zann_compare_with_deep_equal),
+ theCompareWithDeepEqual,
+ aDiag);
+ parseCachingAnnotation(
+ theAnnotationList->get(AnnotationInternal::zann_exclude_from_cache_key),
+ theExcludeFromCacheKey,
+ aDiag);
+}
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::parseCachingAnnotation(AnnotationInternal* aAnnotation,
+ boost::dynamic_bitset<>& aBitset,
+ XQueryDiagnostics* aDiag)
+{
+ if (!aAnnotation)
+ return;
+
+ aBitset = boost::dynamic_bitset<>(theSignature.paramCount());
+ csize lNum = aAnnotation->getNumLiterals();
+ if (lNum)
+ {
+ for (csize i=0; i<lNum; ++i)
+ {
+ zorba::store::Item* lLiteral = aAnnotation->getLiteral(i);
+ if (lLiteral->getTypeCode() != store::XS_INTEGER)
+ {
+ RAISE_ERROR(zerr::ZXQP0063_INVALID_ANNOTATION_LITERAL_TYPE, theLoc,
+ ERROR_PARAMS(
+ lLiteral->getStringValue(),
+ lLiteral->getType()->getLocalName(),
+ AnnotationInternal::lookup(aAnnotation->getId())->getStringValue(),
+ "integer"));
+ }
+ else
+ {
+ int lIndex = atoi(lLiteral->getStringValue().c_str());
+ if (lIndex <1 || lIndex>(int)theSignature.paramCount())
+ {
+ std::string lFunctionName = "anonymous";
+ if (theSignature.getName())
+ lFunctionName = theSignature.getName()->getStringValue().str();
+
+ if (theSignature.paramCount())
+ {
+ RAISE_ERROR(zerr::ZXQP0064_INVALID_ARGUMENT_INDEX, theLoc,
+ ERROR_PARAMS(
+ lLiteral->getStringValue(),
+ lFunctionName,
+ theSignature.paramCount()));
+ }
+ else
+ {
+ RAISE_ERROR(zerr::ZXQP0065_INVALID_ANNOTATION, theLoc,
+ ERROR_PARAMS(
+ lLiteral->getStringValue(),
+ lFunctionName,
+ ZED(ZXQP0065_NO_ARGUMENTS)));
+ }
+ }
+ else
+ {
+ aBitset[lIndex-1] = 1;
+ }
+ }
+ }
+ }
+ else
+ {
+ RAISE_ERROR(zerr::ZXQP0062_MISSING_ANNOTATION_LITERALS, theLoc,
+ ERROR_PARAMS(AnnotationInternal::lookup(aAnnotation->getId())->getStringValue()));
+ }
+}
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::saveDynamicBitset(const boost::dynamic_bitset<>& aBitset, ::zorba::serialization::Archiver& ar)
+{
+ size_t lSize = aBitset.size();
+ ar & lSize;
+ bool lValue;
+ for (boost::dynamic_bitset<>::size_type i = 0; i<lSize; ++i)
+ {
+ lValue = (bool)aBitset[i];
+ ar & lValue;
+ }
+}
+
+/*******************************************************************************
+********************************************************************************/
+void cacheable_function::loadDynamicBitset(boost::dynamic_bitset<>& aBitset, ::zorba::serialization::Archiver& ar)
+{
+ size_t lSize = 0;
+ ar & lSize;
+ aBitset.resize(lSize);
+ bool lValue;
+ for (boost::dynamic_bitset<>::size_type i = 0; i<lSize; ++i)
+ {
+ ar & lValue;
+ aBitset[i] = lValue;
+ }
+}
+
+
+}
=== 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-28 18:08:46 +0000
@@ -0,0 +1,135 @@
+/*
+ * 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_cache.h"
+#include "store/api/item_handle.h"
+#include <boost/dynamic_bitset.hpp>
+
+namespace zorba
+{
+class expr;
+
+typedef typename zorba::ItemHandleCacheHashMap< std::vector<store::Item_t> > FunctionCacheBaseMap;
+
+class FunctionCache : public FunctionCacheBaseMap
+{
+public:
+ typedef typename FunctionCacheBaseMap::iterator iterator;
+
+ FunctionCache(static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual,
+ bool 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.
+
+ theHasCache:
+ ----------------
+ Tells whether caching should be done for this udf or not.
+
+ theCacheComputed:
+ -----------------
+ Tells whether theHasCache has been computed already or not.
+ theHasCache is computed by the computeCacheSettings() 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 theHasCache needs to
+ be done only once. So, during the 1st invcocation of computeCacheSettings(),
+ theCacheComputed is set to true, and subsequent invocations are noops.
+********************************************************************************/
+class cacheable_function : public function
+{
+protected:
+ QueryLoc theLoc;
+ TypeManager* theTypeManager;
+ std::auto_ptr<FunctionCache> theCache;
+
+ //
+ // Cache settings
+ //
+ bool theHasCache;
+ bool theCacheAcrossSnapshots;
+ bool theIsCacheAutomatic;
+ bool theAreCacheSettingsComputed;
+ boost::dynamic_bitset<> theExcludeFromCacheKey;
+ boost::dynamic_bitset<> theCompareWithDeepEqual;
+
+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 hasCache() const;
+ bool cacheAcrossSnapshots() const;
+
+ virtual void computeCacheSettings(XQueryDiagnostics* aDiag);
+ virtual bool disableAutomaticCaching();
+
+protected:
+ virtual void useDefaultCachingSettings();
+ virtual void useLegacyCache(XQueryDiagnostics* aDiag);
+ virtual void useStrictlyDeterministicCache(XQueryDiagnostics* aDiag);
+ void saveDynamicBitset(const boost::dynamic_bitset<>& aBitset, ::zorba::serialization::Archiver& ar);
+ void loadDynamicBitset(boost::dynamic_bitset<>& aBitset, ::zorba::serialization::Archiver& ar);
+
+private:
+ virtual bool haveAtomicArgumentsAndReturnType() const;
+ virtual bool isAtomicSequence(const xqtref_t& aType) const;
+ virtual bool haveAllArgumentOneCardinality() const;
+ virtual void parseCachingAnnotations(XQueryDiagnostics* aDiag);
+ virtual void parseCachingAnnotation(AnnotationInternal* aAnnotation,
+ boost::dynamic_bitset<>& aBitSet,
+ XQueryDiagnostics* aDiag);
+
+ 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-28 18:08:46 +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())
{
+ computeCacheSettings(NULL);
ZORBA_ASSERT(theImpl);
lLocalName = Unmarshaller::getInternalString(theImpl->getLocalName());
}
@@ -92,9 +93,36 @@
if (theImpl == NULL)
{
RAISE_ERROR(zerr::ZXQP0008_FUNCTION_IMPL_NOT_FOUND, theLoc,
- ERROR_PARAMS(BUILD_STRING( '{', theNamespace, '}', lLocalName)));
+ ERROR_PARAMS(BUILD_STRING( '{', theNamespace, '}', lLocalName)));
}
}
+
+ ar & theLoc;
+ ar & theHasCache;
+ ar & theCacheAcrossSnapshots;
+
+ if (ar.is_serializing_out())
+ {
+ saveDynamicBitset(theExcludeFromCacheKey, ar);
+ saveDynamicBitset(theCompareWithDeepEqual, ar);
+ }
+ else
+ {
+ loadDynamicBitset(theExcludeFromCacheKey, ar);
+ loadDynamicBitset(theCompareWithDeepEqual, ar);
+ }
+
+ ar & theAreCacheSettingsComputed;
+ ar & theIsCacheAutomatic;
+
+ if (!ar.is_serializing_out())
+ {
+ theCache.reset(new FunctionCache(
+ theModuleSctx,
+ theExcludeFromCacheKey,
+ theCompareWithDeepEqual,
+ theCacheAcrossSnapshots));
+ }
}
@@ -174,7 +202,6 @@
return true;
}
-
/*******************************************************************************
********************************************************************************/
@@ -188,12 +215,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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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
{
@@ -57,24 +54,22 @@
********************************************************************************/
user_function::user_function(
const QueryLoc& loc,
+ static_context* sctx,
const signature& sig,
expr* expr_body,
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)
{
+ theModuleSctx = sctx;
setFlag(FunctionConsts::isUDF);
setPrivate(false);
}
@@ -85,7 +80,7 @@
********************************************************************************/
user_function::user_function(::zorba::serialization::Archiver& ar)
:
- function(ar)
+ cacheable_function(ar)
{
setFlag(FunctionConsts::isUDF);
resetFlag(FunctionConsts::isBuiltin);
@@ -113,7 +108,7 @@
getPlan(planStateSize, 1);
ZORBA_ASSERT(thePlan != NULL);
- computeResultCaching(theCCB->theXQueryDiagnostics);
+ computeCacheSettings(theCCB->theXQueryDiagnostics);
if (theCCB->theHasEval)
{
@@ -181,8 +176,30 @@
ar & thePlanStateSize;
ar & theArgVarsRefs;
- ar & theCacheResults;
- ar & theCacheComputed;
+ ar & theLoc;
+ ar & theHasCache;
+ ar & theCacheAcrossSnapshots;
+ if (ar.is_serializing_out())
+ {
+ saveDynamicBitset(theExcludeFromCacheKey, ar);
+ saveDynamicBitset(theCompareWithDeepEqual, ar);
+ }
+ else
+ {
+ loadDynamicBitset(theExcludeFromCacheKey, ar);
+ loadDynamicBitset(theCompareWithDeepEqual, ar);
+ }
+ ar & theAreCacheSettingsComputed;
+ ar & theIsCacheAutomatic;
+
+ if (!ar.is_serializing_out())
+ {
+ theCache.reset(new FunctionCache(
+ theModuleSctx,
+ theExcludeFromCacheKey,
+ theCompareWithDeepEqual,
+ theCacheAcrossSnapshots));
+ }
}
@@ -231,8 +248,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 +601,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())
+ theHasCache = 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-28 18:08:46 +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);
@@ -150,6 +119,7 @@
public:
user_function(
const QueryLoc& loc,
+ static_context* sctx,
const signature& sig,
expr* expr_body,
unsigned short scriptingKind,
@@ -159,8 +129,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 +141,8 @@
expr* getBody() const;
+ virtual TypeManager* getTypeManager();
+
void setScriptingKind(unsigned short k);
csize numArgs() const { return theArgVars.size(); }
@@ -237,13 +207,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/CMakeLists.txt'
--- src/runtime/CMakeLists.txt 2014-02-25 00:14:59 +0000
+++ src/runtime/CMakeLists.txt 2014-04-28 18:08:46 +0000
@@ -136,6 +136,7 @@
numerics/format_integer.cpp
numerics/format_number.cpp
sequences/SequencesImpl.cpp
+ sequences/deep_equality.cpp
visitors/iterprinter.cpp
update/update.cpp
util/item_iterator.cpp
=== 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-28 18:08:46 +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-28 18:08:46 +0000
@@ -49,7 +49,7 @@
bool next(store::Item_t&);
- void reset() {}
+ void reset();
void close() {}
=== modified file 'src/runtime/booleans/BooleanImpl.cpp'
--- src/runtime/booleans/BooleanImpl.cpp 2014-02-12 02:25:45 +0000
+++ src/runtime/booleans/BooleanImpl.cpp 2014-04-28 18:08:46 +0000
@@ -533,11 +533,11 @@
{
case CompareConsts::VALUE_EQUAL:
{
- return valueEqual(loc, aItem0, aItem1, typemgr, timezone, aCollation);
+ return valueEqual(loc, aItem0, aItem1, typemgr, timezone, aCollation, true);
}
case CompareConsts::VALUE_NOT_EQUAL:
{
- return ! valueEqual(loc, aItem0, aItem1, typemgr, timezone, aCollation);
+ return ! valueEqual(loc, aItem0, aItem1, typemgr, timezone, aCollation, true);
}
case CompareConsts::VALUE_GREATER:
{
@@ -592,11 +592,14 @@
store::Item_t& aItem1,
const TypeManager* typemgr,
long timezone,
- XQPCollator* aCollation)
+ XQPCollator* aCollation,
+ bool raiseError)
{
store::Item_t castItem0, castItem1;
- valueCasting(loc, typemgr, aItem0, aItem1, castItem0, castItem1);
- return equal(loc, castItem0, castItem1, typemgr, timezone, aCollation);
+ if (valueCasting(loc, typemgr, aItem0, aItem1, castItem0, castItem1, raiseError))
+ return equal(loc, castItem0, castItem1, typemgr, timezone, aCollation, raiseError);
+ else
+ return false;
}
@@ -612,7 +615,7 @@
XQPCollator* aCollation)
{
store::Item_t castItem0, castItem1;
- valueCasting(loc, typemgr, aItem0, aItem1, castItem0, castItem1);
+ valueCasting(loc, typemgr, aItem0, aItem1, castItem0, castItem1, true);
return compare(loc, castItem0, castItem1, typemgr, timezone, aCollation);
}
@@ -620,13 +623,14 @@
/*******************************************************************************
********************************************************************************/
-void CompareIterator::valueCasting(
+bool CompareIterator::valueCasting(
const QueryLoc& loc,
const TypeManager* tm,
store::Item_t& item0,
store::Item_t& item1,
store::Item_t& castItem0,
- store::Item_t& castItem1)
+ store::Item_t& castItem1,
+ bool raiseError)
{
store::SchemaTypeCode type0 = item0->getTypeCode();
store::SchemaTypeCode type1 = item1->getTypeCode();
@@ -641,7 +645,8 @@
}
else
{
- GenericCast::castToBuiltinAtomic(castItem0, item0, store::XS_STRING, NULL, loc);
+ if (!GenericCast::castToBuiltinAtomic(castItem0, item0, store::XS_STRING, NULL, loc, raiseError))
+ return false;
if (!GenericCast::promote(castItem1, item1, store::XS_STRING, NULL, tm, loc))
castItem1.transfer(item1);
@@ -652,7 +657,8 @@
if (!GenericCast::promote(castItem0, item0, store::XS_STRING, NULL, tm, loc))
castItem0.transfer(item0);
- GenericCast::castToBuiltinAtomic(castItem1, item1, store::XS_STRING, NULL, loc);
+ if (!GenericCast::castToBuiltinAtomic(castItem1, item1, store::XS_STRING, NULL, loc, raiseError))
+ return false;
}
else
{
@@ -662,6 +668,7 @@
if (!GenericCast::promote(castItem1, item1, type0, NULL, tm, loc))
castItem1.transfer(item1);
}
+ return true;
}
@@ -760,7 +767,7 @@
{
store::Item_t castItem0, castItem1;
generalCasting(loc, typemgr, aItem0, aItem1, castItem0, castItem1);
- return equal(loc, castItem0, castItem1, typemgr, timezone, aCollation);
+ return equal(loc, castItem0, castItem1, typemgr, timezone, aCollation, true);
}
@@ -882,7 +889,8 @@
const store::Item_t& item1,
const TypeManager* tm,
long timezone,
- XQPCollator* collation)
+ XQPCollator* collation,
+ bool raiseError)
{
store::SchemaTypeCode type0 = item0->getTypeCode();
store::SchemaTypeCode type1 = item1->getTypeCode();
@@ -928,7 +936,7 @@
{
return item1->equals(item0);
}
- else
+ else if (raiseError)
{
xqtref_t type0 = tm->create_value_type(item0.getp());
xqtref_t type1 = tm->create_value_type(item1.getp());
@@ -936,6 +944,8 @@
RAISE_ERROR(err::XPTY0004, loc,
ERROR_PARAMS(ZED(BadType_23o), *type0, ZED(NoCompareWithType_4), *type1));
}
+ else
+ return false;
}
}
@@ -1261,7 +1271,8 @@
lItem1,
theTypeManager,
theTimezone,
- theCollation);
+ theCollation,
+ true);
}
catch (ZorbaException const& e)
{
=== modified file 'src/runtime/booleans/BooleanImpl.h'
--- src/runtime/booleans/BooleanImpl.h 2014-02-12 02:25:45 +0000
+++ src/runtime/booleans/BooleanImpl.h 2014-04-28 18:08:46 +0000
@@ -188,7 +188,8 @@
store::Item_t& aItem1,
const TypeManager* typemgr,
long timezone,
- XQPCollator* aCollation);
+ XQPCollator* aCollation,
+ bool raiseError);
static long valueCompare(
const QueryLoc& loc,
@@ -229,7 +230,8 @@
const store::Item_t& aItem1,
const TypeManager* typemgr,
long timezone,
- XQPCollator* aCollation);
+ XQPCollator* aCollation,
+ bool raiseError);
static long compare(
const QueryLoc& loc,
@@ -240,13 +242,14 @@
XQPCollator* aCollation);
private:
- static void valueCasting(
+ static bool valueCasting(
const QueryLoc& loc,
const TypeManager* typemgr,
store::Item_t& aItem0,
store::Item_t& aItem1,
store::Item_t& castItem0,
- store::Item_t& castItem1);
+ store::Item_t& castItem1,
+ bool raiseError);
static void generalCasting(
const QueryLoc& loc,
=== 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-28 18:08:46 +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-28 18:08:46 +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())
+ return theUDF->hasCache();
+}
+
+/*******************************************************************************
+********************************************************************************/
+bool UDFunctionCallIterator::isCacheAcrossSnapshots() const
+{
+ return theUDF->cacheAcrossSnapshots();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+void UDFunctionCallIterator::initCache(
+ PlanState& aPlanState,
+ UDFunctionCallIteratorState* aState)
+{
+ if (!aState->theCache && theUDF->hasCache())
{
- 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->hasCache())
+ 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
@@ -888,9 +934,12 @@
}
ar & theIsUpdating;
+ ar & theIsSequential;
}
+/*******************************************************************************
+********************************************************************************/
void ExtFunctionCallIterator::openImpl(PlanState& planState, uint32_t& offset)
{
NaryBaseIterator<ExtFunctionCallIterator,
@@ -899,80 +948,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 +1033,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 +1286,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->hasCache();
+}
+
+
+/*******************************************************************************
+********************************************************************************/
+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-28 18:08:46 +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/gflwor/common.cpp'
--- src/runtime/core/gflwor/common.cpp 2013-02-07 17:24:36 +0000
+++ src/runtime/core/gflwor/common.cpp 2014-04-28 18:08:46 +0000
@@ -251,7 +251,8 @@
tmp2,
theTypeManager,
theTimezone,
- (*iter3).theCollator))
+ (*iter3).theCollator,
+ true))
{
return false;
}
=== 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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);
}
=== modified file 'src/runtime/seq/seq_util.h'
--- src/runtime/seq/seq_util.h 2013-10-01 23:33:19 +0000
+++ src/runtime/seq/seq_util.h 2014-04-28 18:08:46 +0000
@@ -43,7 +43,7 @@
bool operator()( store::Item *i, store::Item *j ) const {
store::Item_t it( i ), jt( j );
- return CompareIterator::valueEqual( loc_, it, jt, tm_, tz_, coll_ );
+ return CompareIterator::valueEqual( loc_, it, jt, tm_, tz_, coll_, true );
}
private:
=== added file 'src/runtime/sequences/deep_equality.cpp'
--- src/runtime/sequences/deep_equality.cpp 1970-01-01 00:00:00 +0000
+++ src/runtime/sequences/deep_equality.cpp 2014-04-28 18:08:46 +0000
@@ -0,0 +1,788 @@
+/*
+ * 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 <string>
+#include <fstream>
+#include <vector>
+#include <algorithm>
+#include <sstream>
+
+#include "deep_equality.h"
+#include "diagnostics/xquery_diagnostics.h"
+#include "diagnostics/util_macros.h"
+
+#include "zorbatypes/decimal.h"
+#include "zorbatypes/URI.h"
+#include "zorbamisc/ns_consts.h"
+#include "zorbautils/fatal.h"
+
+// For timing
+#include <zorba/util/time.h>
+
+#include <zorba/util/transcode_stream.h>
+
+#include <util/fs_util.h>
+#include <util/uri_util.h>
+
+#include <compiler/api/compilercb.h>
+
+#include <runtime/sequences/sequences.h>
+#include <runtime/core/arithmetic_impl.h>
+#include <runtime/util/iterator_impl.h>
+#include <runtime/visitors/planiter_visitor.h>
+#include <runtime/util/doc_uri_heuristics.h>
+
+#include <system/globalenv.h>
+
+#include <types/casting.h>
+#include <types/typeops.h>
+#include <types/typeimpl.h>
+
+#include <store/api/store.h>
+#include <store/api/iterator.h>
+#include <store/api/item_factory.h>
+#include "store/api/temp_seq.h"
+#include <store/api/pul.h>
+
+#include <context/static_context.h>
+
+#include "zorbautils/hashset_node_itemh.h"
+#include "zorbautils/hashset_atomic_itemh.h"
+namespace zorba
+{
+namespace equality
+{
+
+bool deepEqualChildren(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it1,
+ const store::Iterator_t& it2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError)
+{
+ store::Item_t child1, child2;
+ bool c1Valid, c2Valid;
+
+ it1->open();
+ it2->open();
+
+ while (1)
+ {
+ while ((c1Valid = it1->next(child1)) &&
+ (child1->getNodeKind() == store::StoreConsts::piNode ||
+ child1->getNodeKind() == store::StoreConsts::commentNode))
+ ;
+
+ while ((c2Valid = it2->next(child2)) &&
+ (child2->getNodeKind() == store::StoreConsts::piNode ||
+ child2->getNodeKind() == store::StoreConsts::commentNode))
+ ;
+
+ if (!c1Valid && !c2Valid)
+ return true;
+ else if (!c1Valid || !c2Valid)
+ return false;
+ else if (!deepEqual(loc, sctx, child1, child2, collator, timezone, raiseError))
+ return false;
+ }
+
+ return true;
+}
+
+
+bool deepEqualAttributes(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it1,
+ const store::Iterator_t& it2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError)
+{
+ store::Item_t child1, child2;
+ int c1count = 0, c2count = 0;
+
+ it1->open();
+ it2->open();
+
+ while (it1->next(child1))
+ {
+ c1count++;
+
+ it2->reset();
+
+ bool found = false;
+ while (it2->next(child2))
+ {
+ if (deepEqual(loc, sctx, child1, child2, collator, timezone, raiseError))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return false;
+ }
+
+ it2->reset();
+ while (it2->next(child2))
+ c2count++;
+
+ if (c1count != c2count)
+ return false;
+
+ return true;
+}
+
+
+bool deepEqualNodes(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item1,
+ const store::Item* item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError)
+{
+ if (item1->getNodeKind() != item2->getNodeKind())
+ return false;
+
+ switch (item1->getNodeKind())
+ {
+ case store::StoreConsts::documentNode:
+ {
+ return deepEqualChildren(loc,
+ sctx,
+ item1->getChildren(),
+ item2->getChildren(),
+ collator,
+ timezone,
+ raiseError);
+ break;
+ }
+ case store::StoreConsts::elementNode:
+ {
+ if (! item1->getNodeName()->equals(item2->getNodeName()))
+ return false;
+
+ if (!deepEqualAttributes(loc,
+ sctx,
+ item1->getAttributes(),
+ item2->getAttributes(),
+ collator,
+ timezone,
+ raiseError))
+ return false;
+
+ if (item1->haveSimpleContent())
+ {
+ if (!item2->haveSimpleContent())
+ return false;
+
+ store::Item_t value1, value2;
+ store::Iterator_t ite1, ite2;
+ item1->getTypedValue(value1, ite1);
+ item2->getTypedValue(value2, ite2);
+
+ if (ite1 == NULL && ite2 == NULL)
+ {
+ return deepEqual(loc, sctx, value1, value2, collator, timezone, raiseError);
+ }
+ else if (ite1 != NULL && ite2 != NULL)
+ {
+ ite1->open();
+ ite2->open();
+
+ while (1)
+ {
+ bool c1Valid = ite1->next(value1);
+ bool c2Valid = ite2->next(value2);
+
+ if (!c1Valid && !c2Valid)
+ return true;
+ else if (!c1Valid || !c2Valid)
+ return false;
+ else if (!deepEqual(loc, sctx, value1, value2, collator, timezone, raiseError))
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (item2->haveSimpleContent())
+ {
+ return false;
+ }
+ else
+ {
+ store::Item* typename1 = item1->getType();
+ store::Item* typename2 = item2->getType();
+
+ if (typename1->equals(typename2))
+ {
+ return deepEqualChildren(loc,
+ sctx,
+ item1->getChildren(),
+ item2->getChildren(),
+ collator,
+ timezone,
+ raiseError);
+ }
+ else
+ {
+ TypeManager* tm = sctx->get_typemanager();
+
+ xqtref_t type1 =
+ tm->create_named_type(typename1, SequenceType::QUANT_ONE, loc, raiseError);
+
+ xqtref_t type2 =
+ tm->create_named_type(typename2, SequenceType::QUANT_ONE, loc, raiseError);
+
+ ZORBA_ASSERT(type1->isComplex() && type2->isComplex());
+
+ if (type1->contentKind() != type2->contentKind())
+ return false;
+
+ return deepEqualChildren(loc,
+ sctx,
+ item1->getChildren(),
+ item2->getChildren(),
+ collator,
+ timezone,
+ raiseError);
+ }
+ }
+ break;
+ }
+ case store::StoreConsts::attributeNode:
+ {
+ if (! item1->getNodeName()->equals(item2->getNodeName()))
+ return false;
+
+ store::Item_t value1, value2;
+ store::Iterator_t ite1, ite2;
+ item1->getTypedValue(value1, ite1);
+ item2->getTypedValue(value2, ite2);
+
+ if (ite1 == NULL && ite2 == NULL)
+ {
+ return deepEqual(loc, sctx, value1, value2, collator, timezone, raiseError);
+ }
+ else if (ite1 != NULL && ite2 != NULL)
+ {
+ ite1->open();
+ ite2->open();
+
+ while (1)
+ {
+ bool c1Valid = ite1->next(value1);
+ bool c2Valid = ite2->next(value2);
+
+ if (!c1Valid && !c2Valid)
+ return true;
+ else if (!c1Valid || !c2Valid)
+ return false;
+ else if (!deepEqual(loc, sctx, value1, value2, collator, timezone, raiseError))
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+ break;
+ }
+ case store::StoreConsts::textNode:
+ case store::StoreConsts::commentNode:
+ {
+ return (0 == utf8::compare(item1->getStringValue(),
+ item2->getStringValue(),
+ collator));
+ }
+
+ case store::StoreConsts::piNode:
+ {
+ if (utf8::compare(item1->getNodeName()->getStringValue(),
+ item2->getNodeName()->getStringValue(),
+ collator))
+ return false;
+
+ return (0 == utf8::compare(item1->getStringValue(),
+ item2->getStringValue(),
+ collator));
+ }
+
+ case store::StoreConsts::namespaceNode:
+ {
+ if (utf8::compare(item1->getNamespacePrefix(),
+ item2->getNamespacePrefix(),
+ collator))
+ return false;
+
+ return (0 == utf8::compare(item1->getStringValue(),
+ item2->getStringValue(),
+ collator));
+ }
+ default:
+ ZORBA_ASSERT(false);
+ }
+
+ return true;
+}
+
+
+bool deepEqualObjects(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item1,
+ const store::Item* item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError)
+{
+ assert(item1->isObject());
+ assert(item2->isObject());
+
+ if (item1->getNumObjectPairs() != item2->getNumObjectPairs())
+ return false;
+
+ store::Iterator_t lKeys = item1->getObjectKeys();
+ lKeys->open();
+
+ store::Item_t lKey, lValue1, lValue2;
+
+ while (lKeys->next(lKey))
+ {
+ lValue2 = item2->getObjectValue(lKey);
+
+ if (lValue2 == NULL)
+ return false;
+
+ lValue1 = item1->getObjectValue(lKey);
+
+ if (!deepEqual(loc, sctx, lValue1, lValue2, collator, timezone, raiseError))
+ return false;
+ }
+
+ return true;
+}
+
+
+bool deepEqualArrays(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item1,
+ const store::Item* item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError)
+{
+ assert(item1->isArray());
+ assert(item2->isArray());
+
+ if (item1->getArraySize() != item2->getArraySize())
+ return false;
+
+ store::Iterator_t lValues1 = item1->getArrayValues();
+ store::Iterator_t lValues2 = item2->getArrayValues();
+ lValues1->open();
+ lValues2->open();
+
+ store::Item_t lValue1, lValue2;
+
+ while (lValues1->next(lValue1) && lValues2->next(lValue2))
+ {
+ if (!deepEqual(loc, sctx, lValue1, lValue2, collator, timezone, raiseError))
+ return false;
+ }
+
+ return true;
+}
+
+
+bool deepEqual(
+ const QueryLoc& loc,
+ static_context* sctx,
+ store::Item_t& item1,
+ store::Item_t& item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError)
+{
+ if (item1->isFunction() || item2->isFunction())
+ {
+ if (raiseError)
+ {
+ RAISE_ERROR(err::FOTY0015, loc,
+ ERROR_PARAMS((item1->isFunction() ? item1 : item2)->getFunctionName()->getStringValue()));
+ }
+ else
+ return false;
+ }
+
+ if (item1->getKind() != item2->getKind())
+ return false;
+
+ switch (item1->getKind())
+ {
+ case store::Item::ATOMIC:
+ {
+ assert(item2->isAtomic());
+
+ store::SchemaTypeCode type1 = item1->getTypeCode();
+ store::SchemaTypeCode type2 = item2->getTypeCode();
+
+ // check if both items are NaN
+ if (((type1 == store::XS_FLOAT && item1->getFloatValue().isNaN()) ||
+ (type1 == store::XS_DOUBLE && item1->getDoubleValue().isNaN()))
+ &&
+ ((type2 == store::XS_FLOAT && item2->getFloatValue().isNaN()) ||
+ (type2 == store::XS_DOUBLE && item2->getDoubleValue().isNaN())))
+ {
+ return true;
+ }
+
+ if (raiseError)
+ {
+ try
+ {
+ TypeManager* tm = sctx->get_typemanager();
+ return CompareIterator::valueEqual(loc, item1, item2, tm, timezone, collator, raiseError);
+ }
+ catch (ZorbaException const& e)
+ {
+ if (e.diagnostic() == err::XPTY0004)
+ return false;
+ throw;
+ }
+ }
+ else
+ {
+ TypeManager* tm = sctx->get_typemanager();
+ return CompareIterator::valueEqual(loc, item1, item2, tm, timezone, collator, raiseError);
+ }
+
+ break;
+ }
+ case store::Item::NODE:
+ {
+ return deepEqualNodes(loc, sctx, item1, item2, collator, timezone, raiseError);
+ }
+ case store::Item::OBJECT:
+ {
+ return deepEqualObjects(loc, sctx, item1, item2, collator, timezone, raiseError);
+ }
+ case store::Item::ARRAY:
+ {
+ return deepEqualArrays(loc, sctx, item1, item2, collator, timezone, raiseError);
+ }
+ default:
+ {
+ ZORBA_ASSERT(false); // should never reach here
+ }
+ }
+
+ return false;
+}
+
+uint32_t deHashChildren(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it,
+ XQPCollator* collator,
+ int timezone)
+{
+ uint32_t lHash = FNV_32_INIT;
+ uint32_t lInnerHash;
+ store::Item_t child;
+ it->open();
+
+ while (it->next(child))
+ {
+ if (child->getNodeKind() == store::StoreConsts::piNode
+ ||
+ child->getNodeKind() == store::StoreConsts::commentNode)
+ continue;
+
+ lInnerHash = deHash(loc, sctx, child, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+
+ return lHash;
+}
+
+
+uint32_t deHashAttributes(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it,
+ XQPCollator* collator,
+ int timezone)
+{
+ uint32_t lHash = FNV_32_INIT;
+ std::vector<uint32_t> lInnerHashes;
+ store::Item_t attr;
+
+ it->open();
+ while (it->next(attr))
+ {
+ lInnerHashes.push_back(deHash(loc, sctx, attr, collator, timezone));
+ }
+
+ std::sort(lInnerHashes.begin(), lInnerHashes.end());
+ for(std::vector<uint32_t>::iterator it = lInnerHashes.begin(); it != lInnerHashes.end(); ++it)
+ {
+ lHash = hashfun::h32(&(*it), sizeof(*it), lHash);
+ }
+
+ return lHash;
+}
+
+
+uint32_t deHashNode(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone)
+{
+ uint32_t lHash = FNV_32_INIT;
+ uint32_t lInnerHash;
+
+ store::NodeKind lNodeKind = item->getNodeKind();
+ lHash = hashfun::h32(&lNodeKind, sizeof(lNodeKind), lHash);
+
+ switch (item->getNodeKind())
+ {
+ case store::StoreConsts::documentNode:
+ {
+ lInnerHash = equality::deHashChildren(loc, sctx, item->getChildren(), collator, timezone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::StoreConsts::elementNode:
+ {
+ lInnerHash = item->getNodeName()->hash();
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ lInnerHash = deHashAttributes(loc, sctx, item->getAttributes(), collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ bool lHaveSimpleContent = item->haveSimpleContent();
+ lHash = hashfun::h32(&lHaveSimpleContent, sizeof(lHaveSimpleContent), lHash);
+
+ if (lHaveSimpleContent)
+ {
+ store::Item_t value;
+ store::Iterator_t ite;
+ item->getTypedValue(value, ite);
+ if (value)
+ {
+ lInnerHash = deHash(loc, sctx, value, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ else if (ite)
+ {
+ ite->open();
+ while (ite->next(value))
+ {
+ lInnerHash = deHash(loc, sctx, value, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ }
+ return lHash;
+ }
+ else
+ {
+ lInnerHash = deHashChildren(loc, sctx, item->getChildren(), collator, timezone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ }
+ case store::StoreConsts::attributeNode:
+ {
+ lInnerHash = item->getNodeName()->hash();
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ store::Item_t value;
+ store::Iterator_t ite;
+ item->getTypedValue(value, ite);
+ if (value)
+ {
+ lInnerHash = deHash(loc, sctx, value, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ else if (ite)
+ {
+ ite->open();
+ while (ite->next(value))
+ {
+ lInnerHash = deHash(loc, sctx, value, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ }
+ return lHash;
+ }
+ case store::StoreConsts::textNode:
+ case store::StoreConsts::commentNode:
+ {
+ zstring lStringValue = item->getStringValue();
+ return hashfun::h32(&lStringValue, sizeof(lStringValue), lHash);
+ }
+ case store::StoreConsts::piNode:
+ {
+ lInnerHash = item->getNodeName()->hash();
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ zstring lStringValue = item->getStringValue();
+ return hashfun::h32(&lStringValue, sizeof(lStringValue), lHash);
+ }
+
+ case store::StoreConsts::namespaceNode:
+ {
+ zstring lNamespacePrefix = item->getNamespacePrefix();
+ lHash = hashfun::h32(&lNamespacePrefix, sizeof(lNamespacePrefix), lHash);
+ zstring lStringValue = item->getStringValue();
+ return hashfun::h32(&lStringValue, sizeof(lStringValue), lHash);
+ }
+ default:
+ {
+ /*
+ * The type of the item is one of:
+ * PUL, FUNCTION, ERROR_
+ */
+ return FNV_32_INIT;
+ }
+ }
+
+ return true;
+}
+
+struct ObjectKeyPred
+{
+ bool operator()(store::Item_t const& a, store::Item_t const& b) const
+ {
+ return a->getString() < b->getString();
+ }
+};
+
+uint32_t deHashObject(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone)
+{
+ uint32_t lHash = FNV_32_INIT;
+ uint32_t lInnerHash;
+ std::vector<store::Item_t> lKeysVec;
+ store::Iterator_t lKeys = item->getObjectKeys();
+ store::Item_t lKey;
+ lKeys->open();
+
+ while (lKeys->next(lKey))
+ {
+ lKeysVec.push_back(lKey);
+ }
+
+ std::sort(lKeysVec.begin(), lKeysVec.end(), ObjectKeyPred());
+ for(std::vector<store::Item_t>::iterator it = lKeysVec.begin(); it != lKeysVec.end(); ++it)
+ {
+ lInnerHash = deHash(loc, sctx, *it, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+
+ return lHash;
+}
+
+
+uint32_t deHashArray(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone)
+{
+ uint32_t lHash = FNV_32_INIT;
+ uint32_t lInnerHash;
+
+ store::Iterator_t lValues = item->getArrayValues();
+ store::Item_t lValue;
+ lValues->open();
+
+ while (lValues->next(lValue))
+ {
+ lInnerHash = deHash(loc, sctx, lValue, collator, timezone);
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+
+ return lHash;
+}
+
+
+uint32_t deHash(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone)
+{
+ store::Item::ItemKind lKind = item->getKind();
+ uint32_t lHash = hashfun::h32(&lKind, sizeof(store::Item::ItemKind), FNV_32_INIT);
+ uint32_t lInnerHash;
+
+ switch (item->getKind())
+ {
+ case store::Item::ATOMIC:
+ {
+ store::SchemaTypeCode type = item->getTypeCode();
+ lHash = hashfun::h32(&type, sizeof(type), lHash);
+ lInnerHash = item->hash(timezone, collator);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::Item::NODE:
+ {
+ lInnerHash = deHashNode(loc, sctx, item, collator, timezone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::Item::OBJECT:
+ {
+ lInnerHash = deHashObject(loc, sctx, item, collator, timezone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::Item::ARRAY:
+ {
+ lInnerHash = deHashArray(loc, sctx, item, collator, timezone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ default:
+ {
+ /*
+ * The type of the item is one of:
+ * PUL, FUNCTION, ERROR_
+ */
+ return FNV_32_INIT;
+ }
+ }
+
+ return false;
+}
+
+
+
+}
+}
=== added file 'src/runtime/sequences/deep_equality.h'
--- src/runtime/sequences/deep_equality.h 1970-01-01 00:00:00 +0000
+++ src/runtime/sequences/deep_equality.h 2014-04-28 18:08:46 +0000
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+#ifndef ZORBA_DEEP_EQUALITY_H
+#define ZORBA_DEEP_EQUALITY_H
+
+#include "common/shared_types.h"
+#include "store/api/iterator.h"
+
+namespace zorba
+{
+
+namespace equality
+{
+
+bool deepEqual(
+ const QueryLoc& loc,
+ static_context* sctx,
+ store::Item_t& item1,
+ store::Item_t& item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError);
+
+bool deepEqualChildren(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it1,
+ const store::Iterator_t& it2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError);
+
+bool deepEqualAttributes(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it1,
+ const store::Iterator_t& it2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError);
+
+bool deepEqualNodes(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item1,
+ const store::Item* item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError);
+
+bool deepEqualObjects(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item1,
+ const store::Item* item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError);
+
+bool deepEqualArrays(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item1,
+ const store::Item* item2,
+ XQPCollator* collator,
+ int timezone,
+ bool raiseError);
+
+uint32_t deHash(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone);
+
+uint32_t deHashChildren(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it,
+ XQPCollator* collator,
+ int timezone);
+
+uint32_t deHashAttributes(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Iterator_t& it,
+ XQPCollator* collator,
+ int timezone);
+
+uint32_t deHashNode(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone);
+
+uint32_t deHashObject(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone);
+
+uint32_t deHashArray(
+ const QueryLoc& loc,
+ static_context* sctx,
+ const store::Item* item,
+ XQPCollator* collator,
+ int timezone);
+
+}
+}
+#endif
=== modified file 'src/runtime/sequences/sequences_impl.cpp'
--- src/runtime/sequences/sequences_impl.cpp 2013-10-10 03:54:10 +0000
+++ src/runtime/sequences/sequences_impl.cpp 2014-04-28 18:08:46 +0000
@@ -20,6 +20,7 @@
#include <vector>
#include <sstream>
+#include "deep_equality.h"
#include "diagnostics/xquery_diagnostics.h"
#include "diagnostics/util_macros.h"
@@ -157,7 +158,7 @@
if (!consumeNext(state->theSearchItem, theChildren[1].getp(), planState))
{
- RAISE_ERROR(err::FORG0006, loc, ERROR_PARAMS(ZED(EmptySeqNoSearchItem)));
+ RAISE_ERROR(err::FORG0006, loc, ERROR_PARAMS(ZED(EmptySeqNoSearchItem)));
}
if (theChildren.size() == 3)
@@ -191,7 +192,8 @@
searchItem,
tm,
timezone,
- state->theCollator);
+ state->theCollator,
+ true);
}
}
catch (ZorbaException const& e)
@@ -384,11 +386,11 @@
if (!consumeNext(lPositionItem, theChildren[1].getp(), planState))
{
- throw XQUERY_EXCEPTION(
- err::FORG0006,
- ERROR_PARAMS( ZED( EmptySeqNoFnRemoveArg ) ),
- ERROR_LOC( loc )
- );
+ throw XQUERY_EXCEPTION(
+ err::FORG0006,
+ ERROR_PARAMS( ZED( EmptySeqNoFnRemoveArg ) ),
+ ERROR_LOC( loc )
+ );
}
state->thePosition = lPositionItem->getIntegerValue();
@@ -729,12 +731,12 @@
{
if (!lNextItem->equals(result))
{
- throw XQUERY_EXCEPTION( err::FORG0003, ERROR_LOC( loc ) );
+ throw XQUERY_EXCEPTION( err::FORG0003, ERROR_LOC( loc ) );
}
}
else
{
- throw XQUERY_EXCEPTION( err::FORG0003, ERROR_LOC( loc ) );
+ throw XQUERY_EXCEPTION( err::FORG0003, ERROR_LOC( loc ) );
}
}
@@ -755,7 +757,7 @@
if (!consumeNext(result, theChildren[0].getp(), planState))
{
- throw XQUERY_EXCEPTION( err::FORG0004, ERROR_LOC( loc ) );
+ throw XQUERY_EXCEPTION( err::FORG0004, ERROR_LOC( loc ) );
}
do
{
@@ -801,7 +803,7 @@
else
{
if (theRaiseError)
- throw XQUERY_EXCEPTION( err::FORG0005, ERROR_LOC( loc ) );
+ throw XQUERY_EXCEPTION( err::FORG0005, ERROR_LOC( loc ) );
else
GENV_ITEMFACTORY->createBoolean(result, false);
}
@@ -813,433 +815,13 @@
/////////////////////////////////////////////////////////////////////////////////
// //
-// 15.3 Deepe Equal, Union, Intersection, and Except //
+// 15.3 Deep Equal, Union, Intersection, and Except //
// //
/////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************
15.3.1 fn:deep-equal
********************************************************************************/
-
-static bool DeepEqual(
- const QueryLoc& loc,
- static_context* sctx,
- store::Item_t& item1,
- store::Item_t& item2,
- XQPCollator* collator,
- int timezone);
-
-
-static bool DeepEqualChildren(
- const QueryLoc& loc,
- static_context* sctx,
- const store::Iterator_t& it1,
- const store::Iterator_t& it2,
- XQPCollator* collator,
- int timezone)
-{
- store::Item_t child1, child2;
- bool c1Valid, c2Valid;
-
- it1->open();
- it2->open();
-
- while (1)
- {
- while ((c1Valid = it1->next(child1)) &&
- (child1->getNodeKind() == store::StoreConsts::piNode ||
- child1->getNodeKind() == store::StoreConsts::commentNode))
- ;
-
- while ((c2Valid = it2->next(child2)) &&
- (child2->getNodeKind() == store::StoreConsts::piNode ||
- child2->getNodeKind() == store::StoreConsts::commentNode))
- ;
-
- if (!c1Valid && !c2Valid)
- return true;
- else if (!c1Valid || !c2Valid)
- return false;
- else if (!DeepEqual(loc, sctx, child1, child2, collator, timezone))
- return false;
- }
-
- return true;
-}
-
-
-static bool DeepEqualAttributes(
- const QueryLoc& loc,
- static_context* sctx,
- const store::Iterator_t& it1,
- const store::Iterator_t& it2,
- XQPCollator* collator,
- int timezone)
-{
- store::Item_t child1, child2;
- int c1count = 0, c2count = 0;
-
- it1->open();
- it2->open();
-
- while (it1->next(child1))
- {
- c1count++;
-
- it2->reset();
-
- bool found = false;
- while (it2->next(child2))
- {
- if (DeepEqual(loc, sctx, child1, child2, collator, timezone))
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- return false;
- }
-
- it2->reset();
- while (it2->next(child2))
- c2count++;
-
- if (c1count != c2count)
- return false;
-
- return true;
-}
-
-
-static bool DeepEqualNodes(
- const QueryLoc& loc,
- static_context* sctx,
- const store::Item_t& item1,
- const store::Item_t& item2,
- XQPCollator* collator,
- int timezone)
-{
- if (item1->getNodeKind() != item2->getNodeKind())
- return false;
-
- switch (item1->getNodeKind())
- {
- case store::StoreConsts::documentNode:
- {
- return DeepEqualChildren(loc,
- sctx,
- item1->getChildren(),
- item2->getChildren(),
- collator,
- timezone);
- break;
- }
- case store::StoreConsts::elementNode:
- {
- if (! item1->getNodeName()->equals(item2->getNodeName()))
- return false;
-
- if (!DeepEqualAttributes(loc,
- sctx,
- item1->getAttributes(),
- item2->getAttributes(),
- collator,
- timezone))
- return false;
-
- if (item1->haveSimpleContent())
- {
- if (!item2->haveSimpleContent())
- return false;
-
- store::Item_t value1, value2;
- store::Iterator_t ite1, ite2;
- item1->getTypedValue(value1, ite1);
- item2->getTypedValue(value2, ite2);
-
- if (ite1 == NULL && ite2 == NULL)
- {
- return DeepEqual(loc, sctx, value1, value2, collator, timezone);
- }
- else if (ite1 != NULL && ite2 != NULL)
- {
- ite1->open();
- ite2->open();
-
- while (1)
- {
- bool c1Valid = ite1->next(value1);
- bool c2Valid = ite2->next(value2);
-
- if (!c1Valid && !c2Valid)
- return true;
- else if (!c1Valid || !c2Valid)
- return false;
- else if (!DeepEqual(loc, sctx, value1, value2, collator, timezone))
- return false;
- }
- }
- else
- {
- return false;
- }
- }
- else if (item2->haveSimpleContent())
- {
- return false;
- }
- else
- {
- store::Item* typename1 = item1->getType();
- store::Item* typename2 = item2->getType();
-
- if (typename1->equals(typename2))
- {
- return DeepEqualChildren(loc,
- sctx,
- item1->getChildren(),
- item2->getChildren(),
- collator,
- timezone);
- }
- else
- {
- TypeManager* tm = sctx->get_typemanager();
-
- xqtref_t type1 =
- tm->create_named_type(typename1, SequenceType::QUANT_ONE, loc, true);
-
- xqtref_t type2 =
- tm->create_named_type(typename2, SequenceType::QUANT_ONE, loc, true);
-
- ZORBA_ASSERT(type1->isComplex() && type2->isComplex());
-
- if (type1->contentKind() != type2->contentKind())
- return false;
-
- return DeepEqualChildren(loc,
- sctx,
- item1->getChildren(),
- item2->getChildren(),
- collator,
- timezone);
- }
- }
- }
- case store::StoreConsts::attributeNode:
- {
- if (! item1->getNodeName()->equals(item2->getNodeName()))
- return false;
-
- store::Item_t value1, value2;
- store::Iterator_t ite1, ite2;
- item1->getTypedValue(value1, ite1);
- item2->getTypedValue(value2, ite2);
-
- if (ite1 == NULL && ite2 == NULL)
- {
- return DeepEqual(loc, sctx, value1, value2, collator, timezone);
- }
- else if (ite1 != NULL && ite2 != NULL)
- {
- ite1->open();
- ite2->open();
-
- while (1)
- {
- bool c1Valid = ite1->next(value1);
- bool c2Valid = ite2->next(value2);
-
- if (!c1Valid && !c2Valid)
- return true;
- else if (!c1Valid || !c2Valid)
- return false;
- else if (!DeepEqual(loc, sctx, value1, value2, collator, timezone))
- return false;
- }
- }
- else
- {
- return false;
- }
-
- break;
- }
- case store::StoreConsts::textNode:
- case store::StoreConsts::commentNode:
- {
- return (0 == utf8::compare(item1->getStringValue(),
- item2->getStringValue(),
- collator));
- }
-
- case store::StoreConsts::piNode:
- {
- if (utf8::compare(item1->getNodeName()->getStringValue(),
- item2->getNodeName()->getStringValue(),
- collator))
- return false;
-
- return (0 == utf8::compare(item1->getStringValue(),
- item2->getStringValue(),
- collator));
- }
-
- case store::StoreConsts::namespaceNode:
- {
- if (utf8::compare(item1->getNamespacePrefix(),
- item2->getNamespacePrefix(),
- collator))
- return false;
-
- return (0 == utf8::compare(item1->getStringValue(),
- item2->getStringValue(),
- collator));
- }
- default:
- ZORBA_ASSERT(false);
- }
-
- return true;
-}
-
-
-static bool DeepEqualObjects(
- const QueryLoc& loc,
- static_context* sctx,
- const store::Item_t& item1,
- const store::Item_t& item2,
- XQPCollator* collator,
- int timezone)
-{
- assert(item1->isObject());
- assert(item2->isObject());
-
- if (item1->getNumObjectPairs() != item2->getNumObjectPairs())
- return false;
-
- store::Iterator_t lKeys = item1->getObjectKeys();
- lKeys->open();
-
- store::Item_t lKey, lValue1, lValue2;
-
- while (lKeys->next(lKey))
- {
- lValue2 = item2->getObjectValue(lKey);
-
- if (lValue2 == NULL)
- return false;
-
- lValue1 = item1->getObjectValue(lKey);
-
- if (!DeepEqual(loc, sctx, lValue1, lValue2, collator, timezone))
- return false;
- }
-
- return true;
-}
-
-
-static bool DeepEqualArrays(
- const QueryLoc& loc,
- static_context* sctx,
- const store::Item_t& item1,
- const store::Item_t& item2,
- XQPCollator* collator,
- int timezone)
-{
- assert(item1->isArray());
- assert(item2->isArray());
-
- if (item1->getArraySize() != item2->getArraySize())
- return false;
-
- store::Iterator_t lValues1 = item1->getArrayValues();
- store::Iterator_t lValues2 = item2->getArrayValues();
- lValues1->open();
- lValues2->open();
-
- store::Item_t lValue1, lValue2;
-
- while (lValues1->next(lValue1) && lValues2->next(lValue2))
- {
- if (!DeepEqual(loc, sctx, lValue1, lValue2, collator, timezone))
- return false;
- }
-
- return true;
-}
-
-
-static bool DeepEqual(
- const QueryLoc& loc,
- static_context* sctx,
- store::Item_t& item1,
- store::Item_t& item2,
- XQPCollator* collator,
- int timezone)
-{
- if (item1->getKind() != item2->getKind())
- return false;
-
- switch (item1->getKind())
- {
- case store::Item::ATOMIC:
- {
- assert(item2->isAtomic());
-
- store::SchemaTypeCode type1 = item1->getTypeCode();
- store::SchemaTypeCode type2 = item2->getTypeCode();
-
- // check if bot items are NaN
- if (((type1 == store::XS_FLOAT && item1->getFloatValue().isNaN()) ||
- (type1 == store::XS_DOUBLE && item1->getDoubleValue().isNaN()))
- &&
- ((type2 == store::XS_FLOAT && item2->getFloatValue().isNaN()) ||
- (type2 == store::XS_DOUBLE && item2->getDoubleValue().isNaN())))
- {
- return true;
- }
-
- try
- {
- TypeManager* tm = sctx->get_typemanager();
-
- return CompareIterator::valueEqual(loc, item1, item2, tm, timezone, collator);
- }
- catch (ZorbaException const& e)
- {
- if (e.diagnostic() == err::XPTY0004)
- return false;
- throw;
- }
-
- break;
- }
- case store::Item::NODE:
- {
- return DeepEqualNodes(loc, sctx, item1, item2, collator, timezone);
- }
- case store::Item::OBJECT:
- {
- return DeepEqualObjects(loc, sctx, item1, item2, collator, timezone);
- }
- case store::Item::ARRAY:
- {
- return DeepEqualArrays(loc, sctx, item1, item2, collator, timezone);
- }
- default:
- {
- ZORBA_ASSERT(false); // should never reach here
- }
- }
-
- return false;
-}
-
-
bool FnDeepEqualIterator::nextImpl(
store::Item_t& result,
PlanState& planState) const
@@ -1279,11 +861,11 @@
if (arg1->isFunction() || arg2->isFunction())
{
- RAISE_ERROR(err::FOTY0015, loc,
+ RAISE_ERROR(err::FOTY0015, loc,
ERROR_PARAMS((arg1->isFunction() ? arg1 : arg2)->getFunctionName()->getStringValue()));
}
- equal = equal && DeepEqual(loc, theSctx, arg1, arg2, collator, timezone);
+ equal = equal && equality::deepEqual(loc, theSctx, arg1, arg2, collator, timezone, true);
}
STACK_PUSH(GENV_ITEMFACTORY->createBoolean(result, equal), state);
@@ -1453,7 +1035,7 @@
{
xqtref_t type = tm->create_value_type(lRunningItem);
RAISE_ERROR(err::FORG0006, loc,
- ERROR_PARAMS(ZED(BadArgTypeForFn_2o34o),
+ ERROR_PARAMS(ZED(BadArgTypeForFn_2o34o),
*type,
"fn:avg",
ZED(ExpectedType_5),
@@ -1524,8 +1106,8 @@
else
{
xqtref_t type = tm->create_value_type(lRunningItem);
- RAISE_ERROR(err::FORG0006, loc,
- ERROR_PARAMS(ZED(BadArgTypeForFn_2o34o),
+ RAISE_ERROR(err::FORG0006, loc,
+ ERROR_PARAMS(ZED(BadArgTypeForFn_2o34o),
*type,
"fn:avg",
ZED(ExpectedNumericOrDurationType)));
@@ -1597,7 +1179,7 @@
{
xqtref_t type = tm->create_value_type(result);
RAISE_ERROR(err::FORG0006, loc,
- ERROR_PARAMS(ZED(BadArgTypeForFn_2o34o), *type, "fn:sum"));
+ ERROR_PARAMS(ZED(BadArgTypeForFn_2o34o), *type, "fn:sum"));
}
while (consumeNext(lRunningItem, theChildren[0].getp(), planState))
@@ -1641,8 +1223,8 @@
{
xqtref_t type1 = tm->create_value_type(result);
xqtref_t type2 = tm->create_value_type(lRunningItem);
- RAISE_ERROR(err::FORG0006, loc,
- ERROR_PARAMS(ZED( SumImpossibleWithTypes_23 ), *type1, *type2));
+ RAISE_ERROR(err::FORG0006, loc,
+ ERROR_PARAMS(ZED( SumImpossibleWithTypes_23 ), *type1, *type2));
}
}
=== 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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 2014-04-23 00:40:33 +0000
+++ src/store/naive/atomic_items.h 2014-04-28 18:08:46 +0000
@@ -571,6 +571,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,
@@ -944,7 +946,7 @@
friend class BasicItemFactory;
protected:
- std::istream & theIstream;
+ std::istream * theIstream;
bool theIsMaterialized;
bool theIsConsumed;
@@ -983,6 +985,8 @@
bool isSeekable() const;
+ void ensureSeekable();
+
std::istream& getStream();
StreamReleaser getStreamReleaser();
@@ -993,7 +997,7 @@
{
if (theStreamReleaser)
{
- theStreamReleaser(&theIstream);
+ theStreamReleaser(theIstream);
}
}
@@ -1012,6 +1016,10 @@
store::Item_t& streamableDependent);
void materialize() const;
+
+private:
+ static void streamReleaser(std::istream* aStream) { delete aStream;}
+
};
@@ -2371,7 +2379,7 @@
friend class BasicItemFactory;
protected:
- std::istream & theIstream;
+ std::istream * theIstream;
bool theIsMaterialized;
bool theIsConsumed;
@@ -2388,7 +2396,7 @@
bool is_encoded = false)
:
Base64BinaryItem(t, is_encoded),
- theIstream(aStream),
+ theIstream(&aStream),
theIsMaterialized(false),
theIsConsumed(false),
theIsSeekable(seekable),
@@ -2403,7 +2411,7 @@
{
if (theStreamReleaser)
{
- theStreamReleaser(&theIstream);
+ theStreamReleaser(theIstream);
}
}
@@ -2411,6 +2419,8 @@
bool isSeekable() const;
+ void ensureSeekable();
+
std::istream& getStream();
StreamReleaser getStreamReleaser();
@@ -2421,6 +2431,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;
@@ -2428,6 +2441,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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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_cache.h'
--- src/zorbautils/hashmap_itemh_cache.h 1970-01-01 00:00:00 +0000
+++ src/zorbautils/hashmap_itemh_cache.h 2014-04-28 18:08:46 +0000
@@ -0,0 +1,474 @@
+/*
+ * 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_CACHE_H
+#define HASHMAP_ITEMH_CACHE_H
+
+#include "context/static_context.h"
+#include "runtime/sequences/deep_equality.h"
+#include "zorbautils/hashfun.h"
+#include "zorbautils/hashmap.h"
+
+#include "store/api/item.h"
+#include "store/naive/item_vector.h"
+
+#include "system/globalenv.h"
+
+#include <boost/dynamic_bitset.hpp>
+
+namespace zorba
+{
+
+class ItemHandleCacheHashMapCmp
+{
+protected:
+ zorba::QueryLoc theEmptyLoc;
+ long theTimeZone;
+ XQPCollator* theCollator;
+ static_context* theSctx;
+ boost::dynamic_bitset<> theExcludeFromCacheKey;
+ boost::dynamic_bitset<> theCompareWithDeepEqual;
+
+public:
+ ItemHandleCacheHashMapCmp(
+ static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual)
+ :
+ theTimeZone(0),
+ theCollator(NULL),
+ theSctx(aSctx),
+ theExcludeFromCacheKey(aExcludeFromCacheKey),
+ theCompareWithDeepEqual(aCompareWithDeepEqual)
+ {
+ /*if (theSctx->get_local_typemanager() == NULL)
+ theSctx->set_typemanager(new TypeManagerImpl(&GENV_TYPESYSTEM));*/
+ }
+
+ ItemHandleCacheHashMapCmp(
+ static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual,
+ long aTimezone,
+ XQPCollator* aCollator)
+ :
+ theTimeZone(aTimezone),
+ theCollator(aCollator),
+ theSctx(aSctx),
+ theExcludeFromCacheKey(aExcludeFromCacheKey),
+ theCompareWithDeepEqual(aCompareWithDeepEqual)
+ {
+ /*if (theSctx->get_local_typemanager() == NULL)
+ theSctx->set_typemanager(new TypeManagerImpl(&GENV_TYPESYSTEM));*/
+ }
+
+ bool id_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 (!id_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;
+ }
+ }
+ }
+
+ bool deep_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:
+ {
+ return equality::deepEqualNodes(theEmptyLoc, theSctx, t1, t2, theCollator, theTimeZone, false);
+ }
+ case store::Item::OBJECT:
+ {
+ return equality::deepEqualObjects(theEmptyLoc, theSctx, t1, t2, theCollator, theTimeZone, false);
+ }
+ case store::Item::ARRAY:
+ {
+ return equality::deepEqualArrays(theEmptyLoc, theSctx, t1, t2, theCollator, theTimeZone, false);
+ }
+ 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 (!deep_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;
+ }
+ }
+ }
+
+ bool equal(const store::Item* t1, const store::Item* t2) const
+ {
+ const simplestore::ItemVector* lVector1 =
+ static_cast<const simplestore::ItemVector*>(t1);
+ const simplestore::ItemVector* lVector2 =
+ static_cast<const simplestore::ItemVector*>(t2);
+
+ for (unsigned int i=0; i<lVector1->size(); ++i)
+ {
+ if (!theExcludeFromCacheKey[i])
+ {
+ if (theCompareWithDeepEqual[i])
+ {
+ if (!deep_equal(lVector1->getItem(i), lVector2->getItem(i)))
+ return false;
+ }
+ else
+ {
+ if (!id_equal(lVector1->getItem(i), lVector2->getItem(i)))
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ uint32_t id_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 = id_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;
+ }
+ }
+ }
+
+ uint32_t deep_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:
+ {
+ lInnerHash = equality::deHashNode(theEmptyLoc, theSctx, t, theCollator, theTimeZone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::Item::OBJECT:
+ {
+ lInnerHash = equality::deHashObject(theEmptyLoc, theSctx, t, theCollator, theTimeZone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ case store::Item::ARRAY:
+ {
+ lInnerHash = equality::deHashArray(theEmptyLoc, theSctx, t, theCollator, theTimeZone);
+ return hashfun::h32(&lInnerHash, sizeof(lInnerHash), 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 = equality::deHash(theEmptyLoc, theSctx, lVector->getItem(i), theCollator, theTimeZone);
+ 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;
+ }
+ }
+ }
+
+ uint32_t hash(const store::Item* t) const
+ {
+ const simplestore::ItemVector* lVector =
+ static_cast<const simplestore::ItemVector*>(t);
+ uint32_t lHash = FNV_32_INIT;
+ uint32_t lInnerHash;
+
+ for (unsigned int i=0; i<lVector->size(); ++i)
+ {
+ if (!theExcludeFromCacheKey[i])
+ {
+ if (theCompareWithDeepEqual[i])
+ lInnerHash = deep_hash(lVector->getItem(i));
+ else
+ lInnerHash = id_hash(lVector->getItem(i));
+ }
+ lHash = hashfun::h32(&lInnerHash, sizeof(lInnerHash), lHash);
+ }
+ return lHash;
+ }
+
+
+ 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 ItemHandleCacheHashMap
+{
+public:
+ typedef typename HashMap<store::Item*, V, ItemHandleCacheHashMapCmp>::iterator iterator;
+
+private:
+ HashMap<store::Item*, V, ItemHandleCacheHashMapCmp> theMap;
+
+public:
+ ItemHandleCacheHashMap(
+ static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual)
+:
+ theMap(
+ ItemHandleCacheHashMapCmp(aSctx, aExcludeFromCacheKey, aCompareWithDeepEqual),
+ 8,
+ false)
+{
+}
+
+ ItemHandleCacheHashMap(
+ static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual,
+ ulong aSize,
+ bool aSync)
+ :
+ theMap(
+ ItemHandleCacheHashMapCmp(aSctx, aExcludeFromCacheKey, aCompareWithDeepEqual),
+ aSize,
+ aSync)
+ {
+ }
+
+ ItemHandleCacheHashMap(
+ static_context* aSctx,
+ boost::dynamic_bitset<>& aExcludeFromCacheKey,
+ boost::dynamic_bitset<>& aCompareWithDeepEqual,
+ long aTimezone,
+ XQPCollator* aCollation,
+ ulong aSize,
+ bool aSync)
+ :
+ theMap(
+ ItemHandleCacheHashMapCmp(aSctx, aExcludeFromCacheKey, aCompareWithDeepEqual, aTimezone, aCollation),
+ aSize,
+ aSync)
+ {
+ }
+
+ ~ItemHandleCacheHashMap()
+ {
+ 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 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-28 18:08:46 +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
=== modified file 'src/zorbautils/hashset_atomic_itemh.h'
--- src/zorbautils/hashset_atomic_itemh.h 2014-04-23 00:40:33 +0000
+++ src/zorbautils/hashset_atomic_itemh.h 2014-04-28 18:08:46 +0000
@@ -83,7 +83,8 @@
t2,
theCompareParam->theTypeManager,
theCompareParam->theTimezone,
- theCompareParam->theCollator);
+ theCompareParam->theCollator,
+ true);
}
catch(ZorbaException const& e)
{
=== 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+1
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/deep-equal-ext-cache-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/deep-equal-ext-cache-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/deep-equal-ext-cache-01.xml.res 2014-04-28 18:08:46 +0000
@@ -0,0 +1,11 @@
+Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
+ Called with { "x" : 1, "y" : 2 }: NOT CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: CACHED
+ Called with { "x" : 1, "y" : 2 }: CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/deep-equal-ext-sd-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/deep-equal-ext-sd-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/deep-equal-ext-sd-01.xml.res 2014-04-28 18:08:46 +0000
@@ -0,0 +1,11 @@
+Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
+ Called with { "x" : 1, "y" : 2 }: NOT CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: CACHED
+ Called with { "x" : 1, "y" : 2 }: CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/deep-equal-udf-cache-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/deep-equal-udf-cache-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/deep-equal-udf-cache-01.xml.res 2014-04-28 18:08:46 +0000
@@ -0,0 +1,11 @@
+Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
+ Called with { "x" : 1, "y" : 2 }: NOT CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: CACHED
+ Called with { "x" : 1, "y" : 2 }: CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/deep-equal-udf-sd-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/deep-equal-udf-sd-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/deep-equal-udf-sd-01.xml.res 2014-04-28 18:08:46 +0000
@@ -0,0 +1,11 @@
+Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
+ Called with { "x" : 1, "y" : 2 }: NOT CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: CACHED
+ Called with { "x" : 1, "y" : 2 }: CACHED
+ Called with { "x" : "<a/>", "y" : "<b/>" }: NOT CACHED
+ Called with { "x" : { "a" : 1 }, "y" : { "b" : 2 } }: NOT CACHED
+ Called with { "x" : [ 1 ], "y" : [ 2 ] }: NOT CACHED
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/ignore-argument-ext-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/ignore-argument-ext-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/ignore-argument-ext-01.xml.res 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+{ "cache" : [ 2, 2, 2, 3, 3, 3 ], "sd" : [ 2, 2, 2, 3, 3, 3 ] }
\ No newline at end of file
=== added file 'test/rbkt/ExpQueryResults/zorba/caching/ignore-argument-udf-01.xml.res'
--- test/rbkt/ExpQueryResults/zorba/caching/ignore-argument-udf-01.xml.res 1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/caching/ignore-argument-udf-01.xml.res 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+{ "cache" : [ 2, 2, 2, 3, 3, 3 ], "sd" : [ 2, 2, 2, 3, 3, 3 ] }
\ 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +0000
@@ -0,0 +1,30 @@
+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)
+{
+};
+
+declare %an:strictlydeterministic %an:exclude-from-cache-key(1) function local:foo-arg($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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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/annotations-literals-01.spec'
--- test/rbkt/Queries/zorba/caching/annotations-literals-01.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-01.spec 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+Error: http://zorba.io/errors:ZXQP0062
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-01.xq'
--- test/rbkt/Queries/zorba/caching/annotations-literals-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,8 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic %an:exclude-from-cache-key function local:foo($x as xs:integer)
+{
+ 1
+};
+
+local:foo(1)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-02.spec'
--- test/rbkt/Queries/zorba/caching/annotations-literals-02.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-02.spec 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+Error: http://zorba.io/errors:ZXQP0063
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-02.xq'
--- test/rbkt/Queries/zorba/caching/annotations-literals-02.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-02.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,8 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic %an:exclude-from-cache-key(1,"a") function local:foo($x as xs:integer)
+{
+ 1
+};
+
+local:foo(1)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-03.spec'
--- test/rbkt/Queries/zorba/caching/annotations-literals-03.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-03.spec 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+Error: http://zorba.io/errors:ZXQP0064
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-03.xq'
--- test/rbkt/Queries/zorba/caching/annotations-literals-03.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-03.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,8 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic %an:exclude-from-cache-key(1, 2) function local:foo($x as xs:integer)
+{
+ 1
+};
+
+local:foo(1)
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-04.spec'
--- test/rbkt/Queries/zorba/caching/annotations-literals-04.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-04.spec 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+Error: http://zorba.io/errors:ZXQP0065
=== added file 'test/rbkt/Queries/zorba/caching/annotations-literals-04.xq'
--- test/rbkt/Queries/zorba/caching/annotations-literals-04.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-literals-04.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,8 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic %an:exclude-from-cache-key(1) function local:foo()
+{
+ 1
+};
+
+local:foo()
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/annotations-requirements-01.spec'
--- test/rbkt/Queries/zorba/caching/annotations-requirements-01.spec 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-requirements-01.spec 2014-04-28 18:08:46 +0000
@@ -0,0 +1,1 @@
+Error: http://www.w3.org/2005/xqt-errors:XQST0106
=== added file 'test/rbkt/Queries/zorba/caching/annotations-requirements-01.xq'
--- test/rbkt/Queries/zorba/caching/annotations-requirements-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/annotations-requirements-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,7 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:exclude-from-cache-key(1) function local:foo($x as xs:integer)
+{
+};
+
+1
\ No newline at end of file
=== 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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/deep-equal-ext-cache-01.xq'
--- test/rbkt/Queries/zorba/caching/deep-equal-ext-cache-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/deep-equal-ext-cache-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,53 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+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];
+
+let $old :=
+(
+ debug:test-07-cache($node, <b/>),
+ debug:test-07-cache($object, {"b": 2}),
+ debug:test-07-cache($array, [2]),
+ debug:test-07-cache(1, 2)
+)
+
+let $old-values := (for $i in (1 to 4) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 4) return $old[$i * 2])
+
+let $equal :=
+(
+ debug:test-07-cache($node, <b/>),
+ debug:test-07-cache($object, {"b": 2}),
+ debug:test-07-cache($array, [2]),
+ debug:test-07-cache(1, 2)
+)
+
+let $expected-old-values := (for $i in (1 to 4) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 4) return $equal[$i * 2])
+
+let $re-evaluated :=
+(
+ debug:test-07-cache(<a/>, <b/>),
+ debug:test-07-cache({"a":1}, {"b": 2}),
+ debug:test-07-cache([1], [2])
+)
+let $expected-new-values := (for $i in (1 to 3) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 3) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 4)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 4)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 3)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
=== added file 'test/rbkt/Queries/zorba/caching/deep-equal-ext-sd-01.xq'
--- test/rbkt/Queries/zorba/caching/deep-equal-ext-sd-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/deep-equal-ext-sd-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,53 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+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];
+
+let $old :=
+(
+ debug:test-07-cache($node, <b/>),
+ debug:test-07-cache($object, {"b": 2}),
+ debug:test-07-cache($array, [2]),
+ debug:test-07-cache(1, 2)
+)
+
+let $old-values := (for $i in (1 to 4) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 4) return $old[$i * 2])
+
+let $equal :=
+(
+ debug:test-07-cache($node, <b/>),
+ debug:test-07-cache($object, {"b": 2}),
+ debug:test-07-cache($array, [2]),
+ debug:test-07-cache(1, 2)
+)
+
+let $expected-old-values := (for $i in (1 to 4) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 4) return $equal[$i * 2])
+
+let $re-evaluated :=
+(
+ debug:test-07-cache(<a/>, <b/>),
+ debug:test-07-cache({"a":1}, {"b": 2}),
+ debug:test-07-cache([1], [2])
+)
+let $expected-new-values := (for $i in (1 to 3) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 3) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 4)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 4)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 3)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
=== added file 'test/rbkt/Queries/zorba/caching/deep-equal-udf-cache-01.xq'
--- test/rbkt/Queries/zorba/caching/deep-equal-udf-cache-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/deep-equal-udf-cache-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,59 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:cache %an:compare-with-deep-equal(2) function local:test-07-cache($x as item(), $y as item())
+{
+ serialize({"x" : $x, "y" : $y}),
+ 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];
+
+let $old :=
+(
+ local:test-07-cache($node, <b/>),
+ local:test-07-cache($object, {"b": 2}),
+ local:test-07-cache($array, [2]),
+ local:test-07-cache(1, 2)
+)
+
+let $old-values := (for $i in (1 to 4) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 4) return $old[$i * 2])
+
+let $equal :=
+(
+ local:test-07-cache($node, <b/>),
+ local:test-07-cache($object, {"b": 2}),
+ local:test-07-cache($array, [2]),
+ local:test-07-cache(1, 2)
+)
+
+let $expected-old-values := (for $i in (1 to 4) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 4) return $equal[$i * 2])
+
+let $re-evaluated :=
+(
+ local:test-07-cache(<a/>, <b/>),
+ local:test-07-cache({"a":1}, {"b": 2}),
+ local:test-07-cache([1], [2])
+)
+let $expected-new-values := (for $i in (1 to 3) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 3) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 4)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 4)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 3)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
=== added file 'test/rbkt/Queries/zorba/caching/deep-equal-udf-sd-01.xq'
--- test/rbkt/Queries/zorba/caching/deep-equal-udf-sd-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/deep-equal-udf-sd-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,59 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:strictlydeterministic %an:compare-with-deep-equal(2) function local:test-07-cache($x as item(), $y as item())
+{
+ serialize({"x" : $x, "y" : $y}),
+ 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];
+
+let $old :=
+(
+ local:test-07-cache($node, <b/>),
+ local:test-07-cache($object, {"b": 2}),
+ local:test-07-cache($array, [2]),
+ local:test-07-cache(1, 2)
+)
+
+let $old-values := (for $i in (1 to 4) return $old[$i * 2 - 1])
+let $old-uuids := (for $i in (1 to 4) return $old[$i * 2])
+
+let $equal :=
+(
+ local:test-07-cache($node, <b/>),
+ local:test-07-cache($object, {"b": 2}),
+ local:test-07-cache($array, [2]),
+ local:test-07-cache(1, 2)
+)
+
+let $expected-old-values := (for $i in (1 to 4) return $equal[$i * 2 -1])
+let $expected-old-uuids := (for $i in (1 to 4) return $equal[$i * 2])
+
+let $re-evaluated :=
+(
+ local:test-07-cache(<a/>, <b/>),
+ local:test-07-cache({"a":1}, {"b": 2}),
+ local:test-07-cache([1], [2])
+)
+let $expected-new-values := (for $i in (1 to 3) return $re-evaluated[$i * 2 - 1])
+let $expected-new-uuids := (for $i in (1 to 3) return $re-evaluated[$i * 2])
+return
+(
+ for $i in (1 to 4)
+ return "Called with " || $old-values[$i] || ": NOT CACHED" || " ",
+ for $j in (1 to 4)
+ return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || " ",
+ for $k in (1 to 3)
+ return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || " "
+)
=== added file 'test/rbkt/Queries/zorba/caching/ignore-argument-ext-01.xq'
--- test/rbkt/Queries/zorba/caching/ignore-argument-ext-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/ignore-argument-ext-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,22 @@
+import module namespace debug = "http://zorba.io/modules/util-tests";
+
+{
+ "cache":
+ [
+ debug:test-06-cache(1,1),
+ debug:test-06-cache(1,2),
+ debug:test-06-cache(1,3),
+ debug:test-06-cache(2,1),
+ debug:test-06-cache(2,2),
+ debug:test-06-cache(2,3)
+ ],
+ "sd":
+ [
+ debug:test-06-cache(1,1),
+ debug:test-06-cache(1,2),
+ debug:test-06-cache(1,3),
+ debug:test-06-cache(2,1),
+ debug:test-06-cache(2,2),
+ debug:test-06-cache(2,3)
+ ]
+}
\ No newline at end of file
=== added file 'test/rbkt/Queries/zorba/caching/ignore-argument-udf-01.xq'
--- test/rbkt/Queries/zorba/caching/ignore-argument-udf-01.xq 1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/caching/ignore-argument-udf-01.xq 2014-04-28 18:08:46 +0000
@@ -0,0 +1,32 @@
+declare namespace an = "http://zorba.io/annotations";
+
+declare %an:cache %an:exclude-from-cache-key(2) function local:test-06-cache($x as xs:integer, $y as xs:integer) as xs:integer
+{
+ $x + $y
+};
+
+declare %an:strictlydeterministic %an:exclude-from-cache-key(2) function local:test-06-sd($x as xs:integer, $y as xs:integer) as xs:integer
+{
+ $x + $y
+};
+
+{
+ "cache":
+ [
+ local:test-06-cache(1,1),
+ local:test-06-cache(1,2),
+ local:test-06-cache(1,3),
+ local:test-06-cache(2,1),
+ local:test-06-cache(2,2),
+ local:test-06-cache(2,3)
+ ],
+ "sd":
+ [
+ local:test-06-cache(1,1),
+ local:test-06-cache(1,2),
+ local:test-06-cache(1,3),
+ local:test-06-cache(2,1),
+ local:test-06-cache(2,2),
+ local:test-06-cache(2,3)
+ ]
+}
\ 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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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-28 18:08:46 +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>