← Back to team overview

zorba-coders team mailing list archive

[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 &lt; 10)
+ :  then $x * $x
+ :  else if ($x &lt; 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 &lt; 10)
+ :  then $x * $x
+ :  else if ($x &lt; 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],
+ :   &lt;a/&gt;,
+ :   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],
+ :   &lt;a/&gt;,
+ :   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()],
+ :   &lt;a&gt;{tests:non-seeakable-streamable-string()}&lt;/a&gt;
+ :   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()],
+ :   &lt;a&gt;{tests:non-seeakable-streamable-string()}&lt;/a&gt;
+ :   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&lt;a/&gt;{ "a" : 1 }[ 1 ] 1&lt;a/&gt;{ "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&lt;a/&gt;{ "a" : 1 }[ 1 ] 1&lt;a/&gt;{ "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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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" : "&lt;a/&gt;", "y" : "&lt;b/&gt;" }: 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 &lt;a/&gt;: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: 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 &lt;a/&gt;: 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 &lt;a/&gt;: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: CACHED
+ Called with { "a" : 1 }: CACHED
+ Called with [ 1 ]: CACHED
+ Called with [ 2 ]: CACHED
+ Called with 1: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: NOT CACHED
+ Called with { "a" : 1 }: NOT CACHED
+ Called with [ 1 ]: NOT CACHED
+ Called with &lt;a/&gt;: 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 &lt;a/&gt;: 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 &lt;a/&gt;: 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" || "&#10;",
+  for $j in (1 to 4)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 3)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"
+)

=== 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" || "&#10;",
+  for $j in (1 to 4)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 3)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"
+)

=== 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" || "&#10;",
+  for $j in (1 to 4)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 3)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"
+)

=== 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" || "&#10;",
+  for $j in (1 to 4)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 3)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"
+)

=== 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" || "&#10;",
+  for $j in (1 to 6)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 5)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;" 
+)
\ 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" || "&#10;",
+  for $j in (1 to 6)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 5)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;" 
+)
\ 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" || "&#10;",
+  for $j in (1 to 11)
+  return "Called with " || $expected-new-values[$j] || ": " || local:is-cached($expected-new-uuids[$j], $old-uuids) || "&#10;" 
+)
\ 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" || "&#10;",
+  for $j in (1 to 6)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 5)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"  
+)
\ 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" || "&#10;",
+  for $j in (1 to 6)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 5)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"
+)
\ 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" || "&#10;",
+  for $j in (1 to 6)
+  return "Called with " || $expected-old-values[$j] || ": " || local:is-cached($expected-old-uuids[$j], $old-uuids) || "&#10;",
+  for $k in (1 to 5)
+  return "Called with " || $expected-new-values[$k] || ": " || local:is-cached($expected-new-uuids[$k], $old-uuids) || "&#10;"  
+)
\ 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>