← Back to team overview

zorba-coders team mailing list archive

[Merge] lp:~markos-za/zorba/indexes into lp:zorba

 

Markos Zaharioudakis has proposed merging lp:~markos-za/zorba/indexes into lp:zorba.

Requested reviews:
  Matthias Brantner (matthias-brantner)
  Markos Zaharioudakis (markos-za)

For more details, see:
https://code.launchpad.net/~markos-za/zorba/indexes/+merge/79334
-- 
https://code.launchpad.net/~markos-za/zorba/indexes/+merge/79334
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'ChangeLog'
--- ChangeLog	2011-10-12 21:30:46 +0000
+++ ChangeLog	2011-10-13 19:58:25 +0000
@@ -40,6 +40,7 @@
   * Fixed bug #863320 (Sentence is incorrectly incremented when token characters end without sentence terminator)
   * Fixed bug #863730 (static delete-node* functions don't raise ZDDY0012)
   * Implemented the probe-index-range-value for general indexes
+  * Removed ZSTR0005 and ZSTR0006 error codes
   * Fixed bug #867662 ("nullptr" warning)
   * Fixed bug #868258 (Assertion failure with two delete collection)
   * Fixed bug #871623 and #871629 (assertion failures with insertions in dynamic collections)
@@ -49,9 +50,14 @@
   * New node-reference module. References can be obtained for any node, and
 	different nodes cannot have the same identifier.
   * Fixed bug #872697  (segmentation fault with validation of NMTOKENS)
+<<<<<<< TREE
   * Added undo for node revalidation
   * Fixed bug #872796  (validate-in-place can interfere with other update primitives)
   * Fixed bug #872799 (validate-in-place can set incorrect types)
+=======
+  * General index cannot be declared as unique if the type of its key is
+    xs:anyAtomicType or xs:untypedAtomic.
+>>>>>>> MERGE-SOURCE
 
 version 2.0.1
 

=== modified file 'doc/zorba/xqddf.dox'
--- doc/zorba/xqddf.dox	2011-10-05 17:49:48 +0000
+++ doc/zorba/xqddf.dox	2011-10-13 19:58:25 +0000
@@ -1375,6 +1375,14 @@
   AtomicType ::= QName
 
   IndexKeyCollation ::= 'collation' UriLiteral
+
+  Note: the following annotations are accepted within the context of an index declaration:
+
+     %ann:unique, %ann:nonunique,
+     %ann:value-range, %ann:value-equality, 
+     %ann:general-range, %ann:general-equality,
+     %ann:manual or %ann:automatic
+
 \endcode
 
 Syntactically, each index is defined by an <a href="#index_declaration">
@@ -1385,8 +1393,8 @@
 value indexes and general indexes. Whether an index is a value or a general 
 index is determined by the value of the usage property, which is explained below.
 
-Index declarations (for both value and general indexes) must be placed inside module prologs.
-The Prolog syntax is extended accordingly, as shown above. 
+Index declarations (for both value and general indexes) must be placed inside 
+module prologs. The Prolog syntax is extended accordingly, as shown above. 
 An additional constraint (not expressible syntactically) is that only library 
 modules may contain index declarations  [<a href="#ERRZDST0023">zerr:ZDST0023</a>]. 
 The reasons for this rule are the same as those for collections (see \ref 
@@ -1424,7 +1432,10 @@
 (or key tuple in the case of value indexs) with exactly one domain node. 
 Otherwise, if the index is '%ann:nonunique', multiple domain nodes may have the 
 same key value, and as a result, each index entry associates a key with a 
-set of domain nodes.
+set of domain nodes. In the current implementation, it is not allowed to declare
+an index as unique if it is a general index whose IndexKeyTypeDecl is either absent
+or specifies xs:anyAtomicType or xs:untypedAtomic as its atomic type 
+[<a href="#ERRZDST0025">zerr:ZDST0025</a>].
 
 The usage property specifies the kind of the index based on the query expressions 
 that may be optimized by using the index. A <strong>value equality index</strong> 
@@ -1529,16 +1540,17 @@
 \subsection index_creation Index Creation
 
 
-As explained already, indexes are just sets of index entries, mapping key items
-or key tuples to domain nodes. In terms of the XQuery language, these sets 
-"live" in the dynamic context. In particular, XQDDF extends the dynamic context 
-with a component called the <strong>available indexes</strong>. This is a map 
-whose entries associate the expanded QName of an index with the entry set of the
-index. If an entry for an index appears in the available indexes of a module,
-the index is said to be available to that module.
+As explained already, indexes are just sets of index entries, where an index 
+entry maps a key item or a key tuple to a set of domain nodes (to be more
+precise, an index entry contains some kind of "pointers" to nodes, not the 
+nodes themselves). In terms of the XQuery language, indexes "live" in the 
+dynamic context. In particular, XQDDF extends the dynamic context with a 
+component called the <strong>available indexes</strong>. This is a map whose 
+entries associate the expanded QName of an index with the entry set for that 
+index. 
 
 In practice, the available indexes component is implemented by Zorba's storage
-system. To begin with, each index entry set is implemented by some appropriate
+system. To begin with, each index is implemented by some appropriate
 data structure that acts as an index entry container. The description of
 potential data structures is beyond the scope of this document, but the typical
 choices are either some sort of hash table(s) (for equality indexes) or some kind
@@ -1595,9 +1607,7 @@
 indexes, an error is raised [<a href="#ERRZDDY0028">zerr:ZDDY0028</a>]. The result
 of the domain expression after duplicate elimination is called the <strong>domain
 sequence</strong>. If the domain sequence contains a node that does not belong to 
-a collection, an error is raised [<a href="#ERRZDDY0020">zerr:ZDDY0020</a>] (the 
-purpose of this rule is to prevent nodes constructed by node construction 
-expression to appear as domain nodes).</li>
+a collection, an error is raised [<a href="#ERRZDDY0020">zerr:ZDDY0020</a>].</li>
 
 <li>
 For each node D in the domain sequence, the IndexKeySpecs are evaluated in some 
@@ -1619,8 +1629,8 @@
   </li>
 
   <li>
-  Duplicate values, which may arise in the case of general indexes only, are 
-  eliminated from the key sequence.
+  Duplicate values (which may arise in the case of general indexes only) are 
+  eliminated from the atomized sequence.
   </li>
   </ul>
 
@@ -1630,12 +1640,12 @@
 
   <ul>
   <li>
-  The result of each IndexKeySpec is a single atomic item. We call this 
-  item a <strong>key item</strong>.
+  The result of each IndexKeySpec is a single atomic item or the empty sequence.
+  We call this result a <strong>key value</strong>.
   </li>
 
   <li>
-  Let D<sub>i</sub> be the i-th domain node, and K<sub>ij</sub> be the key item
+  Let D<sub>i</sub> be the i-th domain node, and K<sub>ij</sub> be the key value
   computed for D<sub>i</sub> by the j-th IndexKeySpec (where the numbering of
   the IndexKeySpecs is done using their order of appearance in the index
   declaration). Let K<sub>i</sub> be the tuple [K<sub>i1</sub>, ...,
@@ -1650,16 +1660,14 @@
   tuples and domain nodes is one-to-one. In this case, if the index already
   contains an entry whose key tuple is equal to K<sub>i</sub>, an error is 
   raised [<a href="#ERRZDDY0024">zerr:ZDDY0024</a>]. Otherwise, the entry 
-  [K<sub>i</sub>, D<sub>i</sub>] is inserted in the index container (to be very
-  precise, the entry contains a "pointer" to the node, not the node itself).
+  [K<sub>i</sub>, D<sub>i</sub>] is inserted in the index container.
   </li>
 
   <li>
-  If the index is non-unique, it maps key tuples to sets of domain nodes. In 
-  this case, if the index already contains an entry whose key is equal to
-  K<sub>i</sub>, D<sub>i</sub> is added to the set associated with K<sub>i</sub>.
-  Otherwise, the entry [K<sub>i</sub>, { D<sub>i</sub> }] is inserted in the
-  index.
+  If the index is non-unique, then if it already contains an entry whose key 
+  tuple is equal to K<sub>i</sub>, D<sub>i</sub> is added to the set associated
+  with K<sub>i</sub>. Otherwise, the entry [K<sub>i</sub>, { D<sub>i</sub> }] 
+  is inserted in the index.
   </li>
   </ul>
 
@@ -1673,7 +1681,7 @@
   to value indexes, the result of this IndexKeySpec may be a sequence of any
   number of atomic items, and the items may have different data types. We call 
   this sequence a <strong>key sequence</strong>, and each atomic item in it a 
-  <strong>key item</strong>.
+  <strong>key item</strong> (the key sequence may also be the empty sequence).
   </li>
 
   <li>
@@ -1694,17 +1702,6 @@
   into K<sub>i</sub>.
   </li>
 
-  <li> 
-  If any item in the expanded key sequence has a data type that is not a 
-  primitive builtin type, this data type is changed to the nearest base type 
-  that is a primitive builtin type. For example, xs:token is changed to 
-  xs:string, and xs:long is changed to xs:decimal. (Note: this is a conceptual 
-  description of the index creation process. The actual implementation may 
-  differ from this description as long as the results of 
-  <a href="#index_probing">probe functions</a> are always the same as those 
-  implied by this conceptual description.)
-  </li>
-
   <li>
   The next step is to insert in the index a mapping from K<sub>ij</sub> to 
   D<sub>i</sub>, for each key item K<sub>ij</sub> in the expanded key sequence
@@ -1714,32 +1711,25 @@
   </li>
 
   <li>
-  If the index is declared as unique, the relationship between between key
-  items and domain nodes is one-to-one. In this case, if the index already
-  contains an entry whose key item has the same type as K<sub>ij</sub> and
-  its value is equal to K<sub>ij</sub>, an error is raised 
+  If the index is declared as unique, the relationship between key items and 
+  domain nodes is one-to-one. In this case, if the index already contains an 
+  entry whose key item is equal to K<sub>ij</sub>, an error is raised 
   [<a href="#ERRZDDY0024">zerr:ZDDY0024</a>]. Otherwise, the entry 
   [K<sub>ij</sub>, D<sub>i</sub>] is inserted in the index container.
-  <li>
-
-  <li>
-  If the index is non-unique, it maps key items to sets of domain nodes. In 
-  this case, if the index already contains an entry whose key K has the same
-  type as K<sub>ij</sub> and its value is equal to K<sub>ij</sub>, D<sub>i</sub>
-  is added to the set associated with K. Otherwise, the entry [K<sub>ij</sub>, 
-  { D<sub>i</sub> }] is inserted into the index.  
-  </li>
-
-  <li>
-  In addition to its entry set, each general index entry stores 2 extra flags: 
-  The <strong>multi-key flag</strong> is set to true if there is any domain
-  node whose unexpanded key sequence contained more than 1 items; otherwise the 
-  flag is false. The <strong>untyped flag</strong> is set to true if during the 
-  expansion of a key sequence, an untyped key was successfully cast to an item
-  with a type other than xs:string or xs:anyURI.; otherwise the flag is false. 
-  As we will see later, these flags are needed during <a href="#index_probing">
-  index probing</a>.
-  </li>
+  </li>
+
+  <li>
+  If the index is non-unique, then if it already contains an entry whose key
+  K is equal to K<sub>ij</sub>, D<sub>i</sub> is added to the node set 
+  associated with K. Otherwise, the entry [K<sub>ij</sub>, { D<sub>i</sub> }] 
+  is inserted into the index.  
+  </li>
+
+  <li>
+  The index maintains a "special" entry for all domain nodes whose key sequence
+  is empty. All such nodes are inserted in the node set associated with this entry.
+  </li>
+
   </ul>
 
 <li>
@@ -1764,28 +1754,32 @@
 
 The delete function is evaluated as follows:
 
-  <ul>
-  <li>If the given expanded QName does not identify an index among the
-statically known indexes in the static context of the invoking module, an error
-is raised [<a href="#ERRZDDY0021">zerr:ZDDY0021</a>].</li>
-  <li>If the given expanded QName does not identify an index among the available
+<ul>
+<li>
+If the given expanded QName does not identify an index among the statically 
+known indexes in the static context of the invoking module, an error is
+raised [<a href="#ERRZDDY0021">zerr:ZDDY0021</a>].
+</li>
+<li>
+If the given expanded QName does not identify an index among the available
 indexes in the dynamic context of the invoking module, an error is raised [<a
-href="#ERRZDDY0023" title="zerr:ZDDY0023">zerr:ZDDY0023</a>].</li>
-  <li>The result of the function is an empty XDM instance and a pending update
-list that consists of a single update primitive:
-upd:deleteIndex($indexName).</li>
-  </ul>
+href="#ERRZDDY0023">zerr:ZDDY0023</a>].
+</li>
+<li>
+The result of the function is an empty XDM instance and a pending update
+list that consists of a single update primitive: upd:deleteIndex($indexName).
+</li>
+</ul>
 
 The update primitive is applied as follows:
 
-  <ul>
-  <li>The index entry container for the index is found via the indexes
-table.</li>
-  <li>All entries in the container are destroyed.</li>
-  <li>The container itself is destroyed.</li>
-  <li>The entry mapping the index name to the index entry container is removed
+<ul>
+<li>The index entry container for the index is found via the indexes table.</li>
+<li>All entries in the container are destroyed.</li>
+<li>The container itself is destroyed.</li>
+<li>The entry mapping the index name to the index entry container is removed
 from the indexes table.</li>
-  </ul>
+</ul>
 
 
 \subsection index_probing Index Probing
@@ -1808,24 +1802,17 @@
 <a name="probe_index_point_value" id="probe_index_point_value"></a>
 \code
   idml:probe-index-point-value($indexUri as xs:QName,
-                                $key1     as xs:anyAtomicType?,
-                                ...,
-                                $keyM     as xs:anyAtomicType?) as node()*
+                               $key1     as xs:anyAtomicType?,
+                               ...,
+                               $keyM     as xs:anyAtomicType?) as node()*
 \endcode
 
-For the probe-index-point-value function, the search condition is specified as a
-number of <strong>search keys</strong> comprising a <strong>search 
-tuple</strong>. A search key is either an atomic item or the empty sequence.
-The number of search keys must be equal to the number of IndexKeySpecs found 
-in the index declaration [<a href="#ERRZDDY0025"> zerr:ZDDY0025</a>]. (Remember 
-that for general indexes, there can be only one IndexKeySpec, and as a result, 
-for general indexes, the probe-index-point-value function takes only one search 
-value as input). Furthermore, for each search key that is not the empty sequence, 
-its type must match the sequence type specified in the corresponding IndexKeyTypeDecl;
-otherwise, a type error is raised [err:XPTY0004].
-
-The result of this function is either an error or the set of domain nodes for which 
-the following xquery condition returns true:
+The probe-index-point-value function retrieves the domain nodes associated by 
+value equality with a given <strong>search tuple</strong>. The search tuple 
+consists of a number of <strong>search keys</strong>, where each search key 
+is either an atomic item or the empty sequence. The result of this function 
+is either an error or the set of domain nodes for which the following xquery 
+expression returns true:
 
 \code
 $key1 eq $node/keyExpr1 and ... and $keyM eq $node/keyExprM
@@ -1835,12 +1822,22 @@
 of the index. Notice that this definition implies that if any of search keys
 is the empty sequence, the result of the probe is also the empty sequence.
 
-In addition to the error conditions described already, the function raises
-a type error [err:XPTY0004] if the index is general and (a) the multi-key flag
-of the index is true, or (b) the untyped flag of the index is true and the type of
-any non-empty search key is something other than xs:untypedAtomic, xs:string, or 
-xs:anyURI (or subtype of these).
+In addition to the errors that may be raised by the above expression, the
+probe-index-point-value function may raise the following errors:
 
+<ul>
+<li>
+[<a href="#ERRZDDY0025"> zerr:ZDDY0025</a>], if the number of search keys is not
+equal to the number of IndexKeySpecs found in the index declaration. (Remember 
+that for general indexes, there can be only one IndexKeySpec, and as a result, 
+for general indexes, the probe-index-point-value function takes only one search 
+key as input).
+</li>
+<li>
+[err:XPTY0004], if a non-empty seach key is given, whose type does not match 
+the sequence type specified in the corresponding IndexKeyTypeDecl;
+</li>
+</ul>
 
 <strong>idml:probe-index-point-general</strong>
 
@@ -2293,8 +2290,8 @@
   <a name="ERRZDST0024" id="ERRZDST0024"></a>zerr:ZDST0024, The declaration for
 index specifies multiple values for the same property.
 
-  <a name="ERRZDST0025" id="ERRZDST0025"></a>zerr:ZDST0025, The declaration for
-index specifies conflicting property values.
+  <a name="ERRZDST0025" id="ERRZDST0025"></a>zerr:ZDST0025, The index cannot be
+declared as unique.
 
   <a name="ERRZDST0026" id="ERRZDST0026"></a>zerr:ZDST0026, The declaration for
 index contains an invalid property value.

=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h	2011-10-05 17:49:48 +0000
+++ include/zorba/pregenerated/diagnostic_list.h	2011-10-13 19:58:25 +0000
@@ -624,6 +624,8 @@
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDST0024_INDEX_MULTIPLE_PROPERTY_VALUES;
 
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDST0025_INDEX_BAD_UNIQUE_PROPERTY;
+
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDST0026_INDEX_INVALID_PROPERTY_VALUE;
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDST0027_INDEX_BAD_KEY_TYPE;
@@ -684,10 +686,6 @@
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZSTR0004_INDEX_PARTIAL_KEY_REMOVE;
 
-extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZSTR0005_INDEX_PARTIAL_KEY_PROBE;
-
-extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZSTR0006_INDEX_INVALID_BOX_PROBE;
-
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZSTR0007_INDEX_UNSUPPORTED_PROBE_CONDITION;
 
 extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZSTR0008_COLLECTION_ALREADY_EXISTS;

=== modified file 'modules/com/zorba-xquery/www/modules/pregenerated/errors.xq'
--- modules/com/zorba-xquery/www/modules/pregenerated/errors.xq	2011-10-05 17:49:48 +0000
+++ modules/com/zorba-xquery/www/modules/pregenerated/errors.xq	2011-10-13 19:58:25 +0000
@@ -549,6 +549,10 @@
 
 (:~
 :)
+declare variable $zerr:ZDST0025 as xs:QName := fn:QName($zerr:NS, "zerr:ZDST0025");
+
+(:~
+:)
 declare variable $zerr:ZDST0026 as xs:QName := fn:QName($zerr:NS, "zerr:ZDST0026");
 
 (:~
@@ -664,14 +668,6 @@
 
 (:~
 :)
-declare variable $zerr:ZSTR0005 as xs:QName := fn:QName($zerr:NS, "zerr:ZSTR0005");
-
-(:~
-:)
-declare variable $zerr:ZSTR0006 as xs:QName := fn:QName($zerr:NS, "zerr:ZSTR0006");
-
-(:~
-:)
 declare variable $zerr:ZSTR0007 as xs:QName := fn:QName($zerr:NS, "zerr:ZSTR0007");
 
 (:~

=== modified file 'modules/com/zorba-xquery/www/modules/store/static/indexes/dml.xq'
--- modules/com/zorba-xquery/www/modules/store/static/indexes/dml.xq	2011-08-26 23:36:24 +0000
+++ modules/com/zorba-xquery/www/modules/store/static/indexes/dml.xq	2011-10-13 19:58:25 +0000
@@ -22,7 +22,7 @@
  :
  : <p>This module is part of <a href="../../html/xqddf.html">Zorba's XQuery Data
  : Definition Facility</a>. All the indexes managed by this module
- : have to be pre-declared in the prolog of a module. Please refer to the
+ : have to be pre-declared in the prolog of a library module. Please refer to the
  : <a href="../../html/data_lifecycle.html">general documentation</a>
  : for more information and examples.</p>
  :
@@ -35,7 +35,7 @@
  : @see http://www.zorba-xquery.com/modules/store/static/integrity_constraints/dml
  : @see <a href="www.zorba-xquery.com_errors.html">http://www.zorba-xquery.com/errors</a>
  :
- : @author Nicolae Brinza, Matthias Brantner, David Graf, Till Westmann, Markos Zaharioudakis
+ : @author Zorba Team
  :
  : @project store/indexes/static
  :
@@ -46,29 +46,36 @@
 declare namespace ann = "http://www.zorba-xquery.com/annotations";;
 
 declare namespace ver = "http://www.zorba-xquery.com/options/versioning";;
+
 declare option ver:module-version "2.0";
 
 (:~
- : The probe function retrieves the domain nodes associated with a particular
- : search condition, which is presented as a single key tuple. This function 
- : is variadic and accepts a variable number of key arguments.
+ : The probe-index-point-value function retrieves the domain nodes associated
+ : by value equality with a particular search tuple. This function is variadic
+ : because the number of search keys comprising the search tuple is not fixed.
  : 
  : The first argument is the QName identifying the index to probe. The remaining 
- : arguments specify the search condition, which is given as a number of 
- : (optional) atomic items comprising a key tuple. The number of key tuples
- : given must be equal to the number of keys declared for the index.
+ : arguments specify the search condition, which is given as a number of search
+ : keys comprising a search tuple. Each search key is either an atomic item
+ : or the empty sequence. The number of search keys given must be equal to the
+ : number of keys declared for the index. 
  :
  : @param $name The QName of the index to probe
- : @param $key_i any number of key used to probe the index (i.e. the search condition).
- :
- : @return If the index contains an entry with the given key tuple,
- :   the associated domain nodes are
- : returned. Otherwise, the empty sequence is returned.
+ : @param $key_i the search keys used to probe the index with. The i-th search
+ :        key corresponds to the i-th key expression in the index declaration.
+ :
+ : @return the set of domain nodes for which the following xquery expression 
+ : returns true:
+ :
+ : $key1 eq $node/keyExpr1 and ... and $keyM eq $node/keyExprM
  :
  : @error zerr:ZDDY0021 if the index with name $name is not declared.
  : @error zerr:ZDDY0023 if the index with name $name does not exist.
- : @error zerr:ZDDY0025 if the number of keys passed as arguments
- :    does not match the number of keys declared for the index.
+ : @error zerr:ZDDY0025 if the number of search keys passed as arguments is not
+ :        the same as the number of keys declared for the index.
+ : @error err:XPTY0004 if a search key is given that is not the empty sequence,
+ :        and whose type does not match the sequence type specified in the 
+ :        index declaration for the corresponding key expression.
  :)
 declare %ann:variadic function idml:probe-index-point-value(
   $name as xs:QName, 
@@ -76,6 +83,14 @@
 
 
 (:~
+ : @param $name The QName of the index to probe
+ :)
+declare %ann:variadic function idml:probe-index-point-general(
+  $name as xs:QName, 
+  $key  as xs:anyAtomicType*) as node()*  external; 
+
+
+(:~
  : The probe function retrieves the domain nodes associated with a particular
  : search condition, which is presented as a range of key tuples.
  : This function accept a variable number of arguments.
@@ -118,13 +133,31 @@
  : @error zerr:ZDDY0025 if the number of rangespecs passed as arguments
  :    does not match the number of keys declared for the index.
  :)
-declare %ann:variadic function idml:probe-index-range-value($name as xs:QName, 
-  $rangeLowerBound1         as xs:anyAtomicType?,
-  $rangeUpperBound1         as xs:anyAtomicType?,
-  $rangeHaveLowerBound1     as xs:boolean,
-  $rangeHaveupperBound1     as xs:boolean,
-  $rangeLowerBoundIncluded1 as xs:boolean,
-  $rangeupperBoundIncluded1 as xs:boolean) as node()*  external;
+declare %ann:variadic function idml:probe-index-range-value(
+  $name                as xs:QName, 
+  $lowerBound1         as xs:anyAtomicType?,
+  $upperBound1         as xs:anyAtomicType?,
+  $haveLowerBound1     as xs:boolean,
+  $haveupperBound1     as xs:boolean,
+  $lowerBoundIncluded1 as xs:boolean,
+  $upperBoundIncluded1 as xs:boolean) as node()*  external;
+
+
+(:~
+ : @param $name The QName of the index to probe
+ :
+ : @error zerr:ZDDY0021 if the index with name $name is not declared.
+ : @error zerr:ZDDY0023 if the index with name $name does not exist.
+ :)
+declare %ann:variadic function idml:probe-index-range-general(
+  $name               as xs:QName, 
+  $lowerBound         as xs:anyAtomicType*,
+  $upperBound         as xs:anyAtomicType*,
+  $haveLowerBound     as xs:boolean,
+  $haveupperBound     as xs:boolean,
+  $lowerBoundIncluded as xs:boolean,
+  $upperBoundIncluded as xs:boolean) as node()*  external;
+
 
 (:~
  : The refresh-index function is an updating function which updates
@@ -136,6 +169,7 @@
  : @return The result of the function is an empty XDM instance and a
  :         pending update list which, when applied, refreshes the contents
  :         of the index.that consists of a
+ :
  : @error zerr:ZDDY0021 if the index with name $name is not declared.
  : @error zerr:ZDDY0023 if the index with name $name does not exist.
  :)

=== modified file 'src/compiler/translator/translator.cpp'
--- src/compiler/translator/translator.cpp	2011-10-03 09:18:49 +0000
+++ src/compiler/translator/translator.cpp	2011-10-13 19:58:25 +0000
@@ -4122,11 +4122,8 @@
 
   if ( !theSctx->is_feature_set(feature::ddl) )
   {
-    throw XQUERY_EXCEPTION(
-      zerr::ZXQP0050_FEATURE_NOT_AVAILABLE,
-      ERROR_PARAMS( "data-definition (ddl)" ),
-      ERROR_LOC( v.get_location() )
-    );
+    RAISE_ERROR(zerr::ZXQP0050_FEATURE_NOT_AVAILABLE, v.get_location(),
+    ERROR_PARAMS("data-definition (ddl)"));
   }
 
   const QName* qname = v.getName();
@@ -4148,10 +4145,10 @@
   }
 
   IndexDecl_t index = new IndexDecl(theSctx, loc, qnameItem);
-  index->setGeneral ( false );
-  index->setUnique ( false );
-  index->setMethod ( IndexDecl::HASH );
-  index->setMaintenanceMode ( IndexDecl::MANUAL );
+  index->setGeneral(false);
+  index->setUnique(false);
+  index->setMethod(IndexDecl::HASH);
+  index->setMaintenanceMode(IndexDecl::MANUAL);
 
   AnnotationListParsenode* lAnns = v.get_annotations();
   if (lAnns)
@@ -4159,27 +4156,28 @@
     lAnns->accept(*this);
   }
 
-  if ( theAnnotations )
+  if (theAnnotations)
   {
-    if ( ZANN_CONTAINS ( zann_general_equality ) ||
-         ZANN_CONTAINS ( zann_general_range ) ) 
-    {
-      index->setGeneral( true );
-    }
-    if ( ZANN_CONTAINS ( zann_general_range ) ||
-         ZANN_CONTAINS ( zann_value_range ) ) 
-    {
-      index->setMethod( IndexDecl::TREE );
-    }
-    if ( ZANN_CONTAINS ( zann_unique ) )
-    {
-      index->setUnique( true );
-    }
-    if ( ZANN_CONTAINS ( zann_automatic ) )
+    if (ZANN_CONTAINS(zann_general_equality) ||
+        ZANN_CONTAINS(zann_general_range)) 
+    {
+      index->setGeneral(true);
+    }
+    if (ZANN_CONTAINS(zann_general_range) ||
+        ZANN_CONTAINS(zann_value_range)) 
+    {
+      index->setMethod(IndexDecl::TREE);
+    }
+    if (ZANN_CONTAINS(zann_unique))
+    {
+      index->setUnique(true);
+    }
+    if (ZANN_CONTAINS(zann_automatic))
     {
       index->setMaintenanceMode(IndexDecl::REBUILD);
     }
   }
+
   theAnnotations = NULL;
 
   theIndexDecl = index;

=== modified file 'src/compiler/xqddf/value_index.cpp'
--- src/compiler/xqddf/value_index.cpp	2011-06-14 17:26:33 +0000
+++ src/compiler/xqddf/value_index.cpp	2011-10-13 19:58:25 +0000
@@ -36,6 +36,8 @@
 
 #include "store/api/item_factory.h"
 
+#include "diagnostics/util_macros.h"
+
 
 namespace zorba
 {
@@ -52,6 +54,7 @@
     const QueryLoc& loc,
     const store::Item_t& name)
   :
+  theLocation(loc),
   theSctx(sctx),
   theName(name),
   theIsGeneral(false),
@@ -210,7 +213,28 @@
 ********************************************************************************/
 void IndexDecl::setKeyTypes(const std::vector<xqtref_t>& keyTypes)
 {
+  assert(!keyTypes.empty());
+
   theKeyTypes = keyTypes;
+
+  if (theIsGeneral && theIsUnique)
+  {
+    TypeManager* tm = theSctx->get_typemanager();
+
+    xqtref_t type = theKeyTypes[0];
+    xqtref_t ptype;
+
+    if (type != NULL)
+      ptype = TypeOps::prime_type(tm, *type);
+
+    if (ptype == NULL ||
+        TypeOps::is_equal(tm, *ptype, *GENV_TYPESYSTEM.ANY_ATOMIC_TYPE_ONE) ||
+        TypeOps::is_subtype(tm, *ptype, *GENV_TYPESYSTEM.UNTYPED_ATOMIC_TYPE_ONE))
+    {
+      RAISE_ERROR(zerr::ZDST0025_INDEX_BAD_UNIQUE_PROPERTY, theLocation,
+      ERROR_PARAMS(theName->getStringValue()));
+    }
+  }
 }
 
 
@@ -269,7 +293,7 @@
 
   std::vector<expr*> keySources;
 
-  ulong numKeys = (ulong)theKeyExprs.size();
+  csize numKeys = theKeyExprs.size();
 
   if (theIsGeneral && numKeys > 1)
   {
@@ -281,7 +305,7 @@
   }
 
   // Check constraints on the key exprs
-  for (ulong i = 0; i < numKeys; ++i)
+  for (csize i = 0; i < numKeys; ++i)
   {
     analyzeExprInternal(theKeyExprs[i].getp(),
                         theSourceNames,
@@ -307,11 +331,9 @@
     // theMaintenanceMode is initially set to REBUILD. If theMaintenanceMode
     // is not changed above (to DOC_MAP), then we throw an error because we
     // don't want to automatically rebuild the full index with every update. 
-		throw XQUERY_EXCEPTION(
-			zerr::ZDST0034_INDEX_CANNOT_DO_AUTOMATIC_MAINTENANCE,
-			ERROR_PARAMS( theName->getStringValue() ),
-			ERROR_LOC( getDomainExpr()->get_loc() )
-		);
+    RAISE_ERROR(zerr::ZDST0034_INDEX_CANNOT_DO_AUTOMATIC_MAINTENANCE,
+    getDomainExpr()->get_loc(),
+    ERROR_PARAMS(theName->getStringValue()));
   }
 }
 
@@ -342,11 +364,8 @@
 
     if (!func->isDeterministic())
     {
-			throw XQUERY_EXCEPTION(
-				zerr::ZDST0028_INDEX_NOT_DETERMINISTIC,
-				ERROR_PARAMS( theName->getStringValue() ),
-				ERROR_LOC( e->get_loc() )
-			);
+			RAISE_ERROR(zerr::ZDST0028_INDEX_NOT_DETERMINISTIC, e->get_loc(),
+			ERROR_PARAMS(theName->getStringValue()));
     }
 
     if (func->isSource())
@@ -364,20 +383,14 @@
         }
         else
         {
-					throw XQUERY_EXCEPTION(
-						zerr::ZDST0030_INDEX_NON_CONST_DATA_SOURCE,
-						ERROR_PARAMS( theName->getStringValue() ),
-						ERROR_LOC( e->get_loc() )
-					);
+					RAISE_ERROR(zerr::ZDST0030_INDEX_NON_CONST_DATA_SOURCE, e->get_loc(),
+          ERROR_PARAMS(theName->getStringValue()));
         }
       }
       else
       {
-				throw XQUERY_EXCEPTION(
-					zerr::ZDST0029_INDEX_INVALID_DATA_SOURCE,
-					ERROR_PARAMS( theName->getStringValue() ),
-					ERROR_LOC( e->get_loc() )
-				);
+        RAISE_ERROR(zerr::ZDST0029_INDEX_INVALID_DATA_SOURCE, e->get_loc(),
+        ERROR_PARAMS(theName->getStringValue()));
       }
     }
   }

=== modified file 'src/compiler/xqddf/value_index.h'
--- src/compiler/xqddf/value_index.h	2011-08-12 16:07:57 +0000
+++ src/compiler/xqddf/value_index.h	2011-10-13 19:58:25 +0000
@@ -92,32 +92,44 @@
   Data members:
   -------------
 
-  - theSctx :
+  theLocation:
+  ------------
+  The query location where the index declaration appears at.
+
+  theSctx:
+  --------
   The root static context of the data module containing the index declaration.
 
-  - theName :
+  theName:
+  --------
   The qname that identifies the index.
 
-  - theIsGeneral :
+  theIsGeneral:
+  -------------
 
-  - theIsUnique :
+  theIsUnique:
+  ------------
   Whether it is a unique index or not. 
 
-  - theIsTemp :
+  theIsTemp:
+  ----------
   Whether it is a temp index or not. A temp index is an index that is created
   on-the-fly to optimize a query by converting a nested-lopp join to a hashjoin
   (see index_join_rule.cpp). Such an index is destroyed at the end of the query
   that created it.
 
-  - theMaintenanceMode: 
+  theMaintenanceMode:
+  ------------------- 
   If and how to maintain the index during/after each apply-updates or not.
 
-  - theContainerKind : 
+  theContainerKind:
+  ----------------- 
   The kind if container used to implement the index. Currently, there are 2 
   kinds: a tree-based container (std::map) for ordered indexes, or hash-based
   container for unordered indexes.
 
-  - theDomainClause : 
+  theDomainClause:
+  ---------------- 
   A FOR-clause that associates the domain expr with a FOR var that is referenced
   by the key exprs and acts as the domain node for those exprs. If dexpr is the
   domain expr specified in the index declaration, the actual domain expr is:
@@ -125,25 +137,31 @@
   for value indexes   : domainExpr := dexpr treat as node()*
   for general indexes : domainExpr := check-distinct-nodes(dexpr treat as node()*)
 
-  - theKeyExprs :
+  theKeyExprs:
+  ------------
   The key expressions of the index. If kexpr is a key expr specified in the 
   index declaration, the actual domain expr is:
 
   for value indexes   : keyExpr := fn:data(kexpr) treat as typeDecl
   for general indexes : distinct-values(fn:data(kexpr) treat as typeDecl)
 
-  - theKeyTypes :
-  The atomic item type that each key value must match with according to the 
-  rules of sequence type matching. For value indexes, their index declaration
-  must always specify a type T, and the item type of T may not be xs:anyAtomicType
-  or xs:untypedAtomic. For general indexes, the key type declaration may be 
-  absent, or its item type may be xs:anyAtomicType or xs:untypedAtomic. If
-  absent, the associated entry in theKeyTypes will be NULL, but this is treated
-  the same as xs:anyAtomicType.
-
-  - theOrderModifiers :
-
-  - theSourceNames :
+  theKeyTypes:
+  ------------
+  For each key expr, this vector contains the builtin atomic item that is the
+  base of the atomic type type T specified for that key expr. For value indexes,
+  their index declaration must always specify a type T, and the item type of T 
+  may not be xs:anyAtomicType or xs:untypedAtomic. For general indexes, the key 
+  type declaration may be absent, or its item type may be xs:anyAtomicType or 
+  xs:untypedAtomic. If absent, the associated entry in theKeyTypes will be NULL, 
+  but this is treated the same as xs:anyAtomicType. The translator makes sure
+  that each key value inserted into the index matches with T according to the 
+  rules of sequence type matching. 
+
+  theOrderModifiers:
+  ------------------
+
+  theSourceNames:
+  -----------------
   The qnames of the collections referenced in the domain and key expressions.
   Currently, it is required that the arg given to every xqddf:collection()
   invocation within the domain expr or any of the key exprs is a constant expr.
@@ -166,11 +184,13 @@
   determine the collection set of an index as the index is being created, and
   then give this info to the store.
                    
-  - theDomainSourceExprs :
+  theDomainSourceExprs:
+  ---------------------
   A vector containing pointers to the xqddf:collection() exprs within the
   domain expr.    
 
-  -theBuildExpr :
+  theBuildExpr:
+  -------------
   The expr that computes the index entries. It is used to create or rebuild
   the full index from scratch. The expr is a flwor expr of the following form,
   for value and general indexes, respectively:
@@ -181,23 +201,27 @@
   for $$dot at $$pos in domainExpr
   return general-index-entry-builder($$dot, fieldExpr);
 
-  - theBuildPlan :
+  theBuildPlan:
+  -------------
   The runtime plan corresponding to theBuildExpr. During runtime (see
   CreateIndexIterator and RebuildIndexIterator), this plan is wrapper into a 
   PlanWrapper and then passed to the store, which uses it to create or 
   re-build the full index.
 
-  - theDocIndexerExpr : 
+  theDocIndexerExpr:
+  ------------------ 
   This is an expr that builds the index over a single xml tree, which is
   provided as an external var to this expr. It is basically the same as
   theBuildExpr except that a reference to a collection inside the domainExpr
   is replaced with a reference to an external var that can be bound dynamically
   to some xml tree.
                                             
-  - theDocIndexerVar :
+  theDocIndexerVar:
+  -----------------
   The external var appearing in theDocIndexerExpr.
 
-  - theDocIndexer : 
+  theDocIndexer:
+  -------------- 
   If the index domain expr is a map over a collection C, then theDocIndexer obj
   is not NULL and it provides a method that takes as input a document D in C 
   and produces all the index entries for D. theDocIndexer obj is passed to the
@@ -223,6 +247,8 @@
 
 
 private:
+  QueryLoc                        theLocation;
+
   static_context                * theSctx;
 
   store::Item_t                   theName;

=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml	2011-10-05 18:52:55 +0000
+++ src/diagnostics/diagnostic_en.xml	2011-10-13 19:58:25 +0000
@@ -2046,6 +2046,10 @@
       <value>index multiple property values</value>
     </diagnostic>
 
+    <diagnostic code="ZDST0025" name="INDEX_BAD_UNIQUE_PROPERTY">
+      <value>"$1": index cannot be declared as unique</value>
+    </diagnostic>
+
     <diagnostic code="ZDST0026" name="INDEX_INVALID_PROPERTY_VALUE">
       <value>index invalid property value</value>
     </diagnostic>
@@ -2174,14 +2178,6 @@
       <value>"$1": partial key deletion from index "$2"</value>
     </diagnostic>
 
-    <diagnostic code="ZSTR0005" name="INDEX_PARTIAL_KEY_PROBE">
-      <value>"$1": partial key probe into index "$2"</value>
-    </diagnostic>
-
-    <diagnostic code="ZSTR0006" name="INDEX_INVALID_BOX_PROBE">
-      <value>for index "$1": $2</value>
-    </diagnostic>
-
     <diagnostic code="ZSTR0007" name="INDEX_UNSUPPORTED_PROBE_CONDITION">
       <value>"$1": unsupported probe condition for index "$2"</value>
     </diagnostic>

=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp	2011-10-05 17:49:48 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp	2011-10-13 19:58:25 +0000
@@ -915,6 +915,9 @@
 ZorbaErrorCode ZDST0024_INDEX_MULTIPLE_PROPERTY_VALUES( "ZDST0024" );
 
 
+ZorbaErrorCode ZDST0025_INDEX_BAD_UNIQUE_PROPERTY( "ZDST0025" );
+
+
 ZorbaErrorCode ZDST0026_INDEX_INVALID_PROPERTY_VALUE( "ZDST0026" );
 
 
@@ -1004,12 +1007,6 @@
 ZorbaErrorCode ZSTR0004_INDEX_PARTIAL_KEY_REMOVE( "ZSTR0004" );
 
 
-ZorbaErrorCode ZSTR0005_INDEX_PARTIAL_KEY_PROBE( "ZSTR0005" );
-
-
-ZorbaErrorCode ZSTR0006_INDEX_INVALID_BOX_PROBE( "ZSTR0006" );
-
-
 ZorbaErrorCode ZSTR0007_INDEX_UNSUPPORTED_PROBE_CONDITION( "ZSTR0007" );
 
 

=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp	2011-10-05 17:49:48 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp	2011-10-13 19:58:25 +0000
@@ -306,6 +306,7 @@
   { "ZDST0022", "\"$1\": index already imported into module \"$2\"" },
   { "ZDST0023", "\"$1\": index declaration not allowed in main module" },
   { "ZDST0024", "index multiple property values" },
+  { "ZDST0025", "\"$1\": index cannot be declared as unique" },
   { "ZDST0026", "index invalid property value" },
   { "ZDST0027", "\"$1\": index bad key type" },
   { "ZDST0028", "\"$1\": index not deterministic" },
@@ -337,8 +338,6 @@
   { "ZSTR0002", "\"$1\": index does not exist" },
   { "ZSTR0003", "\"$1\": partial key insertion into index \"$2\"" },
   { "ZSTR0004", "\"$1\": partial key deletion from index \"$2\"" },
-  { "ZSTR0005", "\"$1\": partial key probe into index \"$2\"" },
-  { "ZSTR0006", "for index \"$1\": $2" },
   { "ZSTR0007", "\"$1\": unsupported probe condition for index \"$2\"" },
   { "ZSTR0008", "\"$1\": collection already exists" },
   { "ZSTR0009", "\"$1\": collection not found" },

=== modified file 'src/runtime/indexing/index_ddl.cpp'
--- src/runtime/indexing/index_ddl.cpp	2011-10-05 17:49:48 +0000
+++ src/runtime/indexing/index_ddl.cpp	2011-10-13 19:58:25 +0000
@@ -135,11 +135,11 @@
 {
   const std::vector<xqtref_t>& keyTypes(indexDecl->getKeyTypes());
   const std::vector<OrderModifier>& keyModifiers(indexDecl->getOrderModifiers());
-  ulong numColumns = (ulong)keyTypes.size();
+  csize numColumns = keyTypes.size();
 
   spec.resize(numColumns);
 
-  for (ulong i = 0; i < numColumns; ++i) 
+  for (csize i = 0; i < numColumns; ++i) 
   {
     if (keyTypes[i] != NULL)
     {
@@ -156,11 +156,11 @@
   spec.theIsThreadSafe = true;
   spec.theIsAutomatic = indexDecl->getMaintenanceMode() != IndexDecl::MANUAL;
 
-  ulong numSources = (ulong)indexDecl->numSources();
+  csize numSources = indexDecl->numSources();
 
   spec.theSources.resize(numSources);
 
-  for (ulong i = 0; i < numSources; ++i)
+  for (csize i = 0; i < numSources; ++i)
   {
     spec.theSources[i] = const_cast<store::Item*>(indexDecl->getSourceName(i));
   }
@@ -545,7 +545,10 @@
 
 
 /*******************************************************************************
-  ProbeIndexPointValueIterator
+  probe-index-point-value($indexName as xs:QName,
+                          $key1      as anyAtomic?,
+                          ...,
+                          $keyN      as anyAtomic?) as node()*
 ********************************************************************************/
 
 ProbeIndexPointValueIteratorState::ProbeIndexPointValueIteratorState() 
@@ -720,7 +723,7 @@
 /*******************************************************************************
   ProbeIndexPointGeneralIterator
 
-  fn-zorba-ddl:probe-index-point-general(
+  probe-index-point-general(
       $indexName as xs:QName,
       $keys      as xs:anyAtomicItem*) as node()*
 
@@ -874,7 +877,24 @@
 
 
 /*******************************************************************************
-  ProbeIndexRangeValueIterator
+
+  probe-index-range-value($indexName               as xs:QName,
+                          $range1LowerBound         as anyAtomic?,
+                          $range1UpperBound         as anyAtomic?,
+                          $range1HaveLowerBound     as boolean?,
+                          $range1HaveupperBound     as boolean?,
+                          $range1LowerBoundIncluded as boolean?,
+                          $range1upperBoundIncluded as boolean?,
+                          ....,
+                          $rangeNLowerBound         as anyAtomic?,
+                          $rangeNUpperBound         as anyAtomic?,
+                          $rangeNHaveLowerBound     as boolean?,
+                          $rangeNHaveupperBound     as boolean?,
+                          $rangeNLowerBoundIncluded as boolean?,
+                          $rangeNupperBoundIncluded as boolean?) as node()*
+
+  Note: the translator makes sure that there is at least one range, and each
+        range consits of exactly 6 values.
 ********************************************************************************/
 
 ProbeIndexRangeValueIteratorState::ProbeIndexRangeValueIteratorState() 
@@ -930,7 +950,8 @@
 void ProbeIndexRangeValueIterator::serialize(::zorba::serialization::Archiver& ar)
 {
   serialize_baseclass(ar,
-  (NaryBaseIterator<ProbeIndexRangeValueIterator, ProbeIndexRangeValueIteratorState>*)this);
+  (NaryBaseIterator<ProbeIndexRangeValueIterator,
+                    ProbeIndexRangeValueIteratorState>*)this);
 
   ar & theCheckKeyType;
 }
@@ -970,13 +991,9 @@
       ERROR_PARAMS(qname->getStringValue()));
     }
 
-    if ((numChildren-1) % 6 != 0)
-    {
-      RAISE_ERROR(zerr::ZDDY0025_INDEX_WRONG_NUMBER_OF_PROBE_ARGS, loc,
-      ERROR_PARAMS(qname->getStringValue()));
-    }
+    assert(numChildren >= 7 && (numChildren-1) % 6 == 0);
 
-    if (indexDecl->getKeyExpressions().size() * 6 > numChildren-1)
+    if (indexDecl->getKeyExpressions().size() * 6 < numChildren-1)
     {
       RAISE_ERROR(zerr::ZDDY0025_INDEX_WRONG_NUMBER_OF_PROBE_ARGS, loc,
       ERROR_PARAMS(qname->getStringValue()));
@@ -1114,7 +1131,7 @@
 
 
 /*******************************************************************************
-  ProbeIndexRangeGeneralIterator
+  probe-index-range-general
 ********************************************************************************/
 ProbeIndexRangeGeneralIteratorState::ProbeIndexRangeGeneralIteratorState()
   :

=== modified file 'src/runtime/indexing/index_ddl.h'
--- src/runtime/indexing/index_ddl.h	2011-08-12 16:07:57 +0000
+++ src/runtime/indexing/index_ddl.h	2011-10-13 19:58:25 +0000
@@ -191,17 +191,14 @@
 };
 
 
-/**
- * 
- *  refresh-index($indexName as xs:QName) as pul()
- *
- *  This is an updating function. During normal runtime (see RefreshIndexIterator),
- *  it checks that index exists (in the dynamic context) and generates an update
- *  primitive. During applyUpdates(), it clears the index of its contents and then
- *  rebuilds the index the same way as the create() function.
- *    
- * Author: Zorba Team
- */
+/******************************************************************************
+   refresh-index($indexName as xs:QName) as pul()
+ 
+   This is an updating function. During normal runtime (see RefreshIndexIterator),
+   it checks that index exists (in the dynamic context) and generates an update
+   primitive. During applyUpdates(), it clears the index of its contents and then
+   rebuilds the index the same way as the create() function.
+*******************************************************************************/
 class RefreshIndexIterator : public UnaryBaseIterator<RefreshIndexIterator, 
                                                       PlanIteratorState>
 { 
@@ -344,6 +341,9 @@
                            $key1      as anyAtomic?,
                            ...,
                            $keyN      as anyAtomic?) as node()*
+
+  Note: the translator wraps calls to this function with an OP_NODE_SORT_ASC
+  function.
 ********************************************************************************/
 class ProbeIndexPointValueIteratorState : public PlanIteratorState
 {
@@ -403,6 +403,9 @@
                              $key1      as anyAtomic*,
                               ...,
                              $keyN      as anyAtomic*) as node()*
+
+  Note: the translator wraps calls to this function with an OP_NODE_SORT_DISTINCT_ASC
+  function.
 ********************************************************************************/
 class ProbeIndexPointGeneralIteratorState : public ProbeIndexPointValueIteratorState
 {
@@ -431,11 +434,12 @@
 
   void serialize(::zorba::serialization::Archiver& ar);
 
+public:
   ProbeIndexPointGeneralIterator(
-        static_context* sctx,
-        const QueryLoc& loc,
-        std::vector<PlanIter_t>& children);
-
+      static_context* sctx,
+      const QueryLoc& loc,
+      std::vector<PlanIter_t>& children);
+  
   ~ProbeIndexPointGeneralIterator();
 
   void accept(PlanIterVisitor& v) const;
@@ -460,6 +464,9 @@
                            $rangeNLowerBoundIncluded as boolean?,
                            $rangeNupperBoundIncluded as boolean?) as node()*
 
+  Note: the translator wraps calls to this function with an OP_NODE_SORT_ASC
+  function.
+
   theQname    : the name of the index
   theIndex    : the index to probe
   theIterator : the index probe iterator
@@ -482,10 +489,9 @@
 };
 
 
-class ProbeIndexRangeValueIterator 
-  :
-  public NaryBaseIterator<ProbeIndexRangeValueIterator,
-                          ProbeIndexRangeValueIteratorState>
+class ProbeIndexRangeValueIterator :
+public NaryBaseIterator<ProbeIndexRangeValueIterator,
+                        ProbeIndexRangeValueIteratorState>
 {
 protected:
   bool theCheckKeyType;
@@ -498,10 +504,11 @@
 
   void serialize(::zorba::serialization::Archiver& ar);
 
+public:
   ProbeIndexRangeValueIterator(
-        static_context* sctx,
-        const QueryLoc& loc,
-        std::vector<PlanIter_t>& children);
+      static_context* sctx,
+      const QueryLoc& loc,
+      std::vector<PlanIter_t>& children);
 
   ~ProbeIndexRangeValueIterator();
 
@@ -553,10 +560,9 @@
 };
 
 
-class ProbeIndexRangeGeneralIterator 
-  : 
-  public NaryBaseIterator<ProbeIndexRangeGeneralIterator, 
-                          ProbeIndexRangeGeneralIteratorState>
+class ProbeIndexRangeGeneralIterator : 
+public NaryBaseIterator<ProbeIndexRangeGeneralIterator, 
+                        ProbeIndexRangeGeneralIteratorState>
 {
 protected:
   bool theCheckKeyType;
@@ -569,11 +575,12 @@
 
   void serialize(::zorba::serialization::Archiver& ar);
 
+public:
   ProbeIndexRangeGeneralIterator(
-        static_context* sctx,
-        const QueryLoc& loc,
-        std::vector<PlanIter_t>& children);
-
+      static_context* sctx,
+      const QueryLoc& loc,
+      std::vector<PlanIter_t>& children);
+  
   ~ProbeIndexRangeGeneralIterator();
 
   void accept(PlanIterVisitor& v) const;

=== modified file 'src/store/api/index.h'
--- src/store/api/index.h	2011-09-30 14:06:33 +0000
+++ src/store/api/index.h	2011-10-13 19:58:25 +0000
@@ -29,8 +29,6 @@
 {
 
 class IndexSpecification;
-class IndexKeyCompareFunction;
-class IndexColumnRange;
 class IndexEntryCreator;
 class Iterator;
 
@@ -40,26 +38,54 @@
 /***************************************************************************//**
   Specification for creating a value or general index.
 
-  theNumKeyColumns: The number of columns in each key.
-  theKeyTypes     : The data types of the key columns. Each type must be a
-                    builtin atomic type, and for sorted indices, it must have
-                    an ordering.
-  theCollations   : The names (uris) of the collations to use when comparing the
-                    string columns of two keys. The size of this vector is equal
-                    to theNumKeyColumns; if a type of a key column is not string,
-                    the associated entry in theCollations is the empty string.
-  theTimezone     : The timezone is needed to compare date/time key values.
-  theIsGeneral    : Whether the index is "general" or not.
-  theIsUnique     : Whether the index is unique, i.e., there is exactly one
-                    value associated with each key.
-  theIsSorted     : Whether the index is sorted by its key values or not.
-  theIsTemp       : Whether the index is temporary or not.
-  theIsThreadSafe : Whether the index can be shared among multiple threads or not
-  theIsAutomatic  : Whether the index must be maintained during/after each apply-
-                    updates or not.
-
-  theSources      : The qnames of the collections accessed by the defining exprs
-                    of this index.
+  theNumKeyColumns: 
+  -----------------
+  The number of columns in each key.
+
+  theKeyTypes:
+  ------------
+  The data types of the key columns. Each type must be a builtin atomic type,
+  and for sorted indices, it must have an ordering.
+
+  theCollations: 
+  --------------
+  The names (uris) of the collations to use when comparing the string columns 
+  of two keys. The size of this vector is equal to theNumKeyColumns; if a type
+  of a key column is not string, the associated entry in theCollations is the 
+  empty string.
+
+  theTimezone:
+  ------------
+  The timezone is needed to compare date/time key values.
+
+  theIsGeneral:
+  -------------
+  Whether the index is "general" or not.
+
+  theIsUnique: 
+  ------------
+  Whether the index is unique, i.e., there is exactly one value associated with
+  each key.
+
+  theIsSorted:
+  ------------
+  Whether the index is sorted by its key values or not.
+
+  theIsTemp:
+  ----------
+  Whether the index is temporary or not.
+
+  theIsThreadSafe:
+  ----------------
+  Whether the index can be shared among multiple threads or not.
+
+  theIsAutomatic:
+  ---------------
+  Whether the index must be maintained during/after each apply- updates or not.
+
+  theSources:
+  -----------
+  The qnames of the collections accessed by the defining exprs of this index.
 ********************************************************************************/
 class IndexSpecification
 {

=== modified file 'src/store/naive/atomic_items.h'
--- src/store/naive/atomic_items.h	2011-09-30 14:06:33 +0000
+++ src/store/naive/atomic_items.h	2011-10-13 19:58:25 +0000
@@ -29,6 +29,7 @@
 #include "store/api/item.h"
 #include "store/api/item_handle.h"
 #include "store/naive/store_defs.h"
+#include "store/naive/shared_types.h"
 
 #ifndef ZORBA_NO_FULL_TEXT
 #include "store/naive/naive_ft_token_iterator.h"
@@ -83,9 +84,6 @@
 };
 
 
-typedef store::ItemHandle<AtomicItem> AtomicItem_t;
-
-
 /*******************************************************************************
   class UserTypedAtomicItem
 ********************************************************************************/
@@ -1095,7 +1093,7 @@
 class DecimalItem : public AtomicItem
 {
   friend class BasicItemFactory;
-  friend class IndexBoxCondition;
+  friend class IndexConditionImpl;
   friend class AtomicItem;
 
 protected:

=== modified file 'src/store/naive/pul_primitives.cpp'
--- src/store/naive/pul_primitives.cpp	2011-10-12 21:41:55 +0000
+++ src/store/naive/pul_primitives.cpp	2011-10-13 19:58:25 +0000
@@ -1755,14 +1755,11 @@
 
   if (!lMap)
   {
-    throw ZORBA_EXCEPTION(
-      zerr::ZDDY0023_INDEX_DOES_NOT_EXIST,
-      ERROR_PARAMS( theQName->getStringValue() )
-    );
+    throw ZORBA_EXCEPTION(zerr::ZDDY0023_INDEX_DOES_NOT_EXIST,
+    ERROR_PARAMS(theQName->getStringValue()));
   }
 
-  simplestore::IndexImpl* lImpl =
-    static_cast<simplestore::IndexImpl*>(lMap.getp());
+  ValueIndex* lImpl = static_cast<ValueIndex*>(lMap.getp());
 
   theValue->open();
   store::Item_t lValue;
@@ -1779,7 +1776,7 @@
     }
 
     store::IndexKey* lKeyPtr = lKey.get();
-    if (!lImpl->insert(lKeyPtr, lValue, lKey->size() > 1))
+    if (!lImpl->insert(lKeyPtr, lValue))
     {
       // the index took the ownership over the key if the index
       // did _not_ already contain an entry with the same key

=== modified file 'src/store/naive/shared_types.h'
--- src/store/naive/shared_types.h	2011-09-22 21:50:20 +0000
+++ src/store/naive/shared_types.h	2011-10-13 19:58:25 +0000
@@ -30,6 +30,9 @@
 namespace simplestore 
 {
 
+class AtomicItem;
+typedef store::ItemHandle<AtomicItem> AtomicItem_t;
+
 class CollectionSet;
 class CollectionIterator;
 typedef rchandle<CollectionIterator> CollectionIterator_t;

=== modified file 'src/store/naive/simple_index.cpp'
--- src/store/naive/simple_index.cpp	2011-09-30 14:06:33 +0000
+++ src/store/naive/simple_index.cpp	2011-10-13 19:58:25 +0000
@@ -17,12 +17,13 @@
 
 #include "diagnostics/assert.h"
 #include "zorbautils/hashfun.h"
-#include "zorbatypes/collation_manager.h"
+
+#include "diagnostics/util_macros.h"
 
 #include "store/api/item.h"
 #include "store/naive/store_defs.h"
 #include "store/naive/simple_index.h"
-#include "store/naive/simple_index_general.h"
+//#include "store/naive/simple_index_general.h"
 #include "store/naive/atomic_items.h"
 #include "store/naive/simple_store.h"
 
@@ -35,114 +36,6 @@
 {
 
 
-/////////////////////////////////////////////////////////////////////////////////
-//                                                                             //
-//  IndexCompareFunction                                                       //
-//                                                                             //
-/////////////////////////////////////////////////////////////////////////////////
-
-
-/******************************************************************************
-
-********************************************************************************/
-uint32_t IndexCompareFunction::hash(const store::IndexKey* key) const
-{
-  uint32_t hval = FNV_32_INIT;
-
-  for (ulong i = 0; i < theNumColumns; ++i)
-  {
-    if ((*key)[i] == NULL)
-      continue;
-
-    hval = hashfun::h32<uint32_t>((*key)[i]->hash(theTimezone, theCollators[i]),
-                                  hval);
-  }
-
-  return hval;
-}
-
-
-/******************************************************************************
-
-********************************************************************************/
-bool IndexCompareFunction::equal(
-    const store::IndexKey* key1,
-    const store::IndexKey* key2) const
-{
-  for (ulong i = 0; i < theNumColumns; ++i)
-  {
-    const store::Item_t& i1 = (*key1)[i];
-    const store::Item_t& i2 = (*key2)[i];
-
-    if (i1 == NULL && i2 == NULL)
-      continue;
-
-    if (i1 == NULL || i2 == NULL)
-      return false;
-
-    if (! (*key1)[i]->equals((*key2)[i].getp(), theTimezone, theCollators[i]))
-      return false;
-  }
-
-  return true;
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-long IndexCompareFunction::compare(
-    const store::IndexKey* key1,
-    const store::IndexKey* key2) const
-{
-  long result;
-
-#ifndef WIN32
-  ulong size = std::min(key1->size(),  key2->size());
-#else
-  ulong size = std::min(key1->size(),  key2->size());
-#endif
-
-  for (ulong i = 0; i < size; i++)
-  {
-    const store::Item_t& i1 = (*key1)[i];
-    const store::Item_t& i2 = (*key2)[i];
-
-    if (i1 == NULL)
-    {
-      if (i2 != NULL)
-        return -1;
-    }
-    else if (i2 == NULL)
-    {
-      if (i1 != NULL)
-        return +1;
-    }
-    else if (i1 == IndexBoxCondition::theNegInf)
-    {
-      return -1;
-    }
-    else if (i1 == IndexBoxCondition::thePosInf)
-    {
-      return +1;
-    }
-    else if (i2 == IndexBoxCondition::theNegInf)
-    {
-      return +1;
-    }
-    else if (i2 == IndexBoxCondition::thePosInf)
-    {
-      return -1;
-    }
-    else if ((result = i1->compare(i2, theTimezone, theCollators[i])))
-    {
-      return result;
-    }
-  }
-
-  return 0;
-}
-
 
 /////////////////////////////////////////////////////////////////////////////////
 //                                                                             //
@@ -161,19 +54,6 @@
   theQname(qname),
   theSpec(spec)
 {
-  theCollators.resize(theSpec.getNumColumns());
-
-  for (ulong i = 0; i < theSpec.getNumColumns(); ++i)
-  {
-    if (!spec.theCollations[i].empty())
-    {
-      theCollators[i] = CollationFactory::createCollator(spec.theCollations[i]);
-    }
-    else
-    {
-      theCollators[i] = NULL;
-    }
-  }
 }
 
 
@@ -182,11 +62,6 @@
 ********************************************************************************/
 IndexImpl::~IndexImpl()
 {
-  for (size_t i = 0; i < theCollators.size(); ++i)
-  {
-    if (theCollators[i])
-      delete theCollators[i]; 
-  }
 }
 
 
@@ -195,25 +70,317 @@
 ********************************************************************************/
 store::IndexCondition_t IndexImpl::createCondition(store::IndexCondition::Kind k)
 {
+  if (!isSorted() &&
+      (k == store::IndexCondition::BOX_VALUE || 
+       k == store::IndexCondition::BOX_GENERAL))
+  {
+    RAISE_ERROR_NO_LOC(zerr::ZSTR0007_INDEX_UNSUPPORTED_PROBE_CONDITION,
+    ERROR_PARAMS(IndexConditionImpl::getKindString(k), getName()->getStringValue()));
+  }
+
+  if (isGeneral())
+  {
+    return new GeneralIndexCondition(this, k);
+  }
+  else if (k == store::IndexCondition::POINT_VALUE)
+  {
+    return new IndexPointCondition(this, k);
+  }
+  else if (k == store::IndexCondition::BOX_VALUE)
+  {
+    return new IndexBoxValueCondition(this, k);
+  }
+  else
+  {
+    RAISE_ERROR_NO_LOC(zerr::ZSTR0007_INDEX_UNSUPPORTED_PROBE_CONDITION,
+    ERROR_PARAMS(IndexConditionImpl::getKindString(k), getName()->getStringValue()));
+
+    ZORBA_ASSERT(false);
+  }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  IndexConditionImpl                                                         //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/*******************************************************************************
+  TODO: proper initialization order is not guaranteed => use factory instead
+********************************************************************************/
+store::Item_t IndexConditionImpl::theNegInf(new DecimalItem);
+store::Item_t IndexConditionImpl::thePosInf(new DecimalItem);
+
+
+/*******************************************************************************
+  Static method
+********************************************************************************/
+std::string IndexConditionImpl::getKindString(store::IndexCondition::Kind k)
+{
   switch (k)
   {
-  case store::IndexCondition::POINT_VALUE:
-    return new IndexPointValueCondition(this);
-
-  case store::IndexCondition::POINT_GENERAL:
-    return new IndexPointGeneralCondition(this);
-
-  case store::IndexCondition::BOX_VALUE:
-    return new IndexBoxValueCondition(this);
-
-  case store::IndexCondition::BOX_GENERAL:
-    return new IndexBoxGeneralCondition(this);
-
-  default:
-    ZORBA_ASSERT(false);
-  }
-}
-
+  case POINT_VALUE:
+    return "POINT_VALUE";
+  case POINT_GENERAL:
+    return "POINT_GENERAL";
+  case BOX_VALUE:
+    return "BOX_VALUE";
+  case BOX_GENERAL:
+    return "BOX_GENERAL";
+  }
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+IndexConditionImpl::IndexConditionImpl(
+    IndexImpl* idx,
+    store::IndexCondition::Kind kind)
+  :
+  theIndex(idx),
+  theKind(kind)
+{
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void IndexConditionImpl::pushItem(store::Item_t& item)
+{
+  ZORBA_ASSERT(false);
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void IndexConditionImpl::pushRange(
+    store::Item_t& lower,
+    store::Item_t& upper,
+    bool haveLower,
+    bool haveUpper,
+    bool lowerIncl,
+    bool upperIncl)
+{
+  ZORBA_ASSERT(false);
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void IndexConditionImpl::pushBound(
+    store::Item_t& bound,
+    bool isLower,
+    bool boundIncl)
+{
+  ZORBA_ASSERT(false);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  GeneralIndexCondition                                                      //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/*******************************************************************************
+
+********************************************************************************/
+GeneralIndexCondition::GeneralIndexCondition(
+    IndexImpl* idx,
+    store::IndexCondition::Kind kind)
+  :
+  IndexConditionImpl(idx, kind),
+  theIsSet(false)
+{
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+std::string GeneralIndexCondition::toString() const
+{
+  std::ostringstream str;
+  str << *this;
+  return str.str();
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+std::ostream& operator<<(std::ostream& os, const GeneralIndexCondition& cond)
+{
+  os << "{ " << cond.getKindString() << " : ";
+
+  if (!cond.theIsSet)
+  {
+    os << "not set" << std::endl;
+    return os;
+  }
+
+  if (cond.theKind == store::IndexCondition::BOX_VALUE || 
+      cond.theKind == store::IndexCondition::BOX_GENERAL)
+  {
+    if (!cond.theRangeFlags.theHaveLowerBound)
+    {
+      os << "[-INF";
+    }
+    else 
+    {
+      if (cond.theRangeFlags.theLowerBoundIncl)
+        os << "[" << cond.theLowerBound->getStringValue();
+      else
+        os << "(" << cond.theLowerBound->getStringValue();
+    }
+    
+    os << ", ";
+  
+  
+    if (!cond.theRangeFlags.theHaveUpperBound)
+    {
+      os << "+INF] ";
+    }
+    else 
+    {
+      if (cond.theRangeFlags.theUpperBoundIncl)
+        os << cond.theUpperBound->getStringValue() << "] ";
+      else
+        os << cond.theUpperBound->getStringValue() << ") ";
+    }
+  }
+  else
+  {
+    os << "[" << cond.theKey->getStringValue() << "]";
+  }
+
+  os << std::endl;
+  return os;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void GeneralIndexCondition::clear()
+{
+  theIsSet = false;
+  theKey = NULL;
+  theLowerBound = NULL;
+  theUpperBound = NULL;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void GeneralIndexCondition::pushItem(store::Item_t& item)
+{
+  assert(theKind == POINT_VALUE || theKind == POINT_GENERAL);
+  assert(!theIsSet);
+  assert(item && item->isAtomic());
+
+  theKey.transfer(item);
+
+  store::Item* baseItem = theKey->getBaseItem();
+  if (baseItem != NULL)
+    theKey = baseItem;
+
+  theIsSet = true;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void GeneralIndexCondition::pushRange(
+    store::Item_t& lower,
+    store::Item_t& upper,
+    bool haveLower,
+    bool haveUpper,
+    bool lowerIncl,
+    bool upperIncl)
+{
+  assert(theKind == BOX_VALUE);
+  assert(!theIsSet);
+  assert(!haveLower || (lower && lower->isAtomic()));
+  assert(!haveUpper || (upper && upper->isAtomic()));
+
+  theRangeFlags.theHaveLowerBound = haveLower;
+  theRangeFlags.theHaveUpperBound = haveUpper;
+  theRangeFlags.theLowerBoundIncl = lowerIncl;
+  theRangeFlags.theUpperBoundIncl = upperIncl;
+
+  if (haveLower)
+  {
+    theLowerBound.transfer(lower);
+
+    store::Item* baseItem = theLowerBound->getBaseItem();
+    if (baseItem != NULL)
+      theLowerBound = baseItem;
+  }
+
+  if (haveUpper)
+  {
+    theUpperBound.transfer(upper);
+
+    store::Item* baseItem = theUpperBound->getBaseItem();
+    if (baseItem != NULL)
+      theUpperBound = baseItem;
+  }
+
+  theIsSet = true;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void GeneralIndexCondition::pushBound(
+    store::Item_t& bound,
+    bool isLower,
+    bool boundIncl)
+{
+  assert(theKind == BOX_GENERAL);
+  assert(!theIsSet);
+
+  assert(bound != NULL);
+
+  if (isLower)
+  {
+    theRangeFlags.theHaveLowerBound = true;
+    theRangeFlags.theHaveUpperBound = false;
+
+    theLowerBound.transfer(bound);
+
+    store::Item* baseItem = theLowerBound->getBaseItem();
+    if (baseItem != NULL)
+      theLowerBound = baseItem;
+  }
+  else
+  {
+    theRangeFlags.theHaveLowerBound = false;
+    theRangeFlags.theHaveUpperBound = true;
+
+    theUpperBound.transfer(bound);
+
+    store::Item* baseItem = theUpperBound->getBaseItem();
+    if (baseItem != NULL)
+      theUpperBound = baseItem;
+  }
+
+  theRangeFlags.theLowerBoundIncl = boundIncl;
+  theRangeFlags.theUpperBoundIncl = boundIncl;
+
+  theIsSet = true;
+}
 
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -244,33 +411,6 @@
 /*******************************************************************************
 
 ********************************************************************************/
-void IndexPointCondition::pushRange(
-    store::Item_t& lower,
-    store::Item_t& upper,
-    bool haveLower,
-    bool haveUpper,
-    bool lowerIncl,
-    bool upperIncl)
-{
-  ZORBA_ASSERT(false);
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void IndexPointCondition::pushBound(
-    store::Item_t& bound,
-    bool isLower,
-    bool boundIncl)
-{
-  ZORBA_ASSERT(false);
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
 bool IndexPointCondition::test(const store::IndexKey& key) const
 {
   ulong numCols = theKey.size();
@@ -312,51 +452,6 @@
 
 /////////////////////////////////////////////////////////////////////////////////
 //                                                                             //
-//  IndexBoxCondition                                                          //
-//                                                                             //
-/////////////////////////////////////////////////////////////////////////////////
-
-
-// TODO: proper initialization order is not guaranteed => use factory instead
-store::Item_t IndexBoxCondition::theNegInf(new DecimalItem);
-store::Item_t IndexBoxCondition::thePosInf(new DecimalItem);
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void IndexBoxCondition::pushItem(store::Item_t& item)
-{
-  ZORBA_ASSERT(false);
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void IndexBoxCondition::pushRange(
-    store::Item_t& lower,
-    store::Item_t& upper,
-    bool haveLower,
-    bool haveUpper,
-    bool lowerIncl,
-    bool upperIncl)
-{
-  ZORBA_ASSERT(false);
-}
-
-
-void IndexBoxCondition::pushBound(
-    store::Item_t& bound, 
-    bool isLower,
-    bool boundIncl)
-{
-  ZORBA_ASSERT(false);
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////
-//                                                                             //
 //  IndexBoxValueCondition                                                     //
 //                                                                             //
 /////////////////////////////////////////////////////////////////////////////////
@@ -490,91 +585,6 @@
 }
 
 
-
-/////////////////////////////////////////////////////////////////////////////////
-//                                                                             //
-//  IndexBoxGeneralCondition                                                   //
-//                                                                             //
-/////////////////////////////////////////////////////////////////////////////////
-
-
-/*******************************************************************************
-
-********************************************************************************/
-IndexBoxGeneralCondition::IndexBoxGeneralCondition(IndexImpl* idx) 
-  :
-  IndexBoxCondition(idx)
-{
-  theRangeFlags.theHaveLowerBound = false;
-  theRangeFlags.theHaveUpperBound = false;
-  theRangeFlags.theLowerBoundIncl = true;
-  theRangeFlags.theUpperBoundIncl = true;
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void IndexBoxGeneralCondition::clear()
-{
-  theBound.clear();
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-void IndexBoxGeneralCondition::pushBound(
-    store::Item_t& bound,
-    bool isLower, 
-    bool boundIncl)
-{
-  theRangeFlags.theHaveLowerBound = isLower;
-  theRangeFlags.theHaveUpperBound = !isLower;
-  theRangeFlags.theLowerBoundIncl = boundIncl;
-  theRangeFlags.theUpperBoundIncl = boundIncl;
-
-  assert(bound != NULL);
-
-  theBound.transfer_back(bound);
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-bool IndexBoxGeneralCondition::test(const store::IndexKey& key) const
-{
-  ZORBA_ASSERT(false);
-  return true;
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-std::ostream& operator<<(std::ostream& os, const IndexBoxGeneralCondition& cond)
-{
-  os << "{ ";
-
-  os << "}";
-
-  return os;
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
-std::string IndexBoxGeneralCondition::toString() const
-{
-  std::ostringstream str;
-  str << *this;
-  return str.str();
-}
-
-
-
 }
 }
 

=== modified file 'src/store/naive/simple_index.h'
--- src/store/naive/simple_index.h	2011-10-07 21:23:03 +0000
+++ src/store/naive/simple_index.h	2011-10-13 19:58:25 +0000
@@ -20,6 +20,8 @@
 #include "store/api/index.h"
 #include "store/api/iterator.h"
 
+#include "store/naive/shared_types.h"
+
 #include "zorbautils/hashmap.h"
 
 namespace zorba 
@@ -35,51 +37,11 @@
 /******************************************************************************
 
 ********************************************************************************/
-class IndexCompareFunction
-{
-  friend class HashIndex;
-
-private:
-  ulong                              theNumColumns;
-  long                               theTimezone;
-  const std::vector<XQPCollator*>&   theCollators;
-
-public:
-  IndexCompareFunction(
-       ulong numCols,
-       long timezone,
-       const std::vector<XQPCollator*>& collators)
-    :
-    theNumColumns(numCols),
-    theTimezone(timezone),
-    theCollators(collators)
-  {
-  }
-
-  uint32_t hash(const store::IndexKey* key) const;
-
-  bool equal(const store::IndexKey* key1, const store::IndexKey* key2) const;
-
-  long compare(const store::IndexKey* key1, const store::IndexKey* key2) const;
-
-  bool operator()(const store::IndexKey* key1, const store::IndexKey* key2) const
-  {
-    return compare(key1, key2) < 0;
-  }
-};
-
-
-/******************************************************************************
-
-********************************************************************************/
 class IndexImpl : public store::Index
 {
 protected:  
   store::Item_t                   theQname;
   store::IndexSpecification       theSpec;
-  std::vector<XQPCollator*>       theCollators;
-
-  std::vector<store::Item_t>      theSources;
 
 public:
   IndexImpl(const store::Item_t& qname, const store::IndexSpecification& spec);
@@ -101,20 +63,18 @@
 
   long getTimezone() const { return theSpec.theTimezone; }
 
-  const XQPCollator* getCollator(ulong i) const { return theCollators[i]; }
-
-  store::IndexCondition_t createCondition(store::IndexCondition::Kind k);
+  const std::vector<std::string>& getCollations() const { return theSpec.theCollations; }
 
   virtual ulong size() const = 0;
 
   virtual KeyIterator_t keys() const = 0;
 
+  store::IndexCondition_t createCondition(store::IndexCondition::Kind k);
+
   //
   // Simplestore methods
   //
 
-  const std::vector<XQPCollator*>& getCollators() const { return theCollators; }
- 
   bool isUnique() const { return theSpec.theIsUnique; }
 
   bool isSorted() const { return theSpec.theIsSorted; }
@@ -124,136 +84,186 @@
   bool isThreadSafe() const { return theSpec.theIsThreadSafe; }
 
   bool isGeneral() const { return theSpec.theIsGeneral; }
-
-  virtual bool insert(
-        store::IndexKey*& key,
-        store::Item_t& item,
-        bool multikey = false) = 0;
-
-  virtual bool remove(
-        const store::IndexKey* key,
-        store::Item_t& item,
-        bool all = false) = 0;
 };
 
 
 /*******************************************************************************
 
 ********************************************************************************/
-class IndexPointCondition : public store::IndexCondition
+class IndexConditionImpl : public store::IndexCondition
 {
   friend class ProbeValueTreeIndexIterator;
   friend class ProbeValueHashIndexIterator;
+  friend class ProbeGeneralIndexIterator;
   friend class ProbeGeneralHashIndexIterator;
   friend class ProbeGeneralTreeIndexIterator;
 
 protected:
-  rchandle<IndexImpl>   theIndex;
-  store::IndexKey       theKey;
-  ulong                 theNumColumns;
-
-public:
-  IndexPointCondition(IndexImpl* idx) 
-    :
-    theIndex(idx),
-    theNumColumns(idx->getNumColumns())
-  {
-  }
-
-  const store::IndexKey& getKey() const { return theKey; }
-
-  void clear();
-
-  void pushItem(store::Item_t& item);
-
-  void pushRange(
-        store::Item_t& lower,
-        store::Item_t& upper,
-        bool haveLower,
-        bool haveUpper,
-        bool lowerIncl,
-        bool upperIncl);
-
-  void pushBound(store::Item_t& bound, bool isLower, bool boundIncl);
-
-  bool test(const store::IndexKey& key) const;
-
-  std::string toString() const;
-};
-
-
-std::ostream& operator<<(std::ostream& os, const IndexPointCondition& cond);
-
-
-/*******************************************************************************
-
-********************************************************************************/
-class IndexPointValueCondition : public IndexPointCondition
-{
-public:
-  IndexPointValueCondition(IndexImpl* idx) : IndexPointCondition(idx) { }
-
-  store::IndexCondition::Kind getKind() const { return POINT_VALUE; }
-
-  std::string getKindString() const { return "POINT_VALUE"; }
-};
-
-
-/*******************************************************************************
-
-********************************************************************************/
-class IndexPointGeneralCondition : public IndexPointCondition
-{
-public:
-  IndexPointGeneralCondition(IndexImpl* idx) : IndexPointCondition(idx) { }
-
-  store::IndexCondition::Kind getKind() const { return POINT_GENERAL; }
-
-  std::string getKindString() const { return "POINT_GENERAL"; }
-};
-
-
-/*******************************************************************************
-
-********************************************************************************/
-class IndexBoxCondition : public store::IndexCondition
-{
-  friend class ValueTreeIndex;
-  friend class ProbeValueTreeIndexIterator;
-
-public:
-  static store::Item_t  theNegInf;
-  static store::Item_t  thePosInf;
-
-protected:
   struct RangeFlags
   {
     bool  theHaveLowerBound;
     bool  theHaveUpperBound;
     bool  theLowerBoundIncl;
     bool  theUpperBoundIncl;
+
+    RangeFlags()
+      :
+      theHaveLowerBound(false),
+      theHaveUpperBound(false),
+      theLowerBoundIncl(true),
+      theUpperBoundIncl(true)
+    {
+    }
   };
 
-  rchandle<IndexImpl>      theIndex;
-
-public:
-  IndexBoxCondition(IndexImpl* idx) : theIndex(idx) { }
-
-  void pushItem(store::Item_t& item);
+public:
+  static store::Item_t         theNegInf;
+  static store::Item_t         thePosInf;
+
+protected:
+  rchandle<IndexImpl>          theIndex;
+
+  store::IndexCondition::Kind  theKind;
+
+public:
+  static std::string getKindString(store::IndexCondition::Kind k);
+
+public:
+  IndexConditionImpl(IndexImpl* idx, store::IndexCondition::Kind kind);
+
+  store::IndexCondition::Kind getKind() const { return theKind; }
+
+  std::string getKindString() const { return getKindString(theKind); }
+
+  virtual void pushItem(store::Item_t& item);
 
   virtual void pushRange(
-        store::Item_t& lower,
-        store::Item_t& upper,
-        bool haveLower,
-        bool haveUpper,
-        bool lowerIncl,
-        bool upperIncl);
-
+      store::Item_t& lower,
+      store::Item_t& upper,
+      bool haveLower,
+      bool haveUpper,
+      bool lowerIncl,
+      bool upperIncl);
+  
   virtual void pushBound(store::Item_t& bound, bool isLower, bool boundIncl);
 };
 
 
 /*******************************************************************************
+  Repesents a search condition on a general index.
+
+  theKind:
+  --------
+  The kind of the condition (one of POINT_VALUE, POINT_GENERAL, BOX_VALUE, or
+  BOX_GENERAL).
+
+  theIsSet:
+  ---------
+  Set to true the 1st time one of the pushXXX methods is called and reset to
+  false by the clear() method. Used to check that the user is not trying to
+  push more than once.
+
+  theKey:
+  ------------
+  The search key for the POINT conditions. It is non-NULL and points to an
+  atomic item.
+
+  theRangeFlags:
+  --------------
+  Use only for the BOX conditions. Specifies the kind of operator and whether
+  the lower/upper bound is INFINITY or not.
+
+  theLowerBound:
+  --------------
+  The search key that serves as the lower bound for the BOX conditions. If,
+  according to theRangeFlags, the bound is not -INFINITY, theLowerBound is 
+  not NULL and points to an atomicitem; otherwise, the value of theLowerBound
+  is irrelevant (is not used).
+
+  theUpperBound:
+  --------------
+  The search key that serves as the upper bound for the BOX conditions. If, 
+  according to theRangeFlags, the bound is not +INFINITY, theUpperBound is 
+  not NULL and points to an atomic item; otherwise, the value of theUpperBound
+  is irrelevant (is not used).
+********************************************************************************/
+class GeneralIndexCondition : public IndexConditionImpl
+{
+  friend class ProbeGeneralIndexIterator;
+  friend class ProbeGeneralHashIndexIterator;
+  friend class ProbeGeneralTreeIndexIterator;
+
+  friend std::ostream& operator<<(std::ostream& os, const GeneralIndexCondition& c);
+
+protected:
+  bool                         theIsSet;
+
+  AtomicItem_t                 theKey;
+
+  RangeFlags                   theRangeFlags;
+  AtomicItem_t                 theLowerBound;
+  AtomicItem_t                 theUpperBound;
+
+public:
+  GeneralIndexCondition(IndexImpl* idx, store::IndexCondition::Kind);
+
+  std::string toString() const;
+
+  void clear();
+
+  void pushItem(store::Item_t& item);
+
+  void pushRange(
+      store::Item_t& lower,
+      store::Item_t& upper,
+      bool haveLower,
+      bool haveUpper,
+      bool lowerIncl,
+      bool upperIncl);
+
+  void pushBound(store::Item_t& bound, bool isLower, bool boundIncl);
+};
+
+
+std::ostream& operator<<(std::ostream& os, const GeneralIndexCondition& cond);
+
+
+/*******************************************************************************
+
+********************************************************************************/
+class IndexPointCondition : public IndexConditionImpl
+{
+  friend class ProbeValueTreeIndexIterator;
+  friend class ProbeValueHashIndexIterator;
+  friend class ProbeGeneralHashIndexIterator;
+  friend class ProbeGeneralTreeIndexIterator;
+
+protected:
+  store::IndexKey theKey;
+
+public:
+  IndexPointCondition(IndexImpl* idx, store::IndexCondition::Kind kind) 
+    :
+    IndexConditionImpl(idx, kind)
+  {
+  }
+
+  const store::IndexKey& getKey() const { return theKey; }
+
+  void clear();
+
+  void pushItem(store::Item_t& item);
+
+  bool test(const store::IndexKey& key) const;
+
+  std::string toString() const;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const IndexPointCondition& cond);
+
+
+/*******************************************************************************
   It represents a condition that is satisfied by the index keys inside a
   user-specified "box".
 
@@ -266,7 +276,7 @@
 
   The lower bound may be -INFINITY and the upper bound may be +INFINTY.
 ********************************************************************************/
-class IndexBoxValueCondition : public IndexBoxCondition
+class IndexBoxValueCondition : public IndexConditionImpl
 {
   friend class ValueTreeIndex;
   friend class ProbeValueTreeIndexIterator;
@@ -280,11 +290,11 @@
   store::IndexKey          theUpperBounds;
 
 public:
-  IndexBoxValueCondition(IndexImpl* idx) : IndexBoxCondition(idx) { }
-
-  store::IndexCondition::Kind getKind() const { return BOX_VALUE; }
-
-  std::string getKindString() const { return "BOX_VALUE"; }
+  IndexBoxValueCondition(IndexImpl* idx, store::IndexCondition::Kind kind)
+    :
+    IndexConditionImpl(idx, kind)
+  {
+  }
 
   ulong numRanges() const { return theLowerBounds.size(); }
 
@@ -307,57 +317,6 @@
 std::ostream& operator<<(std::ostream& os, const IndexBoxValueCondition& cond);
 
 
-/*******************************************************************************
-  It represents the following condition:
-
-  bound op? K, where 
-
-  (a) op? is one of <, <=, >, or >=, 
-  (b) K is a key value, and 
-  (c) bound is either an atomic item or -INFINITY or +INFINITY.
-
-  theRangeFlags:
-  --------------
-  Specify the kind of operator and whether the bound is INFINITY or not
-
-  theBound:
-  ---------
-  The search key that serves as either a lower bound or an upper bound. If,
-  according to theRangeFlags, the bound is not INFINITY, theBound contains 
-  exactly one non-NULL atomic item; otherwise, it is empty.
-********************************************************************************/
-class IndexBoxGeneralCondition : public IndexBoxCondition
-{
-  friend class GeneralTreeIndex;
-  friend class ProbeGeneralTreeIndexIterator;
-
-  friend std::ostream& operator<<(std::ostream& os, const IndexBoxGeneralCondition& c);
-
-protected:
-  RangeFlags      theRangeFlags;
-  store::IndexKey theBound;
-
-public:
-  IndexBoxGeneralCondition(IndexImpl* idx);
-
-  store::IndexCondition::Kind getKind() const { return BOX_GENERAL; }
-
-  std::string getKindString() const { return "BOX_GENERAL"; }
-
-  void clear();
-
-  void pushBound(store::Item_t& bound, bool isLower, bool boundIncl);
-
-  bool test(const store::IndexKey& key) const;
-
-  std::string toString() const;
-};
- 
-
-std::ostream& operator<<(std::ostream& os, const IndexBoxGeneralCondition& cond);
-
-
-
 }
 }
 

=== modified file 'src/store/naive/simple_index_general.cpp'
--- src/store/naive/simple_index_general.cpp	2011-10-04 05:28:07 +0000
+++ src/store/naive/simple_index_general.cpp	2011-10-13 19:58:25 +0000
@@ -31,24 +31,156 @@
 namespace simplestore 
 {
 
-const int64_t  GeneralTreeIndex::theMaxLong       =  99999999999LL;
-const int64_t  GeneralTreeIndex::theMinLong       = -99999999999LL;
-const double   GeneralTreeIndex::theDoubleMaxLong =  99999999999.0;
-const double   GeneralTreeIndex::theDoubleMinLong = -99999999999.0;
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  GeneralIndexCompareFunction                                                //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/******************************************************************************
+
+********************************************************************************/
+GeneralIndexCompareFunction::GeneralIndexCompareFunction(
+    long timezone,
+    const std::string& collation)
+  :
+  theTimezone(timezone)
+{
+  if (!collation.empty())
+  {
+    theCollator = CollationFactory::createCollator(collation);
+  }
+  else
+  {
+    theCollator = NULL;
+  } 
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+GeneralIndexCompareFunction::~GeneralIndexCompareFunction()
+{
+  if (theCollator)
+    delete theCollator; 
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+uint32_t GeneralIndexCompareFunction::hash(const store::Item_t& key) const
+{
+  uint32_t hval = FNV_32_INIT;
+
+  if (key == NULL)
+    return hval;
+
+  return hashfun::h32<uint32_t>(key->hash(theTimezone, theCollator), hval);
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+bool GeneralIndexCompareFunction::equal(
+    const store::Item_t& key1,
+    const store::Item_t& key2) const
+{
+  if (key1 == NULL && key2 == NULL)
+    return true;
+
+  if (key1 == NULL || key2 == NULL)
+    return false;
+
+  if (! key1->equals(key2.getp(), theTimezone, theCollator))
+    return false;
+  
+  return true;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+long GeneralIndexCompareFunction::compare(
+    const store::Item_t& key1,
+    const store::Item_t& key2) const
+{
+  long result;
+
+  if (key1 == NULL)
+  {
+    if (key2 != NULL)
+      return -1;
+  }
+  else if (key2 == NULL)
+  {
+    if (key1 != NULL)
+      return +1;
+  }
+  else if (key1 == IndexConditionImpl::theNegInf)
+  {
+    return -1;
+  }
+  else if (key1 == IndexConditionImpl::thePosInf)
+  {
+    return +1;
+  }
+  else if (key2 == IndexConditionImpl::theNegInf)
+  {
+    return +1;
+  }
+  else if (key2 == IndexConditionImpl::thePosInf)
+  {
+    return -1;
+  }
+  else if ((result = key1->compare(key2, theTimezone, theCollator)))
+  {
+    return result;
+  }
+
+  return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  GeneralIndexValue                                                          //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
 
 /******************************************************************************
 
 *******************************************************************************/
-void GeneralIndexValue::addNode(store::Item_t& node, bool multikey, bool untyped)
+void GeneralIndexValue::addNode(store::Item_t& node, bool untyped)
 {
-  size_t numNodes = theNodes.size();
+  csize numNodes = theNodes.size();
   theNodes.resize(numNodes + 1);
   theNodes[numNodes].theNode.transfer(node);
-  //theNodes[numNodes].theMultiKey = multikey;
   theNodes[numNodes].theUntyped = untyped;
 }
 
 
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  GeneralIndex                                                               //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/******************************************************************************
+
+*******************************************************************************/
+const int64_t  GeneralIndex::theMaxLong       =  99999999999LL;
+const int64_t  GeneralIndex::theMinLong       = -99999999999LL;
+const double   GeneralIndex::theDoubleMaxLong =  99999999999.0;
+const double   GeneralIndex::theDoubleMinLong = -99999999999.0;
+
+
 /******************************************************************************
 
 *******************************************************************************/
@@ -57,147 +189,63 @@
     const store::IndexSpecification& spec)
   :
   IndexImpl(qname, spec),
-  theCompFunction(getNumColumns(), spec.theTimezone, theCollators),
+  theKeyTypeCode(XS_LAST),
+  theCompFunction(spec.theTimezone, spec.theCollations[0]),
   theUntypedFlag(false),
   theMultiKeyFlag(false)
 {
-}
-
-
-/******************************************************************************
-  Macro used during the population of both hash and tree general indexes.
-*******************************************************************************/
-#define ADD_IN_MAP(MAP_ID, untyped)                                            \
-if (castItem !=  NULL)                                                         \
-{                                                                              \
-  if (key == NULL) key = new store::IndexKey(1);                               \
-  (*key)[0].transfer(castItem);                                                \
-  found = found || insertInMap(key, node, theMaps[MAP_ID], multikey, untyped); \
-  node = node2;                                                                \
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////
-//                                                                             //
-//  Hash Map General Index                                                     //
-//                                                                             //
-/////////////////////////////////////////////////////////////////////////////////
-
-
-/******************************************************************************
-
-*******************************************************************************/
-GeneralHashIndex::KeyIterator::~KeyIterator()
-{
-}
-
-
-void GeneralHashIndex::KeyIterator::open()
-{
-  assert(false);
-}
-
-
-bool GeneralHashIndex::KeyIterator::next(store::IndexKey&)
-{
-  assert(false);
-  return false;
-}
-
-
-void GeneralHashIndex::KeyIterator::close()
-{
-  assert(false);
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
-GeneralHashIndex::GeneralHashIndex(
-    const store::Item_t& qname,
-    const store::IndexSpecification& spec)
-  :
-  GeneralIndex(qname, spec),
-  theSingleMap(NULL)
-{
-  assert(getNumColumns() == 1);
-
-  memset(reinterpret_cast<void*>(theMaps), 0, XS_LAST * sizeof(IndexMap*));
-
   store::Item* typeName = spec.theKeyTypes[0].getp();
 
   if (typeName != NULL &&
       typeName != GET_STORE().theSchemaTypeNames[XS_UNTYPED_ATOMIC] &&
       typeName != GET_STORE().theSchemaTypeNames[XS_ANY_ATOMIC])
   {
-    theSingleMap = new IndexMap(theCompFunction, 1024, spec.theIsThreadSafe);
-
-    theMaps[GET_STORE().theSchemaTypeCodes[spec.theKeyTypes[0].getp()]] = theSingleMap;
-  }
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
-GeneralHashIndex::~GeneralHashIndex()
-{
-  for (ulong i = 0; i < XS_LAST; ++i)
-  {
-    if (theMaps[i] == NULL)
-      continue;
-
-    IndexMap::iterator ite = theMaps[i]->begin();
-    IndexMap::iterator end = theMaps[i]->end();
- 
-    for (; ite != end; ++ite)
-    {
-      //std::cout << "Index Entry Delete [" << (*ite).first << "," 
-      //          << (*ite).second << "]" << std::endl;
-      
-      delete (*ite).first;
-      delete (*ite).second;
-    }
-
-    delete theMaps[i];
-  }
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
-ulong GeneralHashIndex::size() const
-{
-  assert(false);
-  return 0;
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
-store::Index::KeyIterator_t GeneralHashIndex::keys() const
-{
-  assert(false);
-  return 0;
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
-bool GeneralHashIndex::insert(
-    store::IndexKey*& key,
-    store::Item_t& node,
-    bool multikey)
-{
+    theKeyTypeCode = GET_STORE().theSchemaTypeCodes[spec.theKeyTypes[0].getp()];
+  }
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+GeneralIndex::~GeneralIndex()
+{
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+const XQPCollator* GeneralIndex::getCollator(ulong i) const
+{
+  ZORBA_ASSERT(i == 0);
+  return theCompFunction.getCollator();
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+ulong GeneralIndex::size() const
+{
+  assert(false);
+  return 0;
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+bool GeneralIndex::insert(store::Item_t& key, store::Item_t& node)
+{
+  bool lossy = false;
   bool found = false;
   store::Item_t castItem;
   store::Item_t node2;
 
-  AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
+  bool sorted = isSorted();
+
+  AtomicItem* keyItem = static_cast<AtomicItem*>(key.getp());
 
   if (keyItem == NULL)
   {
@@ -210,41 +258,50 @@
   if (keyItem->getBaseItem() != NULL)
   {
     keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
-    (*key)[0] = keyItem;
+    key = keyItem;
   }
 
   SchemaTypeCode keyType = keyItem->getTypeCode();
 
   if (isTyped())
   {
-    return insertInMap(key, node, theSingleMap, multikey, false);
+    return insertInMap(key, node, theKeyTypeCode, false);
   }
 
   switch (keyType)
   {
-  case XS_ANY_URI:
+  case XS_BASE64BINARY:
+  case XS_HEXBINARY:
+
   case XS_QNAME:
   case XS_NOTATION:
-  case XS_DATETIME:
-  case XS_DATE:
-  case XS_TIME:
+
   case XS_GYEAR_MONTH:
   case XS_GYEAR:
   case XS_GMONTH_DAY:
   case XS_GDAY:
   case XS_GMONTH:
-  case XS_BASE64BINARY:
-  case XS_HEXBINARY:
+  {
+    assert(!sorted);
+    // falth through
+  }
+
+  case XS_ANY_URI:
+
   case XS_BOOLEAN:
+
+  case XS_DATETIME:
+  case XS_DATE:
+  case XS_TIME:
   {
-    return insertInMap(key, node, theMaps[keyType], multikey, false);
+    return insertInMap(key, node, keyType, false);
   }
 
   case XS_DURATION:
   case XS_YM_DURATION:
   case XS_DT_DURATION:
   {
-    return insertInMap(key, node, theMaps[XS_DURATION], multikey, false);
+    return insertInMap(key, node, XS_DURATION, false);
   }
 
   case XS_STRING:
@@ -258,13 +315,13 @@
   case XS_IDREF:
   case XS_ENTITY:
   {
-    return insertInMap(key, node, theMaps[XS_STRING], multikey, false);
+    return insertInMap(key, node, XS_STRING, false);
   }
 
   case XS_DOUBLE:
   case XS_FLOAT:
   {
-    return insertInMap(key, node, theMaps[XS_DOUBLE], multikey, false);
+    return insertInMap(key, node, XS_DOUBLE, false);
   }
 
   case XS_DECIMAL:
@@ -275,32 +332,67 @@
   case XS_POSITIVE_INTEGER:
   case XS_UNSIGNED_LONG:
   {
+    // try lossless cast to xs:long
     keyItem->castToLong(castItem);
     if (castItem != NULL)
     {
       keyItem = static_cast<AtomicItem*>(castItem.getp());
-      (*key)[0].transfer(castItem);
+      key.transfer(castItem);
       goto longmap;
     }
 
-    bool lossy;
+    // Coerce to xs:double 
     keyItem->coerceToDouble(castItem, true, lossy);
 
+    found = insertInMap(key, node, XS_DOUBLE, false);
+
     if (lossy)
     {
       node2 = node;
-      found = insertInMap(key, node2, theMaps[XS_DECIMAL], multikey, false);
+      found = found || insertInMap(castItem, node2, XS_DECIMAL, false);
     }
 
-    if (key == NULL) key = new store::IndexKey(1);
-    (*key)[0].transfer(castItem);
-
-    found = found || insertInMap(key, node, theMaps[XS_DOUBLE], multikey, false);
-
     return found;
   }
 
   case XS_LONG:
+  {
+longmap:
+    xs_long longValue = static_cast<LongItem*>(keyItem)->getLongValue();
+
+    if (longValue > theMaxLong || longValue < theMinLong)
+    {
+      if (sorted)
+      {
+        lossy = true;
+        xs_double doubleValue(longValue);
+        GET_FACTORY().createDouble(castItem, doubleValue);
+      }
+      else
+      {
+        keyItem->coerceToDouble(castItem, false, lossy);
+      }
+
+      if (lossy)
+      {
+        node2 = node;
+        found = insertInMap(key, node2, XS_LONG, false);
+
+        found = found || insertInMap(castItem, node, XS_DOUBLE, false);
+      }
+      else
+      {
+        found = insertInMap(key, node, XS_LONG, false);
+      }
+    }
+    else
+    {
+      found = insertInMap(key, node, XS_LONG, false);
+    }
+
+    return found;
+  }
+
   case XS_INT:
   case XS_SHORT:
   case XS_BYTE:
@@ -308,68 +400,75 @@
   case XS_UNSIGNED_SHORT:
   case XS_UNSIGNED_BYTE:
   {
-longmap:
-    bool lossy;
-    keyItem->coerceToDouble(castItem, false, lossy);
-
-    if (lossy)
-    {
-      node2 = node;
-      found = insertInMap(key, node2, theMaps[XS_LONG], multikey, false);
-
-      if (key == NULL) key = new store::IndexKey(1);
-      (*key)[0].transfer(castItem);
-
-      found = found || insertInMap(key, node, theMaps[XS_DOUBLE], multikey, false);
-    }
-    else
-    {
-      found = insertInMap(key, node, theMaps[XS_LONG], multikey, false);
-    }
-
-    return found;
+    return insertInMap(key, node, XS_LONG, false);
   }
 
   case XS_UNTYPED_ATOMIC:
   {
-    bool found = false;
-
     store::ItemHandle<UntypedAtomicItem> untypedItem = 
-    static_cast<UntypedAtomicItem*>((*key)[0].getp());
-
-    node2 = node;
+    static_cast<UntypedAtomicItem*>(key.getp());
 
     // cast to xs:string
     untypedItem->castToString(castItem);
-    ADD_IN_MAP(XS_STRING, false);
-
-    // no reason to cast to xs:anyUri, because when we probe with xs:string or with
-    // xs:anyUri, or with xs:untypedAtomic, we unconditionally probe both the
-    // STRING and the ANY_URI tables.
+
+    node2 = node;
+    found = insertInMap(castItem, node2, XS_STRING, false);
+
+    // No reason to cast to xs:anyUri, because when we probe with xs:string or
+    // with xs:anyUri, or with xs:untypedAtomic, we unconditionally probe both
+    // the STRING and the ANY_URI tables.
  
     // try casting to xs:long
     if (untypedItem->castToLong(castItem))
     {
       store::ItemHandle<LongItem> longItem = static_cast<LongItem*>(castItem.getp());
 
-      ADD_IN_MAP(XS_LONG, true);
-
-      bool lossy;
-      longItem->coerceToDouble(castItem, false, lossy);
-      if (lossy)
+      xs_long longValue = longItem->getLongValue();
+
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_LONG, true);
+
+      if (longValue > theMaxLong || longValue < theMinLong)
       {
-        ADD_IN_MAP(XS_DOUBLE, true);
+        if (sorted)
+        {
+          lossy = true;
+          xs_double doubleValue(longValue);
+          GET_FACTORY().createDouble(castItem, doubleValue);
+        }
+        else
+        {
+          longItem->coerceToDouble(castItem, false, lossy);
+        }
+
+        if (lossy)
+        {
+          node2 = node;
+          found = found || insertInMap(castItem, node2, XS_DOUBLE, true);
+        }
       }
 
       // may also be gYear, hexBinary, base64Binary, or boolean
-      if (untypedItem->castToGYear(castItem))
-        ADD_IN_MAP(XS_GYEAR, true);
-
-      if (untypedItem->castToHexBinary(castItem))
-        ADD_IN_MAP(XS_HEXBINARY, true);
-
-      if (untypedItem->castToBase64Binary(castItem))
-        ADD_IN_MAP(XS_BASE64BINARY, true);
+      if (!sorted)
+      {
+        if (untypedItem->castToGYear(castItem))
+        {
+          node2 = node;
+          found = found || insertInMap(castItem, node2, XS_GYEAR, true);
+        }
+
+        if (untypedItem->castToHexBinary(castItem))
+        {
+          node2 = node;
+          found = found || insertInMap(castItem, node2, XS_HEXBINARY, true);
+        }
+
+        if (untypedItem->castToBase64Binary(castItem))
+        {
+          node2 = node;
+          found = found || insertInMap(castItem, node2, XS_BASE64BINARY, true);
+        }
+      }
     }
 
     // try casting to xs:decimal
@@ -378,87 +477,110 @@
       store::ItemHandle<DecimalItem> decimalItem = 
       static_cast<DecimalItem*>(castItem.getp());
 
-      ADD_IN_MAP(XS_DOUBLE, true);
-
-      bool lossy;
       decimalItem->coerceToDouble(castItem, true, lossy);
+
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_DOUBLE, true);
+
       if (lossy)
       {
-        ADD_IN_MAP(XS_DECIMAL, true);
+        castItem.transfer(decimalItem);
+        node2 = node;
+        found = found || insertInMap(castItem, node2, XS_DECIMAL, true);
       }
 
       // may also be hexBinary or base64Binary
-      if (untypedItem->castToHexBinary(castItem))
-        ADD_IN_MAP(XS_HEXBINARY, true);
+      if (sorted)
+      {
+        if (untypedItem->castToHexBinary(castItem))
+        {
+          node2 = node;
+          found = found || insertInMap(castItem, node2, XS_HEXBINARY, true);
+        }
 
-      if (untypedItem->castToBase64Binary(castItem))
-        ADD_IN_MAP(XS_BASE64BINARY, true);
+        if (untypedItem->castToBase64Binary(castItem))
+        {
+          node2 = node;
+          found = found || insertInMap(castItem, node2, XS_BASE64BINARY, true);
+        }
+      }
     }
 
     // try casting to xs:double
     else if (untypedItem->castToDouble(castItem))
     {
-      ADD_IN_MAP(XS_DOUBLE, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_DOUBLE, true);
     }
 
     // try casting to xs:datetime
     else if (untypedItem->castToDateTime(castItem))
     {
-      ADD_IN_MAP(XS_DATETIME, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_DATETIME, true);
     }
 
     // try casting to xs:date
     else if (untypedItem->castToDate(castItem))
     {
-      ADD_IN_MAP(XS_DATE, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_DATE, true);
     }
 
     // try casting to xs:time
     else if (untypedItem->castToTime(castItem))
     {
-      ADD_IN_MAP(XS_TIME, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_TIME, true);
     }
 
     // try casting to xs:gYearMonth
-    else if (untypedItem->castToGYearMonth(castItem))
+    if (!sorted && untypedItem->castToGYearMonth(castItem))
     {
-      ADD_IN_MAP(XS_GYEAR_MONTH, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_GYEAR_MONTH, true);
     }
 
     // try casting to xs:gMonthDay
-    else if (untypedItem->castToGMonthDay(castItem))
+    else if (!sorted && untypedItem->castToGMonthDay(castItem))
     {
-      ADD_IN_MAP(XS_GMONTH_DAY, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_GMONTH_DAY, true);
     }
 
     // try casting to xs:gDay
-    else if (untypedItem->castToGDay(castItem))
+    else if (!sorted && untypedItem->castToGDay(castItem))
     {
-      ADD_IN_MAP(XS_GDAY, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_GDAY, true);
     }
 
     // try casting to xs:gMonth
-    else if (untypedItem->castToGMonth(castItem))
+    else if (!sorted && untypedItem->castToGMonth(castItem))
     {
-      ADD_IN_MAP(XS_GMONTH, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_GMONTH, true);
     }
 
     // try casting to xs:duration
     else if (untypedItem->castToDuration(castItem))
     {
-      ADD_IN_MAP(XS_DURATION, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_DURATION, true);
     }
 
     // try casting to xs:hexBinary
-    else if (untypedItem->castToHexBinary(castItem))
+    else if (!sorted && untypedItem->castToHexBinary(castItem))
     {
-      ADD_IN_MAP(XS_HEXBINARY, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_HEXBINARY, true);
     }
 
     // try casting to xs:base64Binary
-    else if (untypedItem->castToBase64Binary(castItem))
+    else if (!sorted && untypedItem->castToBase64Binary(castItem))
     {
-      ADD_IN_MAP(XS_BASE64BINARY, true);
+      node2 = node;
+      found = found || insertInMap(castItem, node2, XS_BASE64BINARY, true);
     }
 
     return found;
@@ -466,7 +588,8 @@
 
   default:
   {
-    ZORBA_ASSERT(false);
+    RAISE_ERROR_NO_LOC(zerr::ZDTY0012_INDEX_KEY_TYPE_ERROR, 
+    ERROR_PARAMS(getName()->getStringValue()));
     return false;
   }
   }
@@ -476,11 +599,102 @@
 /******************************************************************************
 
 *******************************************************************************/
+bool GeneralIndex::insertInMap(
+    store::Item_t& key,
+    store::Item_t& node,
+    SchemaTypeCode targetMap,
+    bool untyped)
+{
+  if (untyped)
+    theUntypedFlag = true;
+
+  if (isSorted())
+  {
+    GeneralTreeIndex* idx = static_cast<GeneralTreeIndex*>(this);
+    return idx->insertInMap(key, node, idx->theMaps[targetMap], untyped);
+  }
+  else
+  {
+    GeneralHashIndex* idx = static_cast<GeneralHashIndex*>(this);
+    return idx->insertInMap(key, node, idx->theMaps[targetMap], untyped);
+  }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  Hash Map General Index                                                     //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/******************************************************************************
+
+*******************************************************************************/
+GeneralHashIndex::GeneralHashIndex(
+    const store::Item_t& qname,
+    const store::IndexSpecification& spec)
+  :
+  GeneralIndex(qname, spec),
+  theSingleMap(NULL)
+{
+  assert(getNumColumns() == 1);
+
+  memset(reinterpret_cast<void*>(theMaps), 0, XS_LAST * sizeof(IndexMap*));
+
+  if (isTyped())
+  {
+    theSingleMap = new IndexMap(theCompFunction, 1024, spec.theIsThreadSafe);
+
+    theMaps[theKeyTypeCode] = theSingleMap;
+  }
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+GeneralHashIndex::~GeneralHashIndex()
+{
+  for (ulong i = 0; i < XS_LAST; ++i)
+  {
+    if (theMaps[i] == NULL)
+      continue;
+
+    IndexMap::iterator ite = theMaps[i]->begin();
+    IndexMap::iterator end = theMaps[i]->end();
+ 
+    for (; ite != end; ++ite)
+    {
+      //std::cout << "Index Entry Delete [" << (*ite).first << "," 
+      //          << (*ite).second << "]" << std::endl;
+      
+      (*ite).first->removeReference();
+      delete (*ite).second;
+    }
+
+    delete theMaps[i];
+  }
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+store::Index::KeyIterator_t GeneralHashIndex::keys() const
+{
+  assert(false);
+  return 0;
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
 bool GeneralHashIndex::insertInMap(
-    store::IndexKey*& key,
+    store::Item_t& key,
     store::Item_t& node,
     IndexMap*& targetMap,
-    bool multikey,
     bool untyped)
 {
   GeneralIndexValue* valueSet = NULL;
@@ -488,36 +702,27 @@
   if (targetMap == NULL)
     targetMap = new IndexMap(theCompFunction, 1024, theSpec.theIsThreadSafe);
 
-  if (untyped)
-    theUntypedFlag = true;
-
-  if (multikey)
-    theMultiKeyFlag = true;
-
   if (targetMap->get(key, valueSet))
   {
     if (isUnique())
     {
-      throw ZORBA_EXCEPTION(
-        zerr::ZDDY0024_INDEX_UNIQUE_VIOLATION,
-        ERROR_PARAMS( theQname->getStringValue() )
-      );
+      RAISE_ERROR_NO_LOC(zerr::ZDDY0024_INDEX_UNIQUE_VIOLATION,
+      ERROR_PARAMS(theQname->getStringValue()));
     }
     
-    valueSet->addNode(node, multikey, untyped);
+    valueSet->addNode(node, untyped);
 
     return true;
   }
 
   valueSet = new GeneralIndexValue();
-  valueSet->addNode(node, multikey, untyped);
+  valueSet->addNode(node, untyped);
   
   //std::cout << "Index Entry Insert [" << key << "," 
   //          << valueSet << "]" << std::endl;
   
-  const store::IndexKey* key2 = key;
-  targetMap->insert(key2, valueSet);
-  key = NULL; // ownership of the key obj passes to the index.
+  targetMap->insert(key.getp(), valueSet);
+  key.release(); // ownership of the key passes to the index.
 
   return false;
 }
@@ -527,7 +732,7 @@
 
 *******************************************************************************/
 bool GeneralHashIndex::remove(
-    const store::IndexKey* key,
+    const store::Item_t& key,
     store::Item_t& item,
     bool all)
 {
@@ -538,533 +743,47 @@
 
 /////////////////////////////////////////////////////////////////////////////////
 //                                                                             //
-//  ProbeHashGeneralIndexIterator                                              //
-//                                                                             //
-//  Iterator to probe a general, hash-based index. The probe itself may be a   //
-//  value probe or a general probe.                                            //
+//  GeneralHashIndex::KeyIterator                                              //
 //                                                                             //
 /////////////////////////////////////////////////////////////////////////////////
 
 
 /******************************************************************************
-  Create an 
-********************************************************************************/
-ProbeGeneralHashIndexIterator::ProbeGeneralHashIndexIterator(
-    const store::Index_t& index) 
-  :
-  theIsUntypedProbe(false),
-  theResultSets(1)
-{
-  theIndex = static_cast<GeneralHashIndex*>(index.getp());
-    
-  theResultSets[0] = NULL;
-}
-
-
-#define PROBE_MAP(MAP_ID)                                                           \
-{                                                                                   \
-  altKey[0].transfer(castItem);                                                     \
-  theResultSets.push_back(NULL);                                                    \
-  theIndex->theMaps[MAP_ID]->get(&altKey, theResultSets[theResultSets.size() - 1]); \
-}
-
-
-/******************************************************************************
-  
-********************************************************************************/
-void ProbeGeneralHashIndexIterator::init(const store::IndexCondition_t& cond)
-{
-  theProbeKind = cond->getKind();
-
-  if (theProbeKind != store::IndexCondition::POINT_VALUE &&
-      theProbeKind != store::IndexCondition::POINT_GENERAL)
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0007_INDEX_UNSUPPORTED_PROBE_CONDITION,
-    ERROR_PARAMS(cond->getKindString(), theIndex->getName()->getStringValue()));
-  }
-
-  theCondition = reinterpret_cast<IndexPointCondition*>(cond.getp());
-
-  store::IndexKey* key = &(theCondition->theKey);
-
-  if (key->size() != theIndex->getNumColumns())
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0005_INDEX_PARTIAL_KEY_PROBE,
-    ERROR_PARAMS(key->toString(), theIndex->getName()->getStringValue()));
-  }
-
-  if (theProbeKind == store::IndexCondition::POINT_VALUE)
-  {
-    if (theIndex->theMultiKeyFlag)
-    {
-      RAISE_ERROR_NO_LOC(err::XPTY0004,
-      ERROR_PARAMS(ZED(NoMultiKeyNodeValues_2), theIndex->getName()->getStringValue()));
-    }
-
-    if (theIndex->theUntypedFlag)
-    {
-      AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
-
-      if (keyItem->getBaseItem() != NULL)
-        keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
-      
-      SchemaTypeCode keyType = keyItem->getTypeCode();
-
-      if (keyType != XS_UNTYPED_ATOMIC &&
-          keyType != XS_ANY_URI &&
-          keyType != XS_STRING &&
-          keyType != XS_NORMALIZED_STRING &&
-          keyType != XS_TOKEN &&
-          keyType != XS_NMTOKEN &&
-          keyType != XS_LANGUAGE &&
-          keyType != XS_NAME &&
-          keyType != XS_NCNAME &&
-          keyType != XS_ID &&
-          keyType != XS_IDREF &&
-          keyType != XS_ENTITY)
-      {
-        RAISE_ERROR_NO_LOC(err::XPTY0004,
-        ERROR_PARAMS(ZED(NoUntypedKeyNodeValue_2),
-                     theIndex->getName()->getStringValue()));
-      }
-    }
-  }
-  
-  theResultSets.resize(1);
-  theResultSets[0] = NULL;
-
-  if (theIndex->isTyped())
-  {
-    // Note: the runtime (or compiler) makes sure that the search key is a
-    // subtype of the index key type.
-
-    theIndex->theSingleMap->get(key, theResultSets[0]);
-  }
-  else
-  {
-    bool lossy;
-    store::Item_t castItem;
-    store::IndexKey altKey(1);
-    AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
-
-    if (keyItem->getBaseItem() != NULL)
-    {
-      keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
-      (*key)[0] = keyItem;
-    }
-
-    SchemaTypeCode keyType = keyItem->getTypeCode();
-
-    switch (keyType)
-    {
-    case XS_ANY_URI:
-    {
-      if (theIndex->theMaps[XS_ANY_URI])
-      {
-        theIndex->theMaps[XS_ANY_URI]->get(key, theResultSets[0]);
-      }
-
-      if (theIndex->theMaps[XS_STRING] != NULL)
-      {
-        store::Item_t castItem;
-        zstring tmp;
-        keyItem->getStringValue2(tmp);
-        GET_FACTORY().createString(castItem, tmp);
-
-        PROBE_MAP(XS_STRING);
-      }
-
-      break;
-    }
-
-    case XS_QNAME:
-    case XS_NOTATION:
-    case XS_BASE64BINARY:
-    case XS_HEXBINARY:
-    case XS_BOOLEAN:
-    case XS_DATETIME:
-    case XS_DATE:
-    case XS_TIME:
-    case XS_GYEAR_MONTH:
-    case XS_GYEAR:
-    case XS_GMONTH_DAY:
-    case XS_GDAY:
-    case XS_GMONTH:
-    {
-      if (theIndex->theMaps[keyType] != NULL)
-      {
-        theIndex->theMaps[keyType]->get(key, theResultSets[0]);
-      }
-
-      break;
-    }
-
-    case XS_DURATION:
-    case XS_YM_DURATION:
-    case XS_DT_DURATION:
-    {
-      if (theIndex->theMaps[XS_DURATION])
-      {
-        theIndex->theMaps[XS_DURATION]->get(key, theResultSets[0]);
-      }
-
-      break;
-    }
-
-    case XS_STRING:
-    case XS_NORMALIZED_STRING:
-    case XS_TOKEN:
-    case XS_NMTOKEN:
-    case XS_LANGUAGE:
-    case XS_NAME:
-    case XS_NCNAME:
-    case XS_ID:
-    case XS_IDREF:
-    case XS_ENTITY:
-    {
-      if (theIndex->theMaps[XS_STRING])
-      {
-        theIndex->theMaps[XS_STRING]->get(key, theResultSets[0]);
-      }
-
-      if (theIndex->theMaps[XS_ANY_URI])
-      {
-        store::Item_t castItem;
-        zstring tmp;
-        keyItem->getStringValue2(tmp);
-        GET_FACTORY().createAnyURI(castItem, tmp);
-
-        PROBE_MAP(XS_ANY_URI);
-      }
-
-      break;
-    }
-
-    case XS_DOUBLE:
-    case XS_FLOAT:
-    {
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        theIndex->theMaps[XS_DOUBLE]->get(key, theResultSets[0]);
-      }
-
-      if (theIndex->theMaps[XS_LONG] && keyItem->castToLong(castItem))
-      {
-        PROBE_MAP(XS_LONG);
-      }
-
-      break;
-    }
-
-    case XS_DECIMAL:
-    case XS_INTEGER:
-    case XS_NON_POSITIVE_INTEGER:
-    case XS_NEGATIVE_INTEGER:
-    case XS_NON_NEGATIVE_INTEGER:
-    case XS_POSITIVE_INTEGER:
-    case XS_UNSIGNED_LONG:
-    {
-      keyItem->coerceToDouble(castItem, true, lossy);
-
-      if (lossy && theIndex->theMaps[XS_DECIMAL])
-      {
-        theIndex->theMaps[XS_DECIMAL]->get(key, theResultSets[0]);
-      }
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        PROBE_MAP(XS_DOUBLE);
-      }
-
-      if (theIndex->theMaps[XS_LONG] && keyItem->castToLong(castItem))
-      {
-        PROBE_MAP(XS_LONG);
-      }
-
-      break;
-    }
-
-    case XS_LONG:
-    case XS_INT:
-    case XS_SHORT:
-    case XS_BYTE:
-    case XS_UNSIGNED_INT:
-    case XS_UNSIGNED_SHORT:
-    case XS_UNSIGNED_BYTE:
-    {
-      if (theIndex->theMaps[XS_LONG])
-      {
-        theIndex->theMaps[XS_LONG]->get(key, theResultSets[0]);
-      }
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        keyItem->coerceToDouble(castItem, true, lossy);
-        PROBE_MAP(XS_DOUBLE);
-      }
-
-      break;
-    }
-
-    case XS_UNTYPED_ATOMIC:
-    {
-      theIsUntypedProbe = true;
-
-      store::ItemHandle<UntypedAtomicItem> untypedItem = 
-      static_cast<UntypedAtomicItem*>(keyItem);
-
-      // cast to xs:string
-      if (theIndex->theMaps[XS_STRING])
-      {
-        untypedItem->castToString(castItem); 
-        PROBE_MAP(XS_STRING);
-      }
-
-      // cast to xs:anyURI
-      if (theIndex->theMaps[XS_ANY_URI] &&
-          untypedItem->castToUri(castItem))
-      {
-        PROBE_MAP(XS_ANY_URI);
-      }
-
-      if (theProbeKind == store::IndexCondition::POINT_VALUE)
-        return;
-
-      // try casting to xs:long
-      if ((theIndex->theMaps[XS_LONG] ||
-           theIndex->theMaps[XS_DOUBLE]) &&
-          (untypedItem->castToLong(castItem), castItem != NULL))
-      {
-        store::ItemHandle<LongItem> longItem = 
-        static_cast<LongItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_LONG])
-          PROBE_MAP(XS_LONG);
-
-        if (theIndex->theMaps[XS_DOUBLE])
-        {
-          longItem->coerceToDouble(castItem, true, lossy);
-          PROBE_MAP(XS_DOUBLE);
-        }
-
-        // may also be gYear, hexBinary, or boolean
-        if (theIndex->theMaps[XS_GYEAR])
-        {
-          untypedItem->castToGYear(castItem);
-          PROBE_MAP(XS_GYEAR);
-        }
-
-        if (theIndex->theMaps[XS_HEXBINARY])
-        {
-          untypedItem->castToHexBinary(castItem); 
-          PROBE_MAP(XS_HEXBINARY);
-        }
-      }
-
-      // try casting to xs:decimal
-      else if ((theIndex->theMaps[XS_DECIMAL] ||
-                theIndex->theMaps[XS_LONG] ||
-                theIndex->theMaps[XS_DOUBLE]) &&
-               untypedItem->castToDecimal(castItem))
-      {
-        store::ItemHandle<DecimalItem> decimalItem = 
-        static_cast<DecimalItem*>(castItem.getp());
-
-        decimalItem->coerceToDouble(castItem, true, lossy);
-
-        if (theIndex->theMaps[XS_DOUBLE])
-        {
-          PROBE_MAP(XS_DOUBLE);
-        }
-
-        if (theIndex->theMaps[XS_LONG] && decimalItem->castToLong(castItem))
-        {
-          PROBE_MAP(XS_LONG);
-        }
-
-        if (lossy && theIndex->theMaps[XS_DECIMAL])
-        {
-          castItem.transfer(decimalItem);
-          PROBE_MAP(XS_DOUBLE);
-        }
-
-        // may also be hexBinary
-        if (theIndex->theMaps[XS_HEXBINARY])
-        {
-          untypedItem->castToHexBinary(castItem); 
-          PROBE_MAP(XS_HEXBINARY);
-        }
-      }
-
-      // try casting to xs:double
-      else if ((theIndex->theMaps[XS_LONG] || theIndex->theMaps[XS_DOUBLE]) &&
-               untypedItem->castToDouble(castItem))
-      {
-        store::ItemHandle<DoubleItem> doubleItem = 
-        static_cast<DoubleItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_DOUBLE])
-          PROBE_MAP(XS_DOUBLE);
-
-        if (theIndex->theMaps[XS_LONG] && doubleItem->castToLong(castItem))
-        {
-          PROBE_MAP(XS_LONG);
-        }
-      }
-
-      // try casting to xs:datetime
-      else if (theIndex->theMaps[XS_DATETIME] &&
-               untypedItem->castToDateTime(castItem))
-      {
-        PROBE_MAP(XS_DATETIME);
-      }
-
-      // try casting to xs:date
-      else if (theIndex->theMaps[XS_DATE] &&
-               untypedItem->castToDate(castItem))
-      {
-        PROBE_MAP(XS_DATE);
-      }
-
-      // try casting to xs:time
-      else if (theIndex->theMaps[XS_TIME] &&
-               untypedItem->castToTime(castItem))
-      {
-        PROBE_MAP(XS_TIME);
-      }
-
-      // try casting to xs:gYearMonth
-      else if (theIndex->theMaps[XS_GYEAR_MONTH] &&
-               untypedItem->castToGYearMonth(castItem))
-      {
-        PROBE_MAP(XS_GYEAR_MONTH);
-      }
-
-      // try casting to xs:gMonthDay
-      else if (theIndex->theMaps[XS_GMONTH_DAY] &&
-               untypedItem->castToGMonthDay(castItem))
-      {
-        PROBE_MAP(XS_GMONTH_DAY);
-      }
-
-      // try casting to xs:gDay
-      else if (theIndex->theMaps[XS_GDAY] &&
-               untypedItem->castToGDay(castItem))
-      {
-        PROBE_MAP(XS_GDAY);
-      }
-
-      // try casting to xs:gMonth
-      else if (theIndex->theMaps[XS_GMONTH] &&
-               untypedItem->castToGMonth(castItem))
-      {
-        PROBE_MAP(XS_GMONTH);
-      }
-      
-      // try casting to xs:duration
-      else if (theIndex->theMaps[XS_DURATION] &&
-               untypedItem->castToDuration(castItem))
-      {
-        PROBE_MAP(XS_DURATION);
-      }
-      
-      // try casting to xs:hexBinary
-      else if (theIndex->theMaps[XS_HEXBINARY] &&
-               untypedItem->castToHexBinary(castItem))
-      {
-        PROBE_MAP(XS_HEXBINARY);
-      }
-      
-      // try casting to xs:base64Binary
-      else if (theIndex->theMaps[XS_BASE64BINARY] &&
-               untypedItem->castToBase64Binary(castItem))
-      {
-        PROBE_MAP(XS_BASE64BINARY);
-      }
-      
-      break;
-    }
-
-    default:
-    {
-      ZORBA_ASSERT(false);
-    }
-    }
-  }
-}
-
-
-/******************************************************************************
-
-********************************************************************************/
-void ProbeGeneralHashIndexIterator::open()
-{
-  theResultSetsEnd = theResultSets.end();
-  theResultSetsIte = theResultSets.begin();
-
-  for (; theResultSetsIte != theResultSetsEnd; ++theResultSetsIte)
-  {
-    if (*theResultSetsIte != NULL)
-    {
-      theIte = (*theResultSetsIte)->begin();
-      theEnd = (*theResultSetsIte)->end();
-
-      break;
-    }
-  }
-}
-
-
-/******************************************************************************
-
-********************************************************************************/
-void ProbeGeneralHashIndexIterator::reset()
-{
-  open();
-}
-
-
-/******************************************************************************
-
-********************************************************************************/
-void ProbeGeneralHashIndexIterator::close()
-{
-}
-
-
-/******************************************************************************
-  TODO : need sync on result vector
-********************************************************************************/
-bool ProbeGeneralHashIndexIterator::next(store::Item_t& result)
-{
-  while (theResultSetsIte != theResultSetsEnd)
-  {
-    while (theIte != theEnd)
-    {
-      if (theIsUntypedProbe && (*theIte).theUntyped)
-      {
-        ++theIte;
-        continue;
-      }
-
-      result = (*theIte).theNode;
-      ++theIte;
-      return true;
-    }
-
-    ++theResultSetsIte;
-
-    if (theResultSetsIte != theResultSetsEnd && *theResultSetsIte != NULL)
-    {
-      theIte = (*theResultSetsIte)->begin();
-      theEnd = (*theResultSetsIte)->end();
-    }
-  }
-
+
+*******************************************************************************/
+GeneralHashIndex::KeyIterator::~KeyIterator()
+{
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+void GeneralHashIndex::KeyIterator::open()
+{
+  assert(false);
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+bool GeneralHashIndex::KeyIterator::next(store::IndexKey&)
+{
+  assert(false);
   return false;
 }
 
 
+/******************************************************************************
+
+*******************************************************************************/
+void GeneralHashIndex::KeyIterator::close()
+{
+  assert(false);
+}
+
+
 /////////////////////////////////////////////////////////////////////////////////
 //                                                                             //
 //  Tree General Index                                                         //
@@ -1086,15 +805,11 @@
 
   memset(reinterpret_cast<void*>(theMaps), 0, XS_LAST * sizeof(IndexMap*));
 
-  store::Item* typeName = spec.theKeyTypes[0].getp();
-
-  if (typeName != NULL &&
-      typeName != GET_STORE().theSchemaTypeNames[XS_UNTYPED_ATOMIC] &&
-      typeName != GET_STORE().theSchemaTypeNames[XS_ANY_ATOMIC])
+  if (isTyped())
   {
     theSingleMap = new IndexMap(theCompFunction);
 
-    theMaps[GET_STORE().theSchemaTypeCodes[spec.theKeyTypes[0].getp()]] = theSingleMap;
+    theMaps[theKeyTypeCode] = theSingleMap;
   }
 }
 
@@ -1117,7 +832,7 @@
       //std::cout << "Index Entry Delete [" << (*ite).first << "," 
       //          << (*ite).second << "]" << std::endl;
       
-      delete (*ite).first;
+      (*ite).first->removeReference();
       delete (*ite).second;
     }
 
@@ -1129,240 +844,10 @@
 /******************************************************************************
 
 *******************************************************************************/
-bool GeneralTreeIndex::insert(
-    store::IndexKey*& key,
-    store::Item_t& node,
-    bool multikey)
-{
-  bool found = false;
-  store::Item_t castItem;
-  store::Item_t node2;
-  bool lossy;
-
-  AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
-
-  if (keyItem == NULL)
-  {
-    csize numNodes = theEmptyKeyNodes.size();
-    theEmptyKeyNodes.resize(numNodes + 1);
-    theEmptyKeyNodes[numNodes].transfer(node);
-    return true;
-  }
-
-  if (keyItem->getBaseItem() != NULL)
-  {
-    keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
-    (*key)[0] = keyItem;
-  }
-
-  SchemaTypeCode keyType = keyItem->getTypeCode();
-
-  if (isTyped())
-  {
-    return insertInMap(key, node, theSingleMap, multikey, false);
-  }
-
-  switch (keyType)
-  {
-  case XS_ANY_URI:
-  case XS_DATETIME:
-  case XS_DATE:
-  case XS_TIME:
-  case XS_BOOLEAN:
-  {
-    return insertInMap(key, node, theMaps[keyType], multikey, false);
-  }
-
-  case XS_DURATION:
-  case XS_YM_DURATION:
-  case XS_DT_DURATION:
-  {
-    return insertInMap(key, node, theMaps[XS_DURATION], multikey, false);
-  }
-
-  case XS_STRING:
-  case XS_NORMALIZED_STRING:
-  case XS_TOKEN:
-  case XS_NMTOKEN:
-  case XS_LANGUAGE:
-  case XS_NAME:
-  case XS_NCNAME:
-  case XS_ID:
-  case XS_IDREF:
-  case XS_ENTITY:
-  {
-    return insertInMap(key, node, theMaps[XS_STRING], multikey, false);
-  }
-
-  case XS_DOUBLE:
-  case XS_FLOAT:
-  {
-    return insertInMap(key, node, theMaps[XS_DOUBLE], multikey, false);
-  }
-
-  case XS_DECIMAL:
-  case XS_INTEGER:
-  case XS_NON_POSITIVE_INTEGER:
-  case XS_NEGATIVE_INTEGER:
-  case XS_NON_NEGATIVE_INTEGER:
-  case XS_POSITIVE_INTEGER:
-  case XS_UNSIGNED_LONG:
-  {
-    keyItem->castToLong(castItem);
-    if (castItem != NULL)
-    {
-      keyItem = static_cast<AtomicItem*>(castItem.getp());
-      (*key)[0].transfer(castItem);
-      goto longmap;
-    }
-
-    keyItem->coerceToDouble(castItem, true, lossy);
-
-    if (lossy)
-    {
-      node2 = node;
-      found = insertInMap(key, node2, theMaps[XS_DECIMAL], multikey, false);
-    }
-
-    if (key == NULL) key = new store::IndexKey(1);
-    (*key)[0].transfer(castItem);
-
-    found = found || insertInMap(key, node, theMaps[XS_DOUBLE], multikey, false);
-
-    return found;
-  }
-
-  case XS_LONG:
-  {
-longmap:
-    xs_long longValue = static_cast<LongItem*>(keyItem)->getLongValue();
-
-    if (longValue > theMaxLong || longValue < theMinLong)
-    {
-      node2 = node;
-      found = insertInMap(key, node2, theMaps[XS_LONG], multikey, false);
-
-      xs_double doubleValue(longValue);
-      GET_FACTORY().createDouble(castItem, doubleValue);
-
-      if (key == NULL) key = new store::IndexKey(1);
-      (*key)[0].transfer(castItem);
-
-      found = found || insertInMap(key, node, theMaps[XS_DOUBLE], multikey, false);
-    }
-    else
-    {
-      found = insertInMap(key, node, theMaps[XS_LONG], multikey, false);
-    }
-
-    return found;
-  }
-
-  case XS_INT:
-  case XS_SHORT:
-  case XS_BYTE:
-  case XS_UNSIGNED_INT:
-  case XS_UNSIGNED_SHORT:
-  case XS_UNSIGNED_BYTE:
-  {
-    return insertInMap(key, node, theMaps[XS_LONG], multikey, false);
-  }
-
-  case XS_UNTYPED_ATOMIC:
-  {
-    bool found = false;
-
-    store::ItemHandle<UntypedAtomicItem> untypedItem = 
-    static_cast<UntypedAtomicItem*>((*key)[0].getp());
-
-    node2 = node;
-
-    // cast to xs:string
-    untypedItem->castToString(castItem);
-    ADD_IN_MAP(XS_STRING, false);
-
-    // try casting to xs:long
-    if (untypedItem->castToLong(castItem))
-    {
-      ADD_IN_MAP(XS_LONG, true);
-
-      store::ItemHandle<LongItem> longItem = static_cast<LongItem*>(castItem.getp());
-      xs_long longValue = longItem->getLongValue();
-
-      if (longValue > theMaxLong || longValue < theMinLong)
-      {
-        xs_double doubleValue(longValue);
-        GET_FACTORY().createDouble(castItem, doubleValue);
-
-        ADD_IN_MAP(XS_DOUBLE, true);
-      }
-    }
-
-    // try casting to xs:decimal
-    else if (untypedItem->castToDecimal(castItem))
-    {
-      store::ItemHandle<DecimalItem> decimalItem = 
-      static_cast<DecimalItem*>(castItem.getp());
-
-      ADD_IN_MAP(XS_DOUBLE, true);
-
-      decimalItem->coerceToDouble(castItem, true, lossy);
-      if (lossy)
-      {
-        ADD_IN_MAP(XS_DECIMAL, true);
-      }
-    }
-
-    // try casting to xs:double
-    else if (untypedItem->castToDouble(castItem))
-    {
-      ADD_IN_MAP(XS_DOUBLE, true);
-    }
-
-    // try casting to xs:datetime
-    else if (untypedItem->castToDateTime(castItem))
-    {
-      ADD_IN_MAP(XS_DATETIME, true);
-    }
-
-    // try casting to xs:date
-    else if (untypedItem->castToDate(castItem))
-    {
-      ADD_IN_MAP(XS_DATE, true);
-    }
-
-    // try casting to xs:time
-    else if (untypedItem->castToTime(castItem))
-    {
-      ADD_IN_MAP(XS_TIME, true);
-    }
-
-    // try casting to xs:duration
-    else if (untypedItem->castToDuration(castItem))
-    {
-      ADD_IN_MAP(XS_DURATION, true);
-    }
-
-    return found;
-  }
-
-  default:
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZDTY0012_INDEX_KEY_TYPE_ERROR, 
-    ERROR_PARAMS(getName()->getStringValue()));
-  }
-  }
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
 bool GeneralTreeIndex::insertInMap(
-    store::IndexKey*& key,
+    store::Item_t& key,
     store::Item_t& node,
     IndexMap*& targetMap,
-    bool multikey,
     bool untyped)
 {
   GeneralIndexValue* valueSet = NULL;
@@ -1370,12 +855,6 @@
   if (targetMap == NULL)
     targetMap = new IndexMap(theCompFunction);
 
-  if (untyped)
-    theUntypedFlag = true;
-
-  if (multikey)
-    theMultiKeyFlag = true;
-
   IndexMap::iterator pos = targetMap->find(key);
 
   if (pos != targetMap->end())
@@ -1386,19 +865,19 @@
       ERROR_PARAMS(theQname->getStringValue()));
     }
     
-    pos->second->addNode(node, multikey, untyped);
+    pos->second->addNode(node, untyped);
 
     return true;
   }
 
   valueSet = new GeneralIndexValue();
-  valueSet->addNode(node, multikey, untyped);
+  valueSet->addNode(node, untyped);
   
   //std::cout << "Index Entry Insert [" << key << "," 
   //          << valueSet << "]" << std::endl;
   
-  targetMap->insert(IndexMapPair(key, valueSet));
-  key = NULL; // ownership of the key obj passes to the index.
+  targetMap->insert(IndexMapPair(key.getp(), valueSet));
+  key.release(); // ownership of the key obj passes to the index.
 
   return false;
 }
@@ -1408,7 +887,7 @@
 
 *******************************************************************************/
 bool GeneralTreeIndex::remove(
-    const store::IndexKey* key,
+    const store::Item_t& key,
     store::Item_t& item,
     bool all)
 {
@@ -1419,15 +898,6 @@
 /******************************************************************************
 
 *******************************************************************************/
-ulong GeneralTreeIndex::size() const
-{
-  return 0;
-}
-
-
-/******************************************************************************
-
-*******************************************************************************/
 store::Index::KeyIterator_t GeneralTreeIndex::keys() const
 {
   return 0;
@@ -1474,60 +944,31 @@
 }
 
 
-
-/////////////////////////////////////////////////////////////////////////////////
-//                                                                             //
-//  ProbeHashGeneralIndexIterator                                              //
-//                                                                             //
-//  Iterator to probe a general, hash-based index. The probe itself may be a   //
-//  value probe or a general probe.                                            //
-//                                                                             //
-/////////////////////////////////////////////////////////////////////////////////
-
-
-#define PROBE_TREE_MAP(MAP_ID)                                          \
-{                                                                       \
-  ite = theIndex->theMaps[MAP_ID]->find(key);                           \
-  if (ite != theIndex->theMaps[MAP_ID]->end())                          \
-    theResultSets[0] = ite->second;                                     \
-}
-
-
-#define PROBE_ALT_TREE_MAP(MAP_ID)                                      \
-{                                                                       \
-  altKey[0].transfer(castItem);                                         \
-  theResultSets.push_back(NULL);                                        \
-  ite = theIndex->theMaps[MAP_ID]->find(&altKey);                       \
-  if (ite != theIndex->theMaps[MAP_ID]->end())                          \
-    theResultSets[theResultSets.size() - 1] = ite->second;              \
-}
-
-
-/******************************************************************************
-
-********************************************************************************/
-ProbeGeneralTreeIndexIterator::ProbeGeneralTreeIndexIterator(
-    const store::Index_t& index) 
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  ProbeGeneralIndexIterator                                                  //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+ProbeGeneralIndexIterator::ProbeGeneralIndexIterator(const store::Index_t& idx)
   :
+  theIndex(static_cast<GeneralIndex*>(idx.getp())),
   theIsUntypedProbe(false),
-  theIsFullProbe(false),
-  theResultSets(1)
+  theIsFullProbe(false)
 {
-  theIndex = static_cast<GeneralTreeIndex*>(index.getp());
-    
-  theResultSets[0] = NULL;
 }
 
 
-/******************************************************************************
-  
+/*******************************************************************************
+
 ********************************************************************************/
-void ProbeGeneralTreeIndexIterator::checkStringKeyType(AtomicItem* keyItem) const
+void ProbeGeneralIndexIterator::checkStringKeyType(const AtomicItem* key) const
 {
-  if (keyItem == NULL)
+  if (key == NULL)
     return;
 
-  SchemaTypeCode keyType = keyItem->getTypeCode();
+  SchemaTypeCode keyType = key->getTypeCode();
 
   if (keyType != XS_UNTYPED_ATOMIC &&
       keyType != XS_ANY_URI &&
@@ -1543,1032 +984,7 @@
       keyType != XS_ENTITY)
   {
     RAISE_ERROR_NO_LOC(err::XPTY0004,
-    ERROR_PARAMS(ZED(NoUntypedKeyNodeValue_2),
-                 theIndex->getName()->getStringValue()));
-  }
-}
-
-
-/******************************************************************************
-  
-********************************************************************************/
-void ProbeGeneralTreeIndexIterator::init(const store::IndexCondition_t& cond)
-{
-  theProbeKind = cond->getKind();
-
-  if (cond->getKind() == store::IndexCondition::POINT_VALUE ||
-      cond->getKind() == store::IndexCondition::BOX_VALUE)
-  {
-    if (theIndex->theMultiKeyFlag)
-    {
-      RAISE_ERROR_NO_LOC(err::XPTY0004,
-      ERROR_PARAMS(ZED(NoMultiKeyNodeValues_2),
-                   theIndex->getName()->getStringValue()));
-    }
-  }
-
-  if (cond->getKind() == store::IndexCondition::POINT_VALUE ||
-      cond->getKind() == store::IndexCondition::POINT_GENERAL)
-  {
-    initPoint(cond);
-  }
-  else if (cond->getKind() == store::IndexCondition::BOX_VALUE)
-  {
-    initValueBox(cond);
-  }
-  else
-  {
-    initGeneralBox(cond);
-  }
-}
-
-
-/******************************************************************************
-  
-********************************************************************************/
-void ProbeGeneralTreeIndexIterator::initPoint(const store::IndexCondition_t& cond)
-{
-  thePointCondition = reinterpret_cast<IndexPointCondition*>(cond.getp());
-
-  // Note: the runtime (or compiler) makes sure that the search tuple consists
-  // of exactly one search item, which is not NULL and whose type is a subtype
-  // of the index key type. Furthermore, in the case of a point-value probe,
-  // the type of the search item cannot be untyped, because untyped search keys
-  // either don't match the index key type, or are cast to xs:string. 
-
-  store::IndexKey* key = &(thePointCondition->theKey);
-
-  if (key->size() != theIndex->getNumColumns())
-  {
-    ZORBA_ASSERT(false);
-  }
-
-  if (theProbeKind == store::IndexCondition::POINT_VALUE &&
-      theIndex->theUntypedFlag)
-  {
-    AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
-    checkStringKeyType(keyItem);
-  }
-
-  theResultSets.resize(1);
-  theResultSets[0] = NULL;
-
-  EntryIterator ite;
-
-  if (theIndex->isTyped())
-  {
-    ite = theIndex->theSingleMap->find(key);
-
-    if (ite != theIndex->theSingleMap->end())
-      theResultSets[0] = ite->second;
-  }
-  else
-  {
-    bool lossy;
-    store::Item_t castItem;
-    store::IndexKey altKey(1);
-
-    AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
-
-    if (keyItem->getBaseItem() != NULL)
-    {
-      keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
-      (*key)[0] = keyItem;
-    }
-
-    SchemaTypeCode keyType = keyItem->getTypeCode();
-
-    switch (keyType)
-    {
-    case XS_BOOLEAN:
-    case XS_DATETIME:
-    case XS_DATE:
-    case XS_TIME:
-    {
-      if (theIndex->theMaps[keyType] != NULL)
-        PROBE_TREE_MAP(keyType);
-
-      break;
-    }
-
-    case XS_DURATION:
-    case XS_YM_DURATION:
-    case XS_DT_DURATION:
-    {
-      if (theIndex->theMaps[XS_DURATION])
-        PROBE_TREE_MAP(XS_DURATION);
-
-      break;
-    }
-
-    case XS_ANY_URI:
-    {
-      if (theIndex->theMaps[XS_ANY_URI])
-        PROBE_TREE_MAP(XS_ANY_URI);
-
-      if (theIndex->theMaps[XS_STRING] != NULL)
-      {
-        zstring tmp;
-        keyItem->getStringValue2(tmp);
-        GET_FACTORY().createString(castItem, tmp);
-
-        PROBE_ALT_TREE_MAP(XS_STRING);
-      }
-
-      break;
-    }
-
-    case XS_STRING:
-    case XS_NORMALIZED_STRING:
-    case XS_TOKEN:
-    case XS_NMTOKEN:
-    case XS_LANGUAGE:
-    case XS_NAME:
-    case XS_NCNAME:
-    case XS_ID:
-    case XS_IDREF:
-    case XS_ENTITY:
-    {
-      if (theIndex->theMaps[XS_STRING])
-        PROBE_TREE_MAP(XS_STRING);
-
-      if (theIndex->theMaps[XS_ANY_URI])
-      {
-        zstring tmp;
-        keyItem->getStringValue2(tmp);
-        GET_FACTORY().createAnyURI(castItem, tmp);
-
-        PROBE_ALT_TREE_MAP(XS_ANY_URI);
-      }
-
-      break;
-    }
-
-    case XS_DOUBLE:
-    case XS_FLOAT:
-    {
-      if (theIndex->theMaps[XS_DOUBLE])
-        PROBE_TREE_MAP(XS_DOUBLE);
-
-      if (theIndex->theMaps[XS_LONG] && keyItem->castToLong(castItem))
-        PROBE_ALT_TREE_MAP(XS_LONG);
-
-      break;
-    }
-
-    case XS_DECIMAL:
-    case XS_INTEGER:
-    case XS_NON_POSITIVE_INTEGER:
-    case XS_NEGATIVE_INTEGER:
-    case XS_NON_NEGATIVE_INTEGER:
-    case XS_POSITIVE_INTEGER:
-    case XS_UNSIGNED_LONG:
-    {
-      keyItem->coerceToDouble(castItem, true, lossy);
-
-      if (lossy && theIndex->theMaps[XS_DECIMAL])
-        PROBE_TREE_MAP(XS_DECIMAL);
-
-      if (theIndex->theMaps[XS_DOUBLE])
-        PROBE_ALT_TREE_MAP(XS_DOUBLE);
-
-      if (theIndex->theMaps[XS_LONG] && keyItem->castToLong(castItem))
-        PROBE_ALT_TREE_MAP(XS_LONG);
-
-      break;
-    }
-
-    case XS_LONG:
-    case XS_INT:
-    case XS_SHORT:
-    case XS_BYTE:
-    case XS_UNSIGNED_INT:
-    case XS_UNSIGNED_SHORT:
-    case XS_UNSIGNED_BYTE:
-    {
-      if (theIndex->theMaps[XS_LONG])
-        PROBE_TREE_MAP(XS_LONG);
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        keyItem->coerceToDouble(castItem, true, lossy);
-        PROBE_ALT_TREE_MAP(XS_DOUBLE);
-      }
-
-      break;
-    }
-
-    case XS_UNTYPED_ATOMIC:
-    {
-      ZORBA_ASSERT(theProbeKind == store::IndexCondition::POINT_GENERAL);
-
-      theIsUntypedProbe = true;
-
-      store::ItemHandle<UntypedAtomicItem> untypedItem = 
-      static_cast<UntypedAtomicItem*>(keyItem);
-
-      // cast to xs:string
-      if (theIndex->theMaps[XS_STRING])
-      {
-        untypedItem->castToString(castItem); 
-        PROBE_ALT_TREE_MAP(XS_STRING);
-      }
-
-      // cast to xs:anyURI
-      if (theIndex->theMaps[XS_ANY_URI] && untypedItem->castToUri(castItem))
-        PROBE_ALT_TREE_MAP(XS_ANY_URI);
-
-      if (theProbeKind == store::IndexCondition::POINT_VALUE)
-        return;
-
-      // try casting to xs:long
-      if ((theIndex->theMaps[XS_LONG] ||
-           theIndex->theMaps[XS_DOUBLE]) &&
-          (untypedItem->castToLong(castItem), castItem != NULL))
-      {
-        store::ItemHandle<LongItem> longItem = 
-        static_cast<LongItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_LONG])
-          PROBE_ALT_TREE_MAP(XS_LONG);
-
-        if (theIndex->theMaps[XS_DOUBLE])
-        {
-          longItem->coerceToDouble(castItem, true, lossy);
-          PROBE_ALT_TREE_MAP(XS_DOUBLE);
-        }
-      }
-
-      // try casting to xs:decimal
-      else if ((theIndex->theMaps[XS_DECIMAL] ||
-                theIndex->theMaps[XS_LONG] ||
-                theIndex->theMaps[XS_DOUBLE]) &&
-               untypedItem->castToDecimal(castItem))
-      {
-        store::ItemHandle<DecimalItem> decimalItem = 
-        static_cast<DecimalItem*>(castItem.getp());
-
-        decimalItem->coerceToDouble(castItem, true, lossy);
-
-        if (theIndex->theMaps[XS_DOUBLE])
-          PROBE_ALT_TREE_MAP(XS_DOUBLE);
-
-        if (theIndex->theMaps[XS_LONG] && decimalItem->castToLong(castItem))
-          PROBE_ALT_TREE_MAP(XS_LONG);
-
-        if (lossy && theIndex->theMaps[XS_DECIMAL])
-        {
-          castItem.transfer(decimalItem);
-          PROBE_ALT_TREE_MAP(XS_DOUBLE);
-        }
-      }
-
-      // try casting to xs:double
-      else if ((theIndex->theMaps[XS_LONG] || theIndex->theMaps[XS_DOUBLE]) &&
-               untypedItem->castToDouble(castItem))
-      {
-        store::ItemHandle<DoubleItem> doubleItem = 
-        static_cast<DoubleItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_DOUBLE])
-          PROBE_ALT_TREE_MAP(XS_DOUBLE);
-
-        if (theIndex->theMaps[XS_LONG] && doubleItem->castToLong(castItem))
-          PROBE_ALT_TREE_MAP(XS_LONG);
-      }
-
-      // try casting to xs:datetime
-      else if (theIndex->theMaps[XS_DATETIME] && untypedItem->castToDateTime(castItem))
-      {
-        PROBE_ALT_TREE_MAP(XS_DATETIME);
-      }
-
-      // try casting to xs:date
-      else if (theIndex->theMaps[XS_DATE] && untypedItem->castToDate(castItem))
-      {
-        PROBE_ALT_TREE_MAP(XS_DATE);
-      }
-
-      // try casting to xs:time
-      else if (theIndex->theMaps[XS_TIME] && untypedItem->castToTime(castItem))
-      {
-        PROBE_ALT_TREE_MAP(XS_TIME);
-      }
-
-      // try casting to xs:duration
-      else if (theIndex->theMaps[XS_DURATION] && untypedItem->castToDuration(castItem))
-      {
-        PROBE_ALT_TREE_MAP(XS_DURATION);
-      }
-
-      break;
-    }
-
-    default:
-    {
-      ZORBA_ASSERT(false);
-    }
-    }
-  }
-}
-
-
-/******************************************************************************
-  
-********************************************************************************/
-void ProbeGeneralTreeIndexIterator::initValueBox(
-    const store::IndexCondition_t& cond)
-{
-  theBoxValueCondition = static_cast<IndexBoxValueCondition*>(cond.getp());
-
-  ulong numRanges = theBoxValueCondition->numRanges();
-
-  if (numRanges > theIndex->getNumColumns())
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0006_INDEX_INVALID_BOX_PROBE,
-    ERROR_PARAMS(theIndex->getName()->getStringValue(), ZED(BoxCondTooManyColumns)));
-  }
-
-  if (numRanges == 0)
-  {
-    ZORBA_ASSERT(false);
-  }
-
-  store::IndexKey* lowerKey = &theBoxValueCondition->theLowerBounds;
-  store::IndexKey* upperKey = &theBoxValueCondition->theUpperBounds;
-
-  AtomicItem* lowerKeyItem = static_cast<AtomicItem*>((*lowerKey)[0].getp());
-  AtomicItem* upperKeyItem = static_cast<AtomicItem*>((*upperKey)[0].getp());
-
-  bool haveLower = theBoxValueCondition->theRangeFlags[0].theHaveLowerBound;
-  bool haveUpper = theBoxValueCondition->theRangeFlags[0].theHaveUpperBound;
-
-  if (theIndex->theUntypedFlag)
-  {
-    checkStringKeyType(lowerKeyItem);
-    checkStringKeyType(upperKeyItem);
-  }
-
-  theMapBegins.clear();
-  theMapEnds.clear();
-
-  if (theIndex->isTyped())
-  {
-    // Note: the runtime (or compiler) makes sure that each search key is a
-    // subtype of the index key type.
-    probeMap(theIndex->theSingleMap, lowerKey, upperKey);
-  }
-  else if (haveLower || haveUpper)
-  {
-    store::Item_t castItem;
-
-    SchemaTypeCode lowerKeyType = (haveLower ? lowerKeyItem->getTypeCode() : XS_LAST);
-    SchemaTypeCode upperKeyType = (haveUpper ? upperKeyItem->getTypeCode() : XS_LAST);
-
-    SchemaTypeCode keyType = (lowerKeyType < upperKeyType ?
-                              lowerKeyType :
-                              upperKeyType);
-
-    switch (keyType)
-    {
-    case XS_BOOLEAN:
-    case XS_DATETIME:
-    case XS_DATE:
-    case XS_TIME:
-    {
-      probeMap(theIndex->theMaps[keyType], lowerKey, upperKey);
-      break;
-    }
-
-    case XS_DURATION:
-    case XS_YM_DURATION:
-    case XS_DT_DURATION:
-    {
-      probeMap(theIndex->theMaps[XS_DURATION], lowerKey, upperKey);
-      break;
-    }
-
-    case XS_ANY_URI:
-    {
-      probeMap(theIndex->theMaps[XS_ANY_URI], lowerKey, upperKey);
-
-      if (theIndex->theMaps[XS_STRING])
-      {
-        zstring tmp;
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-        {
-          lowerKeyItem->getStringValue2(tmp);
-          GET_FACTORY().createString(castItem, tmp);
-          lowerAltKey[0].transfer(castItem);
-        }
-
-        if (haveUpper)
-        {
-          upperKeyItem->getStringValue2(tmp);
-          GET_FACTORY().createString(castItem, tmp);
-          upperAltKey[0].transfer(castItem);
-        }
-        
-        probeMap(theIndex->theMaps[XS_STRING], &lowerAltKey, &upperAltKey);
-      }
-
-      break;
-    }
-
-    case XS_STRING:
-    case XS_NORMALIZED_STRING:
-    case XS_TOKEN:
-    case XS_NMTOKEN:
-    case XS_LANGUAGE:
-    case XS_NAME:
-    case XS_NCNAME:
-    case XS_ID:
-    case XS_IDREF:
-    case XS_ENTITY:
-    {
-      probeMap(theIndex->theMaps[XS_STRING], lowerKey, upperKey);
-
-      if (theIndex->theMaps[XS_ANY_URI])
-      {
-        zstring tmp;
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-        {
-          lowerKeyItem->getStringValue2(tmp);
-          GET_FACTORY().createAnyURI(castItem, tmp);
-          lowerAltKey[0].transfer(castItem);
-        }
-
-        if (haveUpper)
-        {
-          upperKeyItem->getStringValue2(tmp);
-          GET_FACTORY().createAnyURI(castItem, tmp);
-          upperAltKey[0].transfer(castItem);
-        }
-
-        probeMap(theIndex->theMaps[XS_ANY_URI], &lowerAltKey, &upperAltKey);
-      }
-
-      break;
-    }
-
-    case XS_DOUBLE:
-    case XS_FLOAT:
-    {
-      probeMap(theIndex->theMaps[XS_DOUBLE], lowerKey, upperKey);
-
-      if (theIndex->theMaps[XS_LONG])
-      {
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-        {
-          doubleToLongProbe(castItem, lowerKeyItem, false, haveUpper);
-          if (castItem)
-            lowerAltKey[0].transfer(castItem);
-        }
-
-        if (haveUpper)
-        {
-          doubleToLongProbe(castItem, upperKeyItem, false, haveUpper);
-          if (castItem)
-            upperAltKey[0].transfer(castItem);
-        }
-
-        probeMap(theIndex->theMaps[XS_ANY_URI], &lowerAltKey, &upperAltKey);
-      }
-
-      break;
-    }
-
-    case XS_DECIMAL:
-    case XS_INTEGER:
-    case XS_NON_POSITIVE_INTEGER:
-    case XS_NEGATIVE_INTEGER:
-    case XS_NON_NEGATIVE_INTEGER:
-    case XS_POSITIVE_INTEGER:
-    case XS_UNSIGNED_LONG:
-    {
-      probeMap(theIndex->theMaps[XS_DECIMAL], lowerKey, upperKey);
-
-      if (theIndex->theMaps[XS_LONG])
-      {
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-          lowerAltKey[0] = lowerKeyItem;
-
-        if (haveUpper)
-          upperAltKey[0] = upperKeyItem;
-
-        probeMap(theIndex->theMaps[XS_LONG], &lowerAltKey, &upperAltKey);
-      }
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-        {
-          xs_double doubleValue = lowerKeyItem->getDecimalValue();
-          GET_FACTORY().createDouble(castItem, doubleValue);
-          lowerAltKey[0].transfer(castItem);
-        }
-
-        if (haveUpper)
-        {
-          xs_double doubleValue = upperKeyItem->getDecimalValue();
-          GET_FACTORY().createDouble(castItem, doubleValue);
-          upperAltKey[0].transfer(castItem);
-        }
-
-        probeMap(theIndex->theMaps[XS_DOUBLE], &lowerAltKey, &upperAltKey);
-      }
-
-      break;
-    }
-
-    case XS_LONG:
-    case XS_INT:
-    case XS_SHORT:
-    case XS_BYTE:
-    case XS_UNSIGNED_INT:
-    case XS_UNSIGNED_SHORT:
-    case XS_UNSIGNED_BYTE:
-    {
-      probeMap(theIndex->theMaps[XS_LONG], lowerKey, upperKey);
-
-      if (theIndex->theMaps[XS_DECIMAL])
-      {
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-        {
-          xs_decimal decimalValue = lowerKeyItem->getLongValue();
-          GET_FACTORY().createDecimal(castItem, decimalValue);
-          lowerAltKey[0].transfer(castItem);
-        }
-
-        if (haveUpper)
-        {
-          xs_decimal decimalValue = upperKeyItem->getLongValue();
-          GET_FACTORY().createDecimal(castItem, decimalValue);
-          upperAltKey[0].transfer(castItem);
-        }
-
-        probeMap(theIndex->theMaps[XS_DECIMAL], &lowerAltKey, &upperAltKey);
-      }
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        store::IndexKey lowerAltKey(1);
-        store::IndexKey upperAltKey(1);
-
-        if (haveLower)
-        {
-          xs_double doubleValue = lowerKeyItem->getLongValue();
-          GET_FACTORY().createDouble(castItem, doubleValue);
-          lowerAltKey[0].transfer(castItem);
-        }
-
-        if (haveUpper)
-        {
-          xs_double doubleValue = upperKeyItem->getLongValue();
-          GET_FACTORY().createDouble(castItem, doubleValue);
-          upperAltKey[0].transfer(castItem);
-        }
-
-        probeMap(theIndex->theMaps[XS_DOUBLE], &upperAltKey, &lowerAltKey);
-      }
-
-      break;
-    }
-
-    default:
-      ZORBA_ASSERT(false);
-    }
-  }
-  else
-  {
-    theIsFullProbe = true;
-
-    for (ulong i = 0; i < XS_LAST; ++i)
-    {
-      if (theIndex->theMaps[i] == NULL)
-        continue;
-
-      theMapBegins.push_back(theIndex->theMaps[i]->begin());
-      theMapEnds.push_back(theIndex->theMaps[i]->end());
-    }
-  }
-}
-
-
-/******************************************************************************
-  
-********************************************************************************/
-void ProbeGeneralTreeIndexIterator::initGeneralBox(
-    const store::IndexCondition_t& cond)
-{
-  theBoxGeneralCondition = reinterpret_cast<IndexBoxGeneralCondition*>(cond.getp());
-
-  store::IndexKey* key = &theBoxGeneralCondition->theBound;
-
-  bool haveLower = theBoxGeneralCondition->theRangeFlags.theHaveLowerBound;
-  bool haveUpper = theBoxGeneralCondition->theRangeFlags.theHaveUpperBound;
-
-  theMapBegins.clear();
-  theMapEnds.clear();
-  
-  assert(!(haveLower && haveUpper));
-
-  if (theIndex->isTyped())
-  {
-    // Note: the runtime (or compiler) makes sure that the search key is a
-    // subtype of the index key type.
-    probeMap(theIndex->theSingleMap, key, key);
-  }
-  else if (haveLower || haveUpper)
-  {
-    store::Item_t castItem;
-    store::IndexKey altKey(1);
-
-    AtomicItem* keyItem = static_cast<AtomicItem*>((*key)[0].getp());
-
-    if (keyItem->getBaseItem() != NULL)
-    {
-      keyItem = static_cast<AtomicItem*>(keyItem->getBaseItem());
-      (*key)[0] = keyItem;
-    }
-
-    SchemaTypeCode keyType = keyItem->getTypeCode();
-
-    switch (keyType)
-    {
-    case XS_BOOLEAN:
-    case XS_DATETIME:
-    case XS_DATE:
-    case XS_TIME:
-    {
-      probeMap(theIndex->theMaps[keyType], key, key);
-      break;
-    }
-
-    case XS_DURATION:
-    case XS_YM_DURATION:
-    case XS_DT_DURATION:
-    {
-      probeMap(theIndex->theMaps[XS_DURATION], key, key);
-      break;
-    }
-
-    case XS_ANY_URI:
-    {
-      probeMap(theIndex->theMaps[XS_ANY_URI], key, key);
-
-      if (theIndex->theMaps[XS_STRING])
-      {
-        zstring tmp;
-        keyItem->getStringValue2(tmp);
-        GET_FACTORY().createString(castItem, tmp);
-
-        altKey[0].transfer(castItem);
-        
-        probeMap(theIndex->theMaps[XS_STRING], &altKey, &altKey);
-      }
-
-      break;
-    }
-
-    case XS_STRING:
-    case XS_NORMALIZED_STRING:
-    case XS_TOKEN:
-    case XS_NMTOKEN:
-    case XS_LANGUAGE:
-    case XS_NAME:
-    case XS_NCNAME:
-    case XS_ID:
-    case XS_IDREF:
-    case XS_ENTITY:
-    {
-      probeMap(theIndex->theMaps[XS_STRING], key, key);
-
-      if (theIndex->theMaps[XS_ANY_URI])
-      {
-        zstring tmp;
-        keyItem->getStringValue2(tmp);
-        GET_FACTORY().createAnyURI(castItem, tmp);
-
-        altKey[0].transfer(castItem);
-        
-        probeMap(theIndex->theMaps[XS_ANY_URI], &altKey, &altKey);
-      }
-
-      break;
-    }
-
-    case XS_DOUBLE:
-    case XS_FLOAT:
-    {
-      probeMap(theIndex->theMaps[XS_DOUBLE], key, key);
-
-      if (theIndex->theMaps[XS_LONG])
-      {
-        doubleToLongProbe(castItem, keyItem, haveLower, haveUpper);
-
-        if (castItem)
-        {
-          altKey[0].transfer(castItem);
-          probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
-        }
-      }
-
-      break;
-    }
-
-    case XS_DECIMAL:
-    case XS_INTEGER:
-    case XS_NON_POSITIVE_INTEGER:
-    case XS_NEGATIVE_INTEGER:
-    case XS_NON_NEGATIVE_INTEGER:
-    case XS_POSITIVE_INTEGER:
-    case XS_UNSIGNED_LONG:
-    {
-      probeMap(theIndex->theMaps[XS_DECIMAL], key, key);
-
-      if (theIndex->theMaps[XS_LONG])
-      {
-        altKey[0] = keyItem;
-        probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
-      }
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        xs_double doubleValue = keyItem->getDecimalValue();
-        GET_FACTORY().createDouble(castItem, doubleValue);
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
-      }
-
-      break;
-    }
-
-    case XS_LONG:
-    case XS_INT:
-    case XS_SHORT:
-    case XS_BYTE:
-    case XS_UNSIGNED_INT:
-    case XS_UNSIGNED_SHORT:
-    case XS_UNSIGNED_BYTE:
-    {
-      probeMap(theIndex->theMaps[XS_LONG], key, key);
-
-      if (theIndex->theMaps[XS_DECIMAL])
-      {
-        xs_decimal decimalValue = keyItem->getLongValue();
-        GET_FACTORY().createDecimal(castItem, decimalValue);
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_DECIMAL], &altKey, &altKey);
-      }
-
-      if (theIndex->theMaps[XS_DOUBLE])
-      {
-        xs_double doubleValue = keyItem->getLongValue();
-        GET_FACTORY().createDouble(castItem, doubleValue);
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
-      }
-
-      break;
-    }
-
-    case XS_UNTYPED_ATOMIC:
-    {
-      theIsUntypedProbe = true;
-
-      store::ItemHandle<UntypedAtomicItem> untypedItem = 
-      static_cast<UntypedAtomicItem*>(keyItem);
-
-      // cast to xs:string
-      if (theIndex->theMaps[XS_STRING])
-      {
-        untypedItem->castToString(castItem);
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_STRING], &altKey, &altKey);
-      }
-
-      // cast to xs:anyURI
-      if (theIndex->theMaps[XS_ANY_URI] && untypedItem->castToUri(castItem))
-      {
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_ANY_URI], &altKey, &altKey);
-      }
-
-      // try casting to xs:long
-      if ((theIndex->theMaps[XS_LONG] ||
-           theIndex->theMaps[XS_DOUBLE] ||
-           theIndex->theMaps[XS_DECIMAL]) &&
-          untypedItem->castToLong(castItem), castItem != NULL)
-      {
-        store::ItemHandle<LongItem> longItem = 
-        static_cast<LongItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_LONG])
-        {
-          altKey[0].transfer(castItem);
-          probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
-        }
-
-        if (theIndex->theMaps[XS_DOUBLE])
-        {
-          xs_double doubleValue = longItem->getLongValue();
-          GET_FACTORY().createDouble(castItem, doubleValue);
-          altKey[0].transfer(castItem);
-          probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
-        }
-
-        if (theIndex->theMaps[XS_DECIMAL])
-        {
-          xs_decimal decimalValue = longItem->getLongValue();
-          GET_FACTORY().createDecimal(castItem, decimalValue);
-          altKey[0].transfer(castItem);
-          probeMap(theIndex->theMaps[XS_DECIMAL], &altKey, &altKey);
-        }
-      }
-
-      // try casting to xs:decimal
-      else if ((theIndex->theMaps[XS_LONG] ||
-                theIndex->theMaps[XS_DOUBLE] ||
-                theIndex->theMaps[XS_DECIMAL]) &&
-               untypedItem->castToDecimal(castItem), castItem != NULL)
-      {
-        store::ItemHandle<DecimalItem> decimalItem = 
-        static_cast<DecimalItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_DECIMAL])
-        {
-          altKey[0].transfer(castItem);
-          probeMap(theIndex->theMaps[XS_DECIMAL], &altKey, &altKey);
-
-          if (theIndex->theMaps[XS_LONG])
-          {
-            altKey[0] = decimalItem;
-            probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
-          }
-
-          if (theIndex->theMaps[XS_DOUBLE])
-          {
-            xs_double doubleValue = decimalItem->getDecimalValue();
-            GET_FACTORY().createDouble(castItem, doubleValue);
-            altKey[0].transfer(castItem);
-            probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
-          }
-        }
-      }
-
-      // try casting to xs:double
-      else if ((theIndex->theMaps[XS_LONG] ||
-               theIndex->theMaps[XS_DOUBLE]) &&
-               untypedItem->castToDouble(castItem), castItem != NULL)
-      {
-        store::ItemHandle<DoubleItem> doubleItem = 
-        static_cast<DoubleItem*>(castItem.getp());
-
-        if (theIndex->theMaps[XS_DOUBLE])
-        {
-          altKey[0].transfer(castItem);
-          probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
-        }
-
-        if (theIndex->theMaps[XS_LONG])
-        {
-          doubleToLongProbe(castItem, doubleItem.getp(), haveLower, haveUpper);
-
-          if (castItem)
-          {
-            altKey[0].transfer(castItem);
-            probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
-          }
-        }
-      }
-
-      // try casting to xs:datetime
-      else if (theIndex->theMaps[XS_DATETIME] && untypedItem->castToDateTime(castItem))
-      {
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_DATETIME], &altKey, &altKey);
-      }
-
-      // try casting to xs:date
-      else if (theIndex->theMaps[XS_DATE] && untypedItem->castToDate(castItem))
-      {
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_DATE], &altKey, &altKey);
-      }
-
-      // try casting to xs:time
-      else if (theIndex->theMaps[XS_TIME] && untypedItem->castToTime(castItem))
-      {
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_TIME], &altKey, &altKey);
-      }
-
-      // try casting to xs:duration
-      else if (theIndex->theMaps[XS_DURATION] && untypedItem->castToDuration(castItem))
-      {
-        altKey[0].transfer(castItem);
-        probeMap(theIndex->theMaps[XS_DURATION], &altKey, &altKey);
-      }
-
-      break;
-    }
-
-    default:
-    {
-      ZORBA_ASSERT(false);
-    }
-    }
-  }
-  else
-  {
-    for (ulong i = 0; i < XS_LAST; ++i)
-    {
-      if (theIndex->theMaps[i] == NULL)
-        continue;
-
-      theMapBegins.push_back(theIndex->theMaps[i]->begin());
-      theMapEnds.push_back(theIndex->theMaps[i]->end());
-    }
-  }
-}
-
-
-/******************************************************************************
-  
-********************************************************************************/
-void ProbeGeneralTreeIndexIterator::probeMap(
-    GeneralTreeIndex::IndexMap* map,
-    const store::IndexKey* lowerKey,
-    const store::IndexKey* upperKey)
-{
-  if (map == NULL)
-    return;
-
-  IndexBoxCondition::RangeFlags& flags = 
-  (theProbeKind == store::IndexCondition::BOX_VALUE ?
-   theBoxValueCondition->theRangeFlags[0] :
-   theBoxGeneralCondition->theRangeFlags);
-
-  bool haveLower = flags.theHaveLowerBound;
-  bool haveUpper = flags.theHaveUpperBound;
-  bool lowerIncl = flags.theLowerBoundIncl;
-  bool upperIncl = flags.theUpperBoundIncl;
-
-  assert(theProbeKind != store::IndexCondition::BOX_GENERAL ||
-         !(haveLower && haveUpper));
-
-  if (haveLower && haveUpper)
-  {
-    long cmp = (*lowerKey)[0]->compare((*upperKey)[0]);
-
-    if (cmp > 0)
-      return;
-
-    if (cmp == 0 && (!lowerIncl || !upperIncl))
-      return;
-  }
-
-  if (haveLower)
-  {
-    if (lowerIncl)
-      theMapBegins.push_back(map->lower_bound(lowerKey));
-    else
-      theMapBegins.push_back(map->upper_bound(lowerKey));    
-  }
-  else
-  {
-    theMapBegins.push_back(map->begin());
-  }
- 
-  if (haveUpper)
-  {
-    if (upperIncl)
-      theMapEnds.push_back(map->upper_bound(upperKey));
-    else
-      theMapEnds.push_back(map->lower_bound(upperKey));
-  }
-  else
-  {
-    theMapEnds.push_back(map->end());
+    ERROR_PARAMS(ZED(NoUntypedKeyNodeValue_2), theIndex->getName()->getStringValue()));
   }
 }
 
@@ -2576,7 +992,7 @@
 /*******************************************************************************
 
 ********************************************************************************/
-void ProbeGeneralTreeIndexIterator::doubleToLongProbe(
+void ProbeGeneralIndexIterator::doubleToLongProbe(
     store::Item_t& result,
     const AtomicItem* doubleItem,
     bool haveLower,
@@ -2604,7 +1020,7 @@
     else
     {
       longValue = GeneralTreeIndex::theMaxLong;
-      theBoxGeneralCondition->theRangeFlags.theUpperBoundIncl = true;
+      theCondition->theRangeFlags.theUpperBoundIncl = true;
     }
   }
   else if (doubleObj.isNegInf() || doubleValue < GeneralTreeIndex::theDoubleMinLong)
@@ -2612,7 +1028,7 @@
     if (haveLower)
     {
       longValue = GeneralTreeIndex::theMinLong;
-      theBoxGeneralCondition->theRangeFlags.theLowerBoundIncl = true;
+      theCondition->theRangeFlags.theLowerBoundIncl = true;
     }
     else
     {
@@ -2630,11 +1046,11 @@
 
     if (haveLower && lossy)
     {
-      theBoxGeneralCondition->theRangeFlags.theLowerBoundIncl = false;
+      theCondition->theRangeFlags.theLowerBoundIncl = false;
     }
     else if (haveUpper && lossy)
     {
-      theBoxGeneralCondition->theRangeFlags.theUpperBoundIncl = true;
+      theCondition->theRangeFlags.theUpperBoundIncl = true;
     }
   }
 
@@ -2642,10 +1058,822 @@
 }
 
 
-/******************************************************************************
-
-********************************************************************************/
-void ProbeGeneralTreeIndexIterator::open()
+/*******************************************************************************
+  
+********************************************************************************/
+void ProbeGeneralIndexIterator::init(const store::IndexCondition_t& cond)
+{
+  theProbeKind = cond->getKind();
+  theCondition = static_cast<GeneralIndexCondition*>(cond.getp());
+
+  if (theProbeKind == store::IndexCondition::POINT_VALUE ||
+      theProbeKind == store::IndexCondition::BOX_VALUE)
+  {
+    if (theIndex->theMultiKeyFlag)
+    {
+      RAISE_ERROR_NO_LOC(err::XPTY0004,
+      ERROR_PARAMS(ZED(NoMultiKeyNodeValues_2), theIndex->getName()->getStringValue()));
+    }
+
+    if (theIndex->theUntypedFlag)
+    {
+      checkStringKeyType(theCondition->theKey.getp());
+      checkStringKeyType(theCondition->theLowerBound.getp());
+      checkStringKeyType(theCondition->theUpperBound.getp());
+    }
+  }
+
+  if (theProbeKind == store::IndexCondition::POINT_VALUE ||
+      theProbeKind == store::IndexCondition::POINT_GENERAL)
+  {
+    initPoint();
+  }
+  else
+  {
+    static_cast<ProbeGeneralTreeIndexIterator*>(this)->initBox();
+  }
+}
+
+
+/******************************************************************************
+  
+********************************************************************************/
+void ProbeGeneralIndexIterator::initPoint()
+{
+  // Note: the runtime (or compiler) makes sure that the search key is not NULL
+  // and its type is a subtype of the index key type. Furthermore, in the case 
+  // of a point-value probe, the type of the search item cannot be untyped, 
+  // because untyped search keys either don't match the index key type, or are 
+  // cast to xs:string. 
+  AtomicItem_t& key = theCondition->theKey;
+
+  bool sorted = theIndex->isSorted();
+
+  if (theIndex->isTyped())
+  {
+    probeMap(theIndex->theKeyTypeCode, key.getp());
+  }
+  else
+  {
+    bool lossy;
+    store::Item_t castItem;
+
+    SchemaTypeCode keyType = key->getTypeCode();
+
+    switch (keyType)
+    {
+    case XS_QNAME:
+    case XS_NOTATION:
+    case XS_BASE64BINARY:
+    case XS_HEXBINARY:
+    case XS_GYEAR_MONTH:
+    case XS_GYEAR:
+    case XS_GMONTH_DAY:
+    case XS_GDAY:
+    case XS_GMONTH:
+    {
+      assert(!sorted);
+    }
+
+    case XS_BOOLEAN:
+    case XS_DATETIME:
+    case XS_DATE:
+    case XS_TIME:
+
+    {
+      probeMap(keyType, key.getp());
+      break;
+    }
+
+    case XS_DURATION:
+    case XS_YM_DURATION:
+    case XS_DT_DURATION:
+    {
+      probeMap(XS_DURATION, key.getp()); 
+      break;
+    }
+
+    case XS_ANY_URI:
+    {
+      probeMap(XS_ANY_URI, key.getp()); 
+
+      if (haveMap(XS_STRING))
+      {
+        zstring tmp;
+        key->getStringValue2(tmp);
+        GET_FACTORY().createString(castItem, tmp);
+
+        probeMap(XS_STRING, castItem.getp());
+      }
+
+      break;
+    }
+
+    case XS_STRING:
+    case XS_NORMALIZED_STRING:
+    case XS_TOKEN:
+    case XS_NMTOKEN:
+    case XS_LANGUAGE:
+    case XS_NAME:
+    case XS_NCNAME:
+    case XS_ID:
+    case XS_IDREF:
+    case XS_ENTITY:
+    {
+      probeMap(XS_STRING, key.getp());
+
+      if (haveMap(XS_ANY_URI))
+      {
+        zstring tmp;
+        key->getStringValue2(tmp);
+        GET_FACTORY().createAnyURI(castItem, tmp);
+
+        probeMap(XS_ANY_URI, castItem.getp());
+      }
+
+      break;
+    }
+
+    case XS_DOUBLE:
+    case XS_FLOAT:
+    {
+      probeMap(XS_DOUBLE, key.getp());
+
+      if (haveMap(XS_LONG) && key->castToLong(castItem))
+        probeMap(XS_LONG, castItem.getp());
+
+      break;
+    }
+
+    case XS_DECIMAL:
+    case XS_INTEGER:
+    case XS_NON_POSITIVE_INTEGER:
+    case XS_NEGATIVE_INTEGER:
+    case XS_NON_NEGATIVE_INTEGER:
+    case XS_POSITIVE_INTEGER:
+    case XS_UNSIGNED_LONG:
+    {
+      key->coerceToDouble(castItem, true, lossy);
+
+      if (lossy)
+        probeMap(XS_DECIMAL, key.getp());
+
+      probeMap(XS_DOUBLE, castItem.getp());
+
+      if (haveMap(XS_LONG) && key->castToLong(castItem))
+        probeMap(XS_LONG, castItem.getp());
+
+      break;
+    }
+
+    case XS_LONG:
+    case XS_INT:
+    case XS_SHORT:
+    case XS_BYTE:
+    case XS_UNSIGNED_INT:
+    case XS_UNSIGNED_SHORT:
+    case XS_UNSIGNED_BYTE:
+    {
+      probeMap(XS_LONG, key.getp());
+
+      if (haveMap(XS_DOUBLE))
+      {
+        key->coerceToDouble(castItem, true, lossy);
+        probeMap(XS_DOUBLE, castItem.getp());
+      }
+
+      break;
+    }
+
+    case XS_UNTYPED_ATOMIC:
+    {
+      ZORBA_ASSERT(theProbeKind == store::IndexCondition::POINT_GENERAL);
+
+      theIsUntypedProbe = true;
+
+      store::ItemHandle<UntypedAtomicItem> untypedItem = 
+      static_cast<UntypedAtomicItem*>(key.getp());
+
+      // cast to xs:string
+      if (haveMap(XS_STRING))
+      {
+        untypedItem->castToString(castItem); 
+        probeMap(XS_STRING, castItem.getp());
+      }
+
+      // cast to xs:anyURI
+      if (haveMap(XS_ANY_URI) && untypedItem->castToUri(castItem))
+      {
+        probeMap(XS_ANY_URI, castItem.getp());
+      }
+
+      // try casting to xs:long
+      if ((haveMap(XS_LONG) || haveMap(XS_DOUBLE)) &&
+          (untypedItem->castToLong(castItem), castItem != NULL))
+      {
+        store::ItemHandle<LongItem> longItem = 
+        static_cast<LongItem*>(castItem.getp());
+
+        probeMap(XS_LONG, castItem.getp());
+
+        if (haveMap(XS_DOUBLE))
+        {
+          longItem->coerceToDouble(castItem, true, lossy);
+          probeMap(XS_DOUBLE, castItem.getp());
+        }
+
+        // may also be gYear, hexBinary, base64Binary, or boolean
+        if (!sorted)
+        {
+          if (haveMap(XS_GYEAR))
+          {
+            untypedItem->castToGYear(castItem);
+            probeMap(XS_GYEAR, castItem.getp());
+          }
+
+          if (haveMap(XS_HEXBINARY))
+          {
+            untypedItem->castToHexBinary(castItem); 
+            probeMap(XS_HEXBINARY, castItem.getp());
+          }
+
+          if (haveMap(XS_BASE64BINARY))
+          {
+            untypedItem->castToBase64Binary(castItem); 
+            probeMap(XS_BASE64BINARY, castItem.getp());
+          }
+        }
+      }
+
+      // try casting to xs:decimal
+      else if ((haveMap(XS_DECIMAL) || haveMap(XS_LONG) || haveMap(XS_DOUBLE)) &&
+               untypedItem->castToDecimal(castItem))
+      {
+        store::ItemHandle<DecimalItem> decimalItem = 
+        static_cast<DecimalItem*>(castItem.getp());
+
+        decimalItem->coerceToDouble(castItem, true, lossy);
+
+        probeMap(XS_DOUBLE, castItem.getp());
+
+        if (haveMap(XS_LONG) && decimalItem->castToLong(castItem))
+        {
+          probeMap(XS_LONG, castItem.getp());
+        }
+
+        if (lossy && haveMap(XS_DECIMAL))
+        {
+          castItem.transfer(decimalItem);
+          probeMap(XS_DOUBLE, castItem.getp());
+        }
+
+        // may also be hexBinary or base64Binary
+        if (!sorted)
+        {
+          if (haveMap(XS_HEXBINARY))
+          {
+            untypedItem->castToHexBinary(castItem); 
+            probeMap(XS_HEXBINARY, castItem.getp());
+          }
+
+          if (haveMap(XS_BASE64BINARY))
+          {
+            untypedItem->castToBase64Binary(castItem); 
+            probeMap(XS_BASE64BINARY, castItem.getp());
+          }
+        }
+      }
+
+      // try casting to xs:double
+      else if ((haveMap(XS_LONG) || haveMap(XS_DOUBLE)) &&
+               untypedItem->castToDouble(castItem))
+      {
+        store::ItemHandle<DoubleItem> doubleItem = 
+        static_cast<DoubleItem*>(castItem.getp());
+
+        probeMap(XS_DOUBLE, castItem.getp());
+
+        if (haveMap(XS_LONG) && doubleItem->castToLong(castItem))
+        {
+          probeMap(XS_LONG, castItem.getp());
+        }
+      }
+
+      // try casting to xs:datetime
+      else if (haveMap(XS_DATETIME) && untypedItem->castToDateTime(castItem))
+      {
+        probeMap(XS_DATETIME, castItem.getp());
+      }
+
+      // try casting to xs:date
+      else if (haveMap(XS_DATE) && untypedItem->castToDate(castItem))
+      {
+        probeMap(XS_DATE, castItem.getp());
+      }
+
+      // try casting to xs:time
+      else if (haveMap(XS_TIME) && untypedItem->castToTime(castItem))
+      {
+        probeMap(XS_TIME, castItem.getp());
+      }
+
+      // try casting to xs:gYearMonth
+      if (!sorted && 
+          haveMap(XS_GYEAR_MONTH) && untypedItem->castToGYearMonth(castItem))
+      {
+        probeMap(XS_GYEAR_MONTH, castItem.getp());
+      }
+
+      // try casting to xs:gMonthDay
+      else if (!sorted && 
+               haveMap(XS_GMONTH_DAY) && untypedItem->castToGMonthDay(castItem))
+      {
+        probeMap(XS_GMONTH_DAY, castItem.getp());
+      }
+
+      // try casting to xs:gDay
+      else if (!sorted &&
+               haveMap(XS_GDAY) && untypedItem->castToGDay(castItem))
+      {
+        probeMap(XS_GDAY, castItem.getp());
+      }
+
+      // try casting to xs:gMonth
+      else if (!sorted &&
+               haveMap(XS_GMONTH) && untypedItem->castToGMonth(castItem))
+      {
+        probeMap(XS_GMONTH, castItem.getp());
+      }
+
+      // try casting to xs:duration
+      else if (haveMap(XS_DURATION) && untypedItem->castToDuration(castItem))
+      {
+        probeMap(XS_DURATION, castItem.getp());
+      }
+      
+      // try casting to xs:hexBinary
+      else if (!sorted &&
+               haveMap(XS_HEXBINARY) && untypedItem->castToHexBinary(castItem))
+      {
+        probeMap(XS_HEXBINARY, castItem.getp());
+      }
+      
+      // try casting to xs:base64Binary
+      else if (!sorted &&
+               haveMap(XS_BASE64BINARY) && untypedItem->castToBase64Binary(castItem))
+      {
+        probeMap(XS_BASE64BINARY, castItem.getp());
+      }
+      
+      break;
+    }
+
+    default:
+    {
+      ZORBA_ASSERT(false);
+    }
+    }
+  }
+}
+
+
+/******************************************************************************
+  
+********************************************************************************/
+void ProbeGeneralIndexIterator::initBox()
+{
+  GeneralTreeIndex* idx = static_cast<GeneralTreeIndex*>(theIndex.getp());
+
+  bool haveLower = theCondition->theRangeFlags.theHaveLowerBound;
+  bool haveUpper = theCondition->theRangeFlags.theHaveUpperBound;
+
+  assert(theProbeKind == store::IndexCondition::BOX_VALUE ||
+         !(haveLower && haveUpper));
+
+  AtomicItem_t& lowerKey = theCondition->theLowerBound;
+  AtomicItem_t& upperKey = theCondition->theUpperBound;
+  store::Item_t lowerAltKey;
+  store::Item_t upperAltKey;
+
+  zstring tmp;
+
+  theMapBegins.clear();
+  theMapEnds.clear();
+
+  if (idx->isTyped())
+  {
+    // Note: the runtime (or compiler) makes sure that each search key is a
+    // subtype of the index key type.
+    probeMap(theIndex->theKeyTypeCode, lowerKey, upperKey);
+  }
+  else if (haveLower || haveUpper)
+  {
+    store::Item_t castItem;
+
+    SchemaTypeCode lowerKeyType = (haveLower ? lowerKey->getTypeCode() : XS_LAST);
+    SchemaTypeCode upperKeyType = (haveUpper ? upperKey->getTypeCode() : XS_LAST);
+
+    SchemaTypeCode keyType = (lowerKeyType < upperKeyType ?
+                              lowerKeyType :
+                              upperKeyType);
+
+    switch (keyType)
+    {
+    case XS_BOOLEAN:
+    case XS_DATETIME:
+    case XS_DATE:
+    case XS_TIME:
+    {
+      probeMap(keyType, lowerKey, upperKey);
+      break;
+    }
+
+    case XS_DURATION:
+    case XS_YM_DURATION:
+    case XS_DT_DURATION:
+    {
+      probeMap(XS_DURATION, lowerKey, upperKey);
+      break;
+    }
+
+    case XS_ANY_URI:
+    {
+      probeMap(XS_ANY_URI, lowerKey, upperKey);
+
+      if (idx->theMaps[XS_STRING])
+      {
+        if (haveLower)
+        {
+          lowerKey->getStringValue2(tmp);
+          GET_FACTORY().createString(lowerAltKey, tmp);
+        }
+
+        if (haveUpper)
+        {
+          upperKey->getStringValue2(tmp);
+          GET_FACTORY().createString(upperAltKey, tmp);
+        }
+        
+        probeMap(XS_STRING, lowerAltKey, upperAltKey);
+      }
+
+      break;
+    }
+
+    case XS_STRING:
+    case XS_NORMALIZED_STRING:
+    case XS_TOKEN:
+    case XS_NMTOKEN:
+    case XS_LANGUAGE:
+    case XS_NAME:
+    case XS_NCNAME:
+    case XS_ID:
+    case XS_IDREF:
+    case XS_ENTITY:
+    {
+      probeMap(XS_STRING, lowerKey, upperKey);
+
+      if (idx->theMaps[XS_ANY_URI])
+      {
+        if (haveLower)
+        {
+          lowerKey->getStringValue2(tmp);
+          GET_FACTORY().createAnyURI(lowerAltKey, tmp);
+        }
+
+        if (haveUpper)
+        {
+          upperKey->getStringValue2(tmp);
+          GET_FACTORY().createAnyURI(upperAltKey, tmp);
+        }
+
+        probeMap(XS_ANY_URI, lowerAltKey, upperAltKey);
+      }
+
+      break;
+    }
+
+    case XS_DOUBLE:
+    case XS_FLOAT:
+    {
+      probeMap(XS_DOUBLE, lowerKey, upperKey);
+
+      if (idx->theMaps[XS_LONG])
+      {
+        if (haveLower)
+          doubleToLongProbe(lowerAltKey, lowerKey, true, false);
+
+        if (haveUpper)
+          doubleToLongProbe(upperAltKey, upperKey, false, true);
+
+        if (haveLower && haveUpper)
+        {
+          if (lowerAltKey && upperAltKey)
+            probeMap(XS_ANY_URI, lowerAltKey, upperAltKey);    
+        }
+        else if ((haveLower && lowerAltKey) || (haveUpper && upperAltKey))
+        {
+          probeMap(XS_ANY_URI, lowerAltKey, upperAltKey);
+        }
+      }
+
+      break;
+    }
+
+    case XS_DECIMAL:
+    case XS_INTEGER:
+    case XS_NON_POSITIVE_INTEGER:
+    case XS_NEGATIVE_INTEGER:
+    case XS_NON_NEGATIVE_INTEGER:
+    case XS_POSITIVE_INTEGER:
+    case XS_UNSIGNED_LONG:
+    {
+      probeMap(XS_DECIMAL, lowerKey, upperKey);
+
+      if (idx->theMaps[XS_LONG])
+      {
+        probeMap(XS_LONG, lowerKey, upperKey);
+      }
+
+      if (idx->theMaps[XS_DOUBLE])
+      {
+        if (haveLower)
+        {
+          xs_double doubleValue = lowerKey->getDecimalValue();
+          GET_FACTORY().createDouble(lowerAltKey, doubleValue);
+        }
+
+        if (haveUpper)
+        {
+          xs_double doubleValue = upperKey->getDecimalValue();
+          GET_FACTORY().createDouble(upperAltKey, doubleValue);
+        }
+
+        probeMap(XS_DOUBLE, lowerAltKey, upperAltKey);
+      }
+
+      break;
+    }
+
+    case XS_LONG:
+    case XS_INT:
+    case XS_SHORT:
+    case XS_BYTE:
+    case XS_UNSIGNED_INT:
+    case XS_UNSIGNED_SHORT:
+    case XS_UNSIGNED_BYTE:
+    {
+      probeMap(XS_LONG, lowerKey, upperKey);
+
+      if (idx->theMaps[XS_DECIMAL])
+      {
+        if (haveLower)
+        {
+          xs_decimal decimalValue = lowerKey->getLongValue();
+          GET_FACTORY().createDecimal(lowerAltKey, decimalValue);
+        }
+
+        if (haveUpper)
+        {
+          xs_decimal decimalValue = upperKey->getLongValue();
+          GET_FACTORY().createDecimal(upperAltKey, decimalValue);
+        }
+
+        probeMap(XS_DECIMAL, lowerAltKey, upperAltKey);
+      }
+
+      if (idx->theMaps[XS_DOUBLE])
+      {
+        if (haveLower)
+        {
+          xs_double doubleValue = lowerKey->getLongValue();
+          GET_FACTORY().createDouble(lowerAltKey, doubleValue);
+        }
+
+        if (haveUpper)
+        {
+          xs_double doubleValue = upperKey->getLongValue();
+          GET_FACTORY().createDouble(upperAltKey, doubleValue);
+        }
+
+        probeMap(XS_DOUBLE, lowerAltKey, upperAltKey);
+      }
+
+      break;
+    }
+
+    case XS_UNTYPED_ATOMIC:
+    {
+      assert(theProbeKind == store::IndexCondition::BOX_GENERAL);
+
+      theIsUntypedProbe = true;
+
+      store::ItemHandle<UntypedAtomicItem> untypedItem = 
+      (haveLower ? 
+       static_cast<UntypedAtomicItem*>(lowerKey.getp()) :
+       static_cast<UntypedAtomicItem*>(upperKey.getp()));
+
+      store::Item_t altKey;
+
+      // cast to xs:string
+      if (idx->theMaps[XS_STRING])
+      {
+        untypedItem->castToString(altKey);
+        probeMap(XS_STRING, altKey, altKey);
+      }
+
+      // cast to xs:anyURI
+      if (idx->theMaps[XS_ANY_URI] && untypedItem->castToUri(altKey))
+      {
+        probeMap(XS_ANY_URI, altKey, altKey);
+      }
+
+      // try casting to xs:long
+      if ((idx->theMaps[XS_LONG] ||
+           idx->theMaps[XS_DOUBLE] ||
+           idx->theMaps[XS_DECIMAL]) &&
+          untypedItem->castToLong(altKey), altKey != NULL)
+      {
+        store::ItemHandle<LongItem> longItem = 
+        static_cast<LongItem*>(altKey.getp());
+
+        if (idx->theMaps[XS_LONG])
+        {
+          probeMap(XS_LONG, altKey, altKey);
+        }
+
+        if (idx->theMaps[XS_DOUBLE])
+        {
+          xs_double doubleValue = longItem->getLongValue();
+          GET_FACTORY().createDouble(altKey, doubleValue);
+          probeMap(XS_DOUBLE, altKey, altKey);
+        }
+
+        if (idx->theMaps[XS_DECIMAL])
+        {
+          xs_decimal decimalValue = longItem->getLongValue();
+          GET_FACTORY().createDecimal(altKey, decimalValue);
+          probeMap(XS_DECIMAL, altKey, altKey);
+        }
+      }
+
+      // try casting to xs:decimal
+      else if ((idx->theMaps[XS_LONG] ||
+                idx->theMaps[XS_DOUBLE] ||
+                idx->theMaps[XS_DECIMAL]) &&
+               untypedItem->castToDecimal(altKey), altKey != NULL)
+      {
+        store::ItemHandle<DecimalItem> decimalItem = 
+        static_cast<DecimalItem*>(altKey.getp());
+
+        if (idx->theMaps[XS_DECIMAL])
+        {
+          probeMap(XS_DECIMAL, altKey, altKey);
+        }
+
+        if (idx->theMaps[XS_LONG])
+        {
+          probeMap(XS_LONG, altKey, altKey);
+        }
+
+        if (idx->theMaps[XS_DOUBLE])
+        {
+          xs_double doubleValue = decimalItem->getDecimalValue();
+          GET_FACTORY().createDouble(altKey, doubleValue);
+          probeMap(XS_DOUBLE, altKey, altKey);
+        }
+      }
+
+      // try casting to xs:double
+      else if ((idx->theMaps[XS_LONG] ||
+               idx->theMaps[XS_DOUBLE]) &&
+               untypedItem->castToDouble(altKey), altKey != NULL)
+      {
+        store::ItemHandle<DoubleItem> doubleItem = 
+        static_cast<DoubleItem*>(altKey.getp());
+
+        if (idx->theMaps[XS_DOUBLE])
+        {
+          probeMap(XS_DOUBLE, altKey, altKey);
+        }
+
+        if (idx->theMaps[XS_LONG])
+        {
+          doubleToLongProbe(altKey, doubleItem.getp(), haveLower, haveUpper);
+
+          if (altKey)
+          {
+            probeMap(XS_LONG, altKey, altKey);
+          }
+        }
+      }
+
+      // try casting to xs:datetime
+      else if (idx->theMaps[XS_DATETIME] && untypedItem->castToDateTime(altKey))
+      {
+        probeMap(XS_DATETIME, altKey, altKey);
+      }
+
+      // try casting to xs:date
+      else if (idx->theMaps[XS_DATE] && untypedItem->castToDate(altKey))
+      {
+        probeMap(XS_DATE, altKey, altKey);
+      }
+
+      // try casting to xs:time
+      else if (idx->theMaps[XS_TIME] && untypedItem->castToTime(altKey))
+      {
+        probeMap(XS_TIME, altKey, altKey);
+      }
+
+      // try casting to xs:duration
+      else if (idx->theMaps[XS_DURATION] && untypedItem->castToDuration(altKey))
+      {
+        probeMap(XS_DURATION, altKey, altKey);
+      }
+
+      break;
+    }
+
+    default:
+      ZORBA_ASSERT(false);
+    }
+  }
+  else
+  {
+    theIsFullProbe = true;
+
+    for (ulong i = 0; i < XS_LAST; ++i)
+    {
+      if (idx->theMaps[i] == NULL)
+        continue;
+
+      theMapBegins.push_back(idx->theMaps[i]->begin());
+      theMapEnds.push_back(idx->theMaps[i]->end());
+    }
+  }
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
+void ProbeGeneralIndexIterator::probeMap(
+    SchemaTypeCode targetMap,
+    const store::Item* key)
+{
+  if (theIndex->isSorted())
+  {
+    static_cast<ProbeGeneralTreeIndexIterator*>(this)->
+    probeMap(static_cast<GeneralTreeIndex*>(theIndex.getp())->theMaps[targetMap],
+             key);
+  }
+  else
+  {
+    static_cast<ProbeGeneralHashIndexIterator*>(this)->
+    probeMap(static_cast<GeneralHashIndex*>(theIndex.getp())->theMaps[targetMap],
+             key);
+  }
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+void ProbeGeneralIndexIterator::probeMap(
+    SchemaTypeCode targetMap,
+    const AtomicItem_t& lowerKey,
+    const AtomicItem_t& upperKey)
+{
+    static_cast<ProbeGeneralTreeIndexIterator*>(this)->
+    probeMap(static_cast<GeneralTreeIndex*>(theIndex.getp())->theMaps[targetMap],
+             lowerKey,
+             upperKey);
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+bool ProbeGeneralIndexIterator::haveMap(SchemaTypeCode targetMap) const
+{
+  if (theIndex->isSorted())
+  {
+    GeneralTreeIndex* idx = static_cast<GeneralTreeIndex*>(theIndex.getp());
+    return (idx->theMaps[targetMap] != NULL);
+  }
+  else
+  {
+    GeneralHashIndex* idx = static_cast<GeneralHashIndex*>(theIndex.getp());
+    return (idx->theMaps[targetMap] != NULL);
+  }
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+void ProbeGeneralIndexIterator::open()
 {
   if (theProbeKind == store::IndexCondition::POINT_VALUE ||
       theProbeKind == store::IndexCondition::POINT_GENERAL)
@@ -2655,13 +1883,12 @@
 
     for (; theResultSetsIte != theResultSetsEnd; ++theResultSetsIte)
     {
-      if (*theResultSetsIte != NULL)
-      {
-        theIte = (*theResultSetsIte)->begin();
-        theEnd = (*theResultSetsIte)->end();
+      assert(*theResultSetsIte != NULL);
+
+      theIte = (*theResultSetsIte)->begin();
+      theEnd = (*theResultSetsIte)->end();
         
-        break;
-      }
+      break;
     }
   }
   else
@@ -2688,7 +1915,7 @@
 /******************************************************************************
 
 ********************************************************************************/
-void ProbeGeneralTreeIndexIterator::reset()
+void ProbeGeneralIndexIterator::reset()
 {
   open();
 }
@@ -2697,7 +1924,7 @@
 /******************************************************************************
 
 ********************************************************************************/
-void ProbeGeneralTreeIndexIterator::close()
+void ProbeGeneralIndexIterator::close()
 {
 }
 
@@ -2705,7 +1932,7 @@
 /******************************************************************************
   TODO : need sync on result vector
 ********************************************************************************/
-bool ProbeGeneralTreeIndexIterator::next(store::Item_t& result)
+bool ProbeGeneralIndexIterator::next(store::Item_t& result)
 {
   if (theProbeKind == store::IndexCondition::POINT_VALUE ||
       theProbeKind == store::IndexCondition::POINT_GENERAL)
@@ -2717,10 +1944,6 @@
         if (theIsUntypedProbe && (*theIte).theUntyped)
         {
           assert(theProbeKind == store::IndexCondition::POINT_GENERAL);
-          // Note: in case of a point value probe, (*theIte).theUntyped implies
-          // that the search key is of type xs:string, or xs:anyURI (otherwise,
-          // an error would have been raised in the initPoint method). As a 
-          // result, we should not skip this node.
 
           ++theIte;
           continue;
@@ -2734,7 +1957,7 @@
 
       ++theResultSetsIte;
 
-      if (theResultSetsIte != theResultSetsEnd && *theResultSetsIte != NULL)
+      if (theResultSetsIte != theResultSetsEnd)
       {
         theIte = (*theResultSetsIte)->begin();
         theEnd = (*theResultSetsIte)->end();
@@ -2789,6 +2012,143 @@
 }
 
 
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  ProbeHashGeneralIndexIterator                                              //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/******************************************************************************
+
+********************************************************************************/
+ProbeGeneralHashIndexIterator::ProbeGeneralHashIndexIterator(
+    const store::Index_t& index) 
+  :
+  ProbeGeneralIndexIterator(index)
+{
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+void ProbeGeneralHashIndexIterator::probeMap(
+    const GeneralHashIndex::IndexMap* targetMap,
+    const store::Item* key)
+{
+  if (targetMap == NULL)
+    return;
+
+  GeneralHashIndex::EntryIterator ite = const_cast<GeneralHashIndex::IndexMap*>
+  (targetMap)->find(const_cast<store::Item*>(key));
+
+  if (ite != targetMap->end())
+  {
+    theResultSets.push_back(NULL);
+    theResultSets[theResultSets.size() - 1] = (*ite).second;
+  }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  ProbeGeneralTreeIndexIterator                                              //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/*******************************************************************************
+
+********************************************************************************/
+ProbeGeneralTreeIndexIterator::ProbeGeneralTreeIndexIterator(
+    const store::Index_t& index) 
+  :
+  ProbeGeneralIndexIterator(index)
+{
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+void ProbeGeneralTreeIndexIterator::probeMap(
+    const GeneralTreeIndex::IndexMap* targetMap,
+    const store::Item* key)
+{
+  if (targetMap == NULL)
+    return;
+
+  GeneralTreeIndex::EntryIterator ite = const_cast<GeneralTreeIndex::IndexMap*>
+  (targetMap)->find(const_cast<store::Item*>(key));
+
+  if (ite != targetMap->end())
+  {
+    theResultSets.push_back(NULL);
+    theResultSets[theResultSets.size() - 1] = (*ite).second;
+  }
+}
+
+
+/******************************************************************************
+  
+********************************************************************************/
+void ProbeGeneralTreeIndexIterator::probeMap(
+    const GeneralTreeIndex::IndexMap* map,
+    const AtomicItem_t& lowerKey,
+    const AtomicItem_t& upperKey)
+{
+  if (map == NULL)
+    return;
+
+  GeneralIndexCondition::RangeFlags& flags = theCondition->theRangeFlags;
+
+  bool haveLower = flags.theHaveLowerBound;
+  bool haveUpper = flags.theHaveUpperBound;
+  bool lowerIncl = flags.theLowerBoundIncl;
+  bool upperIncl = flags.theUpperBoundIncl;
+
+  assert(theProbeKind != store::IndexCondition::BOX_GENERAL ||
+         !(haveLower && haveUpper));
+
+  if (haveLower && haveUpper)
+  {
+    long cmp = lowerKey->compare(upperKey);
+
+    if (cmp > 0)
+      return;
+
+    if (cmp == 0 && (!lowerIncl || !upperIncl))
+      return;
+  }
+
+  if (haveLower)
+  {
+    if (lowerIncl)
+      theMapBegins.push_back(map->lower_bound(lowerKey.getp()));
+    else
+      theMapBegins.push_back(map->upper_bound(lowerKey.getp()));
+  }
+  else
+  {
+    theMapBegins.push_back(map->begin());
+  }
+ 
+  if (haveUpper)
+  {
+    if (upperIncl)
+      theMapEnds.push_back(map->upper_bound(upperKey.getp()));
+    else
+      theMapEnds.push_back(map->lower_bound(upperKey.getp()));
+  }
+  else
+  {
+    theMapEnds.push_back(map->end());
+  }
+}
+
+
+
 } // namespace simplestore
 } // namespace zorba
 /* vim:set et sw=2 ts=2: */

=== modified file 'src/store/naive/simple_index_general.h'
--- src/store/naive/simple_index_general.h	2011-10-04 05:28:07 +0000
+++ src/store/naive/simple_index_general.h	2011-10-13 19:58:25 +0000
@@ -30,8 +30,41 @@
 class AtomicItem;
 
 
+/******************************************************************************
+  Acts as a comparison function for the hash or tree map that implements a
+  general index.
+********************************************************************************/
+class GeneralIndexCompareFunction
+{
+private:
+  long               theTimezone;
+  const XQPCollator* theCollator;
+
+public:
+  GeneralIndexCompareFunction(long timezone, const std::string& collation);
+
+  ~GeneralIndexCompareFunction();
+
+  const XQPCollator* getCollator() const { return theCollator; }
+
+  uint32_t hash(const store::Item_t& key) const;
+
+  bool equal(const store::Item_t& key1, const store::Item_t& key2) const;
+
+  long compare(const store::Item_t& key1, const store::Item_t& key2) const;
+
+  bool operator()(const store::Item_t& key1, const store::Item_t& key2) const
+  {
+    return compare(key1, key2) < 0;
+  }
+};
+
+
 /**************************************************************************//**
-
+  Stores all the domain nodes associated with a key K. For each such node N, a
+  boolean flag is also stored. The flag is true if  K was produced by 
+  casting an untypedAtomic key that was found in the result of the key expr
+  for node N.
 *******************************************************************************/
 class GeneralIndexValue
 {
@@ -50,47 +83,125 @@
 public:
   GeneralIndexValue(ulong size = 0) : theNodes(size) {}
 
-  void addNode(store::Item_t& node, bool multikey, bool untyped);
-
   void clear() { theNodes.clear(); }
 
   const_iterator begin() { return theNodes.begin(); }
 
   const_iterator end()   { return theNodes.end(); }
+
+  void addNode(store::Item_t& node, bool untyped);
 };
 
 
 /******************************************************************************
 
+  theKeyTypeCode:
+  ---------------
+  The type code for the builtin atomic key type (set to XS_LAST if the index
+  is not typed).
+
+  theCompFunction:
+  ----------------
+  An instance of GeneralIndexCompareFunction that acts as a comparison function
+  for the hash or tree map that implements the index.
+
+  theEmptyKeyNodes:
+  -----------------
+  A vector storing all domain nodes for which the key expr returns the empty
+  sequence.
+
+  theUntypedFlag:
+  ---------------
+  Set to true if there is at least one domain node for which the key expression
+  returns an item with type xs:untypedAtomic and that item is sucessfully cast
+  to an item with a type other than xs:string.
+
+  theMultiKeyFlag:
+  ----------------
+  Set to true if there is at least one domain node for which the key expression
+  returns more than one items.
 *******************************************************************************/
 class GeneralIndex : public IndexImpl
 {
-  friend class SimpleStore;
+  friend class IndexImpl;
+  friend class GeneralHashIndex;
+  friend class GeneralTreeIndex;
+  friend class ProbeGeneralIndexIterator;
+  friend class ProbeGeneralTreeIndexIterator;
+
+  typedef std::pair<store::Item*, GeneralIndexValue*> IndexMapPair;
+
+private:
+  static const int64_t        theMaxLong;
+  static const int64_t        theMinLong;
+  static const double         theDoubleMaxLong;
+  static const double         theDoubleMinLong;
 
 protected:
-  IndexCompareFunction        theCompFunction;
+  SchemaTypeCode              theKeyTypeCode;
+
+  GeneralIndexCompareFunction theCompFunction;
+
   std::vector<store::Item_t>  theEmptyKeyNodes;
+
   bool                        theUntypedFlag;
+
   bool                        theMultiKeyFlag;
 
 protected:
-  GeneralIndex(
-      const store::Item_t& qname,
-      const store::IndexSpecification& spec);
+  GeneralIndex(const store::Item_t& name, const store::IndexSpecification& spec);
+
+  virtual ~GeneralIndex();
+
+  bool isTyped() const { return (theKeyTypeCode != XS_LAST); }
+
+  bool insertInMap(
+      store::Item_t& key,
+      store::Item_t& node,
+      SchemaTypeCode targetMap,
+      bool untyped);
+
+  bool probeMap(
+      const store::Item* key,
+      SchemaTypeCode targetMap);
+
+public:
+  const XQPCollator* getCollator(ulong i) const;
+
+  void setMultiKey() { theMultiKeyFlag = true; }
+
+  ulong size() const;
+
+  bool insert(store::Item_t& key, store::Item_t& node);
+
+  virtual bool remove(const store::Item_t& key, store::Item_t& item, bool all) = 0;
 };
 
 
 /******************************************************************************
+  theMaps:
+  --------
+  One hash map for each builtin atomic type T, except from xs:untypedAtomic 
+  and xs:anyAtomicType. TheMaps is indexed by the type code of T.
 
+  theSingleMap:
+  -------------
+  If the keyspec of the index specifies an atomic type T and T is neither
+  xs:untypedAtomic nor xs:anyAtomicType, then theSingleMap points to theMaps
+  entry that corresponds to the builtin base type of T. Otherwise, theSingleMap
+  is NULL.
 *******************************************************************************/
 class GeneralHashIndex : public GeneralIndex
 {
-  friend class SimpleStore;
+  friend class GeneralIndex;
+  friend class ProbeGeneralIndexIterator;
   friend class ProbeGeneralHashIndexIterator;
 
-  typedef HashMap<const store::IndexKey*,
+  typedef HashMap<store::Item*,
                   GeneralIndexValue*,
-                  IndexCompareFunction> IndexMap;
+                  GeneralIndexCompareFunction> IndexMap;
+
+  typedef IndexMap::iterator EntryIterator;
 
   class KeyIterator : public Index::KeyIterator
   {
@@ -108,75 +219,23 @@
   IndexMap  * theMaps[XS_LAST];
   IndexMap  * theSingleMap;
 
+protected:
+  bool insertInMap(
+      store::Item_t& key,
+      store::Item_t& node,
+      IndexMap*& targetMap,
+      bool untyped);
+
 public:
-  ulong size() const;
-
-  Index::KeyIterator_t keys() const;
-
-  bool insert(store::IndexKey*& key, store::Item_t& node, bool multikey);
-
-  bool remove(const store::IndexKey* key, store::Item_t& item, bool all = false);
-
-protected:
   GeneralHashIndex(
-      const store::Item_t& qname,
+      const store::Item_t& name,
       const store::IndexSpecification& spec);
 
   ~GeneralHashIndex();
 
-  bool isTyped() const { return (theSingleMap != NULL); }
-
-  bool insertInMap(
-      store::IndexKey*& key,
-      store::Item_t& node,
-      IndexMap*& targetMap,
-      bool multikey,
-      bool untyped);
-};
-
-
-/******************************************************************************
-  Iterator to probe a hash-based, general index. The probe itself may be a
-  value probe or a general probe.
-
-  theIndex         : The index to probe
-  theCondition     : The condition to satisfy. May be a POINT_VALUE or 
-                      POINT_GENERAL condition.
-  theProbeKind     : 
-
-  theResultSets    : The node sets associated with the keys that match the 
-                     condition
-  theResultSetsIte :
-  theResultSetsEnd :
-********************************************************************************/
-class ProbeGeneralHashIndexIterator : public store::IndexProbeIterator
-{
-protected:
-  rchandle<GeneralHashIndex>                 theIndex;
-
-  rchandle<IndexPointCondition>              theCondition;
-  store::IndexCondition::Kind                theProbeKind;
-
-  bool                                       theIsUntypedProbe;
-
-  std::vector<GeneralIndexValue*>            theResultSets;
-  std::vector<GeneralIndexValue*>::iterator  theResultSetsIte;
-  std::vector<GeneralIndexValue*>::iterator  theResultSetsEnd;
-  GeneralIndexValue::const_iterator          theIte;
-  GeneralIndexValue::const_iterator          theEnd;
-
-public:
-  ProbeGeneralHashIndexIterator(const store::Index_t& index);
-
-  void init(const store::IndexCondition_t& cond);
-
-  void open();
-
-  bool next(store::Item_t& result);
-  
-  void reset();
-
-  void close();
+  Index::KeyIterator_t keys() const;
+
+  bool remove(const store::Item_t& key, store::Item_t& item, bool);
 };
 
 
@@ -185,14 +244,16 @@
 *******************************************************************************/
 class GeneralTreeIndex : public GeneralIndex
 {
-  friend class SimpleStore;
+  friend class GeneralIndex;
+  friend class ProbeGeneralIndexIterator;
   friend class ProbeGeneralTreeIndexIterator;
 
-  typedef std::pair<const store::IndexKey*, GeneralIndexValue*> IndexMapPair;
-
-  typedef std::map<const store::IndexKey*,
+  typedef std::map<store::Item*,
                    GeneralIndexValue*,
-                   IndexCompareFunction> IndexMap;
+                   GeneralIndexCompareFunction> IndexMap;
+
+  typedef IndexMap::const_iterator EntryIterator;
+
 
   class KeyIterator : public Index::KeyIterator
   {
@@ -207,126 +268,152 @@
   typedef rchandle<KeyIterator> KeyIterator_t;
 
 private:
-  static const int64_t  theMaxLong;
-  static const int64_t  theMinLong;
-  static const double   theDoubleMaxLong;
-  static const double   theDoubleMinLong;
-
-private:
   IndexMap       * theMaps[XS_LAST];
   IndexMap       * theSingleMap;
   SYNC_CODE(Mutex  theMapMutex;)
 
+protected:
+  bool insertInMap(
+      store::Item_t& key,
+      store::Item_t& node,
+      IndexMap*& targetMap,
+      bool untyped);
+
 public:
-  ulong size() const;
-
-  Index::KeyIterator_t keys() const;
-
-  bool insert(store::IndexKey*& key, store::Item_t& node, bool multikey);
-
-  bool remove(const store::IndexKey* key, store::Item_t& item, bool all = false);
-
-protected:
   GeneralTreeIndex(
       const store::Item_t& qname,
       const store::IndexSpecification& spec);
 
   ~GeneralTreeIndex();
 
-  bool isTyped() const { return (theSingleMap != NULL); }
+  Index::KeyIterator_t keys() const;
 
-  bool insertInMap(
-      store::IndexKey*& key,
-      store::Item_t& node,
-      IndexMap*& targetMap,
-      bool multikey,
-      bool untyped);
+  bool remove(const store::Item_t& key, store::Item_t& item, bool all);
 };
 
 
 /******************************************************************************
-  Iterator to probe a tree-based, general index. The probe itself may be a
-  value probe or a general probe.
-
-  theIndex         : The index to probe
-  theCondition     : The condition to satisfy. May be a POINT_VALUE, or 
-                      POINT_GENERAL, or BOX_VALUE, or BOX_GENERAL condition.
-  theProbeKind     : 
-
-  theResultSets    : The node sets associated with the keys that match the 
-                     condition. This is used for point probes only.
-  theResultSetsIte : Iterator over theResultSets; points to the "current" result
-                     set. This is used for point probes only.
-  theResultSetsEnd : The "end" iterator of theResultSets. This is used for 
-                     point probes only. 
-
-  theMapBegins     :  A vector that stores an iterator pointing to the 1st 
-                      qualifying entry in each tree that has at least one
-                      qualifying entry. This is used for range probes only.
-  theMapEnds       :  A vector that stores an iterator pointing to the last 
-                      qualifying entry in each tree that has at least one
-                      qualifying entry. This is used for range probes only.
-  theMapIte        :
-
-  theIte           : Iterator over the "current" result set. 
-  theEnd           : The "end" iterator of the "current" result set. 
-
+  Iterator to probe a general index.
+
+  theIndex:
+  ---------
+  The index to probe
+
+  theProbeKind: 
+  --------------
+  The kind of condition to satisfy. May be POINT_VALUE, POINT_GENERAL, BOX_VALUE,
+  or BOX_GENERAL.
+
+  theCondition:
+  -------------
+  The condition to satisfy. 
+
+  theIsUntypedProbe:
+  ------------------
+
+  theIsFullProbe:
+  ---------------
+  Set to true if the condition is a range condition with no bounds. In this case,
+  domain nodes that appear in the index with their associated "untyped" flag set
+  to true must be skipped from the result because they will be just duplicates
+  (they appear for sure in the STRING map). This is used for range probes only.
+ 
+  theResultSets:
+  --------------
+  The node sets associated with the keys that match the condition. This is used
+  for point probes only.
+
+  theResultSetsIte:
+  -----------------
+  Iterator over theResultSets; points to the "current" result set. This is used
+  for point probes only.
+
+  theResultSetsEnd:
+  -----------------
+  The "end" iterator of theResultSets. This is used for point probes only. 
+
+  theMapBegins:
+  -------------
+  A vector that stores an iterator pointing to the 1st qualifying entry in 
+  each tree that has at least one qualifying entry. This is used for range 
+  probes only.
+
+  theMapEnds:
+  -----------
+  A vector that stores an iterator pointing to the last qualifying entry in 
+  each tree that has at least one qualifying entry. This is used for range 
+  probes only.
+
+  theMapIte:
+  ----------
+
+  theIte:
+  -------
+  For iterating over the domain nodes associated with an index key that satisfies
+  the search condition. These domain nodes are returned as results of "this"
+  probe iterator.
+
+  theEnd:
+  -------
+  For marking the end of an iteration over the domain nodes associated with an
+  index key that satisfies the search condition..
 ********************************************************************************/
-class ProbeGeneralTreeIndexIterator : public store::IndexProbeIterator
+class ProbeGeneralIndexIterator : public store::IndexProbeIterator
 {
+  friend class ProbeGeneralHashIndexIterator;
+  friend class ProbeGeneralTreeIndexIterator;
+
   typedef std::vector<GeneralIndexValue*> ResultSets;
 
-  typedef GeneralTreeIndex::IndexMap::const_iterator EntryIterator;
+  typedef GeneralTreeIndex::EntryIterator EntryIterator;
 
   typedef std::vector<EntryIterator> EntryIterators;
 
 protected:
-  rchandle<GeneralTreeIndex>                  theIndex;
-
-  store::IndexCondition::Kind                 theProbeKind;
-  rchandle<IndexPointCondition>               thePointCondition;
-  rchandle<IndexBoxValueCondition>            theBoxValueCondition;
-  rchandle<IndexBoxGeneralCondition>          theBoxGeneralCondition;
-  bool                                        theIsUntypedProbe;
-  bool                                        theIsFullProbe;
-
-  ResultSets                                  theResultSets;
-  ResultSets::const_iterator                  theResultSetsIte;
-  ResultSets::const_iterator                  theResultSetsEnd;
-
-  EntryIterators                              theMapBegins;
-  EntryIterators                              theMapEnds;
-
-  ulong                                       theCurrentMap;
-  EntryIterator                               theMapIte;
-
-  GeneralIndexValue::const_iterator           theIte;
-  GeneralIndexValue::const_iterator           theEnd;
-
-public:
-  ProbeGeneralTreeIndexIterator(const store::Index_t& index);
-
-  void init(const store::IndexCondition_t& cond);
-
-  void open();
-
-  bool next(store::Item_t& result);
-  
-  void reset();
-
-  void close();
+  rchandle<GeneralIndex>                theIndex;
+
+  store::IndexCondition::Kind           theProbeKind;
+
+  rchandle<GeneralIndexCondition>       theCondition;
+
+  bool                                  theIsUntypedProbe;
+
+  bool                                  theIsFullProbe;
+
+  ResultSets                            theResultSets;
+
+  ResultSets::const_iterator            theResultSetsIte;
+
+  ResultSets::const_iterator            theResultSetsEnd;
+
+  EntryIterators                        theMapBegins;
+
+  EntryIterators                        theMapEnds;
+
+  csize                                 theCurrentMap;
+
+  EntryIterator                         theMapIte;
+
+  GeneralIndexValue::const_iterator     theIte;
+  GeneralIndexValue::const_iterator     theEnd;
 
 protected:
-  void initPoint(const store::IndexCondition_t& cond);
-
-  void initValueBox(const store::IndexCondition_t& cond);
-
-  void initGeneralBox(const store::IndexCondition_t& cond);
+  ProbeGeneralIndexIterator(const store::Index_t& index);
+
+  void initPoint();
+
+  void initBox();
+
+  bool haveMap(SchemaTypeCode targetMap) const;
+
+  void probeMap(SchemaTypeCode targetMap, const store::Item* key);
 
   void probeMap(
-      GeneralTreeIndex::IndexMap* map,
-      const store::IndexKey* lowerKey,
-      const store::IndexKey* upperKey);
+      const SchemaTypeCode targetMap,
+      const AtomicItem_t& lowerKey,
+      const AtomicItem_t& upperKey);
+
+  void checkStringKeyType(const AtomicItem* keyItem) const;
 
   void doubleToLongProbe(
       store::Item_t& result,
@@ -334,7 +421,57 @@
       bool haveLower,
       bool haveUpper) const;
 
-  void checkStringKeyType(AtomicItem* keyItem) const;
+public:
+  void init(const store::IndexCondition_t& cond);
+
+  void open();
+
+  void reset();
+
+  void close();
+
+  bool next(store::Item_t& result);
+};
+
+
+/******************************************************************************
+  Iterator to probe a hash-based, general index. The probe itself may be a
+  value probe or a general probe.
+********************************************************************************/
+class ProbeGeneralHashIndexIterator : public ProbeGeneralIndexIterator
+{
+  friend class ProbeGeneralIndexIterator;
+
+protected:
+  void probeMap(
+    const GeneralHashIndex::IndexMap* targetMap,
+    const store::Item* key);
+
+public:
+  ProbeGeneralHashIndexIterator(const store::Index_t& index);
+};
+
+
+/******************************************************************************
+  Iterator to probe a tree-based, general index. The probe itself may be a
+  value probe or a general probe.
+********************************************************************************/
+class ProbeGeneralTreeIndexIterator : public ProbeGeneralIndexIterator
+{
+  friend class ProbeGeneralIndexIterator;
+
+protected:
+  void probeMap(
+      const GeneralTreeIndex::IndexMap* targetMap,
+      const store::Item* key);
+
+  void probeMap(
+      const GeneralTreeIndex::IndexMap* targetMap,
+      const AtomicItem_t& lowerKey,
+      const AtomicItem_t& upperKey);
+
+public:
+  ProbeGeneralTreeIndexIterator(const store::Index_t& index);
 };
 
 

=== modified file 'src/store/naive/simple_index_value.cpp'
--- src/store/naive/simple_index_value.cpp	2011-10-03 15:55:33 +0000
+++ src/store/naive/simple_index_value.cpp	2011-10-13 19:58:25 +0000
@@ -18,9 +18,12 @@
 #include <algorithm>
 
 #include "store/naive/simple_index_value.h"
+
 #include "diagnostics/xquery_diagnostics.h"
 #include "diagnostics/util_macros.h"
 
+#include "zorbatypes/collation_manager.h"
+
 namespace zorba 
 { 
 
@@ -28,6 +31,158 @@
 {
 
 
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  ValueIndexCompareFunction                                                  //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/******************************************************************************
+
+********************************************************************************/
+ValueIndexCompareFunction::ValueIndexCompareFunction(
+     csize numCols,
+     long timezone,
+     const std::vector<std::string>& collations)
+  :
+  theNumColumns(numCols),
+  theTimezone(timezone)
+{
+  theCollators.resize(theNumColumns);
+
+  for (csize i = 0; i < theNumColumns; ++i)
+  {
+    if (!collations[i].empty())
+    {
+      theCollators[i] = CollationFactory::createCollator(collations[i]);
+    }
+    else
+    {
+      theCollators[i] = NULL;
+    }
+  }
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+ValueIndexCompareFunction::~ValueIndexCompareFunction()
+{
+  for (csize i = 0; i < theCollators.size(); ++i)
+  {
+    if (theCollators[i])
+      delete theCollators[i]; 
+  }
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+uint32_t ValueIndexCompareFunction::hash(const store::IndexKey* key) const
+{
+  uint32_t hval = FNV_32_INIT;
+
+  for (csize i = 0; i < theNumColumns; ++i)
+  {
+    if ((*key)[i] == NULL)
+      continue;
+
+    hval = hashfun::h32<uint32_t>((*key)[i]->hash(theTimezone, theCollators[i]),
+                                  hval);
+  }
+
+  return hval;
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+bool ValueIndexCompareFunction::equal(
+    const store::IndexKey* key1,
+    const store::IndexKey* key2) const
+{
+  for (csize i = 0; i < theNumColumns; ++i)
+  {
+    const store::Item_t& i1 = (*key1)[i];
+    const store::Item_t& i2 = (*key2)[i];
+
+    if (i1 == NULL && i2 == NULL)
+      continue;
+
+    if (i1 == NULL || i2 == NULL)
+      return false;
+
+    if (! (*key1)[i]->equals((*key2)[i].getp(), theTimezone, theCollators[i]))
+      return false;
+  }
+
+  return true;
+}
+
+
+/*******************************************************************************
+
+********************************************************************************/
+long ValueIndexCompareFunction::compare(
+    const store::IndexKey* key1,
+    const store::IndexKey* key2) const
+{
+  long result;
+
+  csize size = std::min(key1->size(),  key2->size());
+
+  for (csize i = 0; i < size; i++)
+  {
+    const store::Item_t& i1 = (*key1)[i];
+    const store::Item_t& i2 = (*key2)[i];
+
+    if (i1 == NULL)
+    {
+      if (i2 != NULL)
+        return -1;
+    }
+    else if (i2 == NULL)
+    {
+      if (i1 != NULL)
+        return +1;
+    }
+    else if (i1 == IndexConditionImpl::theNegInf)
+    {
+      return -1;
+    }
+    else if (i1 == IndexConditionImpl::thePosInf)
+    {
+      return +1;
+    }
+    else if (i2 == IndexConditionImpl::theNegInf)
+    {
+      return +1;
+    }
+    else if (i2 == IndexConditionImpl::thePosInf)
+    {
+      return -1;
+    }
+    else if ((result = i1->compare(i2, theTimezone, theCollators[i])))
+    {
+      return result;
+    }
+  }
+
+  return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+//                                                                             //
+//  Value Index                                                                //
+//                                                                             //
+/////////////////////////////////////////////////////////////////////////////////
+
+
 /******************************************************************************
 
 ********************************************************************************/
@@ -35,8 +190,26 @@
     const store::Item_t& qname,
     const store::IndexSpecification& spec)
   :
-  IndexImpl(qname, spec)
-{
+  IndexImpl(qname, spec),
+  theCompFunction(getNumColumns(), spec.theTimezone, spec.theCollations)
+{
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+ValueIndex::~ValueIndex()
+{
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
+const XQPCollator* ValueIndex::getCollator(ulong i) const 
+{
+  return theCompFunction.getCollator(i);
 }
 
 
@@ -108,7 +281,6 @@
     const store::IndexSpecification& spec)
   :
   ValueIndex(qname, spec),
-  theCompFunction(getNumColumns(), spec.theTimezone, theCollators),
   theMap(theCompFunction, 1024, spec.theIsThreadSafe)
 {
 }
@@ -165,10 +337,7 @@
   in the index already, then the key itself is inserted as well. Return true
   if the key was already in the index, false otherwise
 ********************************************************************************/
-bool ValueHashIndex::insert(
-    store::IndexKey*& key,
-    store::Item_t& value,
-    bool multikey)
+bool ValueHashIndex::insert(store::IndexKey*& key, store::Item_t& value)
 {
   if (key->size() != getNumColumns())
   {
@@ -278,21 +447,11 @@
 ********************************************************************************/
 void ProbeValueHashIndexIterator::init(const store::IndexCondition_t& cond)
 {
-  if (cond->getKind() != store::IndexCondition::POINT_VALUE)
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0007_INDEX_UNSUPPORTED_PROBE_CONDITION,
-    ERROR_PARAMS(cond->getKindString(), theIndex->getName()->getStringValue()));
-  }
-
-  theCondition = reinterpret_cast<IndexPointValueCondition*>(cond.getp());
+  theCondition = reinterpret_cast<IndexPointCondition*>(cond.getp());
 
   store::IndexKey* key = &(theCondition->theKey);
 
-  if (key->size() != theIndex->getNumColumns())
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0005_INDEX_PARTIAL_KEY_PROBE,
-    ERROR_PARAMS(key->toString(), theIndex->getName()->getStringValue()));
-  }
+  assert(key->size() == theIndex->getNumColumns());
 
   theIndex->theMap.get(key, theResultSet);
 
@@ -392,7 +551,6 @@
     const store::IndexSpecification& spec)
   :
   ValueIndex(qname, spec),
-  theCompFunction(getNumColumns(), spec.theTimezone, theCollators),
   theMap(theCompFunction)
 {
 }
@@ -446,10 +604,7 @@
 /******************************************************************************
 
 ********************************************************************************/
-bool ValueTreeIndex::insert(
-    store::IndexKey*& key, 
-    store::Item_t& value,
-    bool multikey)
+bool ValueTreeIndex::insert(store::IndexKey*& key, store::Item_t& value)
 {
   if (key->size() != getNumColumns())
   {
@@ -565,7 +720,7 @@
 
   if (cond->getKind() == store::IndexCondition::POINT_VALUE)
   {
-    thePointCond = reinterpret_cast<IndexPointValueCondition*>(cond.getp());
+    thePointCond = reinterpret_cast<IndexPointCondition*>(cond.getp());
 
     initExact();
   }
@@ -585,11 +740,7 @@
 {
   const store::IndexKey& key = thePointCond->theKey;
 
-  if (key.size() != theIndex->getNumColumns())
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0005_INDEX_PARTIAL_KEY_PROBE,
-    ERROR_PARAMS(key.toString(), theIndex->getName()->getStringValue()));
-  }
+  assert(key.size() == theIndex->getNumColumns());
 
   theMapBegin = theIndex->theMap.find(&key);
 
@@ -612,18 +763,7 @@
 {
   ulong numRanges = theBoxCond->numRanges();
 
-  if (numRanges == 0)
-  {
-    theMapBegin = theIndex->theMap.begin();
-    theMapEnd = theIndex->theMap.end();
-    return;
-  }
-
-  if (numRanges > theIndex->getNumColumns())
-  {
-    RAISE_ERROR_NO_LOC(zerr::ZSTR0006_INDEX_INVALID_BOX_PROBE,
-    ERROR_PARAMS(theIndex->getName()->getStringValue(), ZED(BoxCondTooManyColumns)));
-  }
+  assert(numRanges > 0 && numRanges <= theIndex->getNumColumns());
 
   theDoExtraFiltering = (numRanges > 1);
 
@@ -637,7 +777,7 @@
   store::IndexKey& lowerBounds = theBoxCond->theLowerBounds;
   store::IndexKey& upperBounds = theBoxCond->theUpperBounds;
 
-  const std::vector<IndexBoxCondition::RangeFlags>& flags = 
+  const std::vector<IndexConditionImpl::RangeFlags>& flags = 
     theBoxCond->theRangeFlags;
 
   //
@@ -681,13 +821,13 @@
     if (haveLowerBound)
     {
       if (!flags[i].theHaveLowerBound)
-        lowerBounds[i] = IndexBoxCondition::theNegInf;
+        lowerBounds[i] = IndexConditionImpl::theNegInf;
     }
 
     if (haveUpperBound)
     {
       if (!flags[i].theHaveUpperBound)
-        upperBounds[i] = IndexBoxCondition::thePosInf;
+        upperBounds[i] = IndexConditionImpl::thePosInf;
     }
 
     if (flags[i].theHaveLowerBound && flags[i].theHaveUpperBound)
@@ -697,12 +837,8 @@
       if (comp > 0 || 
           (comp == 0 && (!flags[i].theLowerBoundIncl || !flags[i].theUpperBoundIncl)))
       { 
-        throw ZORBA_EXCEPTION(
-          zerr::ZSTR0006_INDEX_INVALID_BOX_PROBE,
-          ERROR_PARAMS(
-            theIndex->getName()->getStringValue(), theBoxCond->toString()
-          )
-        );
+        theMapBegin = theMapEnd = theIndex->theMap.end();
+        return;
       }
     }
   }

=== modified file 'src/store/naive/simple_index_value.h'
--- src/store/naive/simple_index_value.h	2011-06-21 19:23:09 +0000
+++ src/store/naive/simple_index_value.h	2011-10-13 19:58:25 +0000
@@ -25,6 +25,39 @@
 namespace simplestore
 {
 
+/******************************************************************************
+
+********************************************************************************/
+class ValueIndexCompareFunction
+{
+private:
+  csize                       theNumColumns;
+  long                        theTimezone;
+  std::vector<XQPCollator*>   theCollators;
+
+public:
+  ValueIndexCompareFunction(
+       csize numCols,
+       long timezone,
+       const std::vector<std::string>& collation);
+
+  ~ValueIndexCompareFunction();
+
+  const XQPCollator* getCollator(ulong i) const { return theCollators[i]; }
+
+  uint32_t hash(const store::IndexKey* key) const;
+
+  bool equal(const store::IndexKey* key1, const store::IndexKey* key2) const;
+
+  long compare(const store::IndexKey* key1, const store::IndexKey* key2) const;
+
+  bool operator()(const store::IndexKey* key1, const store::IndexKey* key2) const
+  {
+    return compare(key1, key2) < 0;
+  }
+};
+
+
 /**************************************************************************//**
   Class ValueIndexValue represents a value set as a vector of item handles.
 *******************************************************************************/
@@ -43,9 +76,22 @@
   friend class SimpleStore;
 
 protected:
-  ValueIndex(
-        const store::Item_t& qname,
-        const store::IndexSpecification& spec);
+  ValueIndexCompareFunction   theCompFunction;
+
+protected:
+  ValueIndex(const store::Item_t& qname, const store::IndexSpecification& spec);
+
+  virtual ~ValueIndex();
+
+public:
+  const XQPCollator* getCollator(ulong i) const;
+
+  virtual bool insert(store::IndexKey*& key, store::Item_t& item) = 0;
+
+  virtual bool remove(
+        const store::IndexKey* key,
+        store::Item_t& item,
+        bool all = false) = 0;
 };
 
 
@@ -59,7 +105,7 @@
 
   typedef HashMap<const store::IndexKey*,
                   ValueIndexValue*,
-                  IndexCompareFunction> IndexMap;
+                  ValueIndexCompareFunction> IndexMap;
 
 protected:
 
@@ -82,19 +128,7 @@
   typedef rchandle<KeyIterator> KeyIterator_t;
 
 private:
-  IndexCompareFunction   theCompFunction;
-  IndexMap               theMap;
-
-public:
-  void clear();
-
-  ulong size() const;
-
-  Index::KeyIterator_t keys() const;
-
-  bool insert(store::IndexKey*& key, store::Item_t& item, bool multikey = false);
-
-  bool remove(const store::IndexKey* key, store::Item_t& item, bool all);
+  IndexMap  theMap;
 
 protected:
   ValueHashIndex(
@@ -102,6 +136,17 @@
       const store::IndexSpecification& spec);
 
   ~ValueHashIndex();
+
+public:
+  void clear();
+
+  ulong size() const;
+
+  Index::KeyIterator_t keys() const;
+
+  bool insert(store::IndexKey*& key, store::Item_t& item);
+
+  bool remove(const store::IndexKey* key, store::Item_t& item, bool all);
 };
 
 
@@ -113,7 +158,7 @@
 protected:
   rchandle<ValueHashIndex>               theIndex;
 
-  rchandle<IndexPointValueCondition>     theCondition;
+  rchandle<IndexPointCondition>          theCondition;
 
   ValueIndexValue                      * theResultSet;
   ValueIndexValue::const_iterator        theIte;
@@ -149,7 +194,7 @@
 
   typedef std::map<const store::IndexKey*,
                    ValueIndexValue*,
-                   IndexCompareFunction> IndexMap;
+                   ValueIndexCompareFunction> IndexMap;
 
   class KeyIterator : public Index::KeyIterator
   {
@@ -164,20 +209,9 @@
   typedef rchandle<KeyIterator> KeyIterator_t;
 
 private:
-  IndexCompareFunction   theCompFunction;
-  IndexMap               theMap;
-  SYNC_CODE(Mutex        theMapMutex;)
-
-public:
-  void clear();
-
-  ulong size() const;
-
-  Index::KeyIterator_t keys() const;
-
-  bool insert(store::IndexKey*& key, store::Item_t& item, bool multikey = false);
-
-  bool remove(const store::IndexKey* key, store::Item_t& item, bool all = false);
+  IndexMap          theMap;
+
+  SYNC_CODE(Mutex   theMapMutex;)
 
 protected:
   ValueTreeIndex(
@@ -185,6 +219,17 @@
         const store::IndexSpecification& spec);
 
   ~ValueTreeIndex();
+
+public:
+  void clear();
+
+  ulong size() const;
+
+  Index::KeyIterator_t keys() const;
+
+  bool insert(store::IndexKey*& key, store::Item_t& item);
+
+  bool remove(const store::IndexKey* key, store::Item_t& item, bool all = false);
 };
 
 
@@ -196,7 +241,7 @@
 protected:
   rchandle<ValueTreeIndex>                  theIndex;
 
-  rchandle<IndexPointValueCondition>        thePointCond;
+  rchandle<IndexPointCondition>             thePointCond;
   rchandle<IndexBoxValueCondition>          theBoxCond;
 
   bool                                      theDoExtraFiltering;
@@ -209,6 +254,11 @@
   ValueIndexValue::const_iterator           theIte;
   ValueIndexValue::const_iterator           theEnd;
 
+protected:
+  void initExact();
+
+  void initBox();
+
 public:
   ProbeValueTreeIndexIterator(const store::Index_t& index)
     :
@@ -227,11 +277,6 @@
   void reset();
 
   void close();
-
-protected:
-  void initExact();
-
-  void initBox();
 };
 
 

=== modified file 'src/store/naive/simple_pul.cpp'
--- src/store/naive/simple_pul.cpp	2011-10-13 08:12:41 +0000
+++ src/store/naive/simple_pul.cpp	2011-10-13 19:58:25 +0000
@@ -22,7 +22,7 @@
 #include "store/naive/store_defs.h"
 #include "store/naive/simple_store.h"
 #include "store/naive/simple_collection.h"
-#include "store/naive/simple_index.h"
+#include "store/naive/simple_index_value.h"
 #include "store/naive/simple_pul.h"
 #include "store/naive/pul_primitives.h"
 #include "store/naive/node_items.h"
@@ -1953,18 +1953,18 @@
 ********************************************************************************/
 void CollectionPul::refreshIndices()
 {
-  ulong numIncrementalIndices = (ulong)theIncrementalIndices.size();
+  csize numIncrementalIndices = theIncrementalIndices.size();
 
-  for (ulong idx = 0; idx < numIncrementalIndices; ++idx)
+  for (csize idx = 0; idx < numIncrementalIndices; ++idx)
   {
-    IndexImpl* index = theIncrementalIndices[idx];
+    ValueIndex* index = static_cast<ValueIndex*>(theIncrementalIndices[idx]);
 
     //
     // Referesh the index w.r.t. modified docs.
     //
-    IndexCompareFunction keyCmp(index->getNumColumns(),
-                                index->getTimezone(),
-                                index->getCollators());
+    ValueIndexCompareFunction keyCmp(index->getNumColumns(),
+                                     index->getTimezone(),
+                                     index->getCollations());
     
     store::IndexDelta& beforeDelta = theBeforeIndexDeltas[idx];
     store::IndexDelta& afterDelta = theAfterIndexDeltas[idx];

=== modified file 'src/store/naive/simple_store.cpp'
--- src/store/naive/simple_store.cpp	2011-10-10 12:56:57 +0000
+++ src/store/naive/simple_store.cpp	2011-10-13 19:58:25 +0000
@@ -560,7 +560,7 @@
   store::Item_t domainItem;
   store::IndexKey* key = NULL;
 
-  IndexImpl* index = static_cast<IndexImpl*>(aIndex.getp());
+  ValueIndex* index = static_cast<ValueIndex*>(aIndex.getp());
 
   aSourceIter->open();
 
@@ -621,7 +621,6 @@
   store::Item_t domainNode;
   store::Item_t firstKeyItem;
   store::Item_t keyItem;
-  store::IndexKey* key = NULL;
 
   GeneralIndex* index = static_cast<GeneralIndex*>(idx.getp());
 
@@ -634,67 +633,54 @@
       bool more = true;
 
       assert(domainNode->isNode());
+      assert(keyItem == NULL);
 
+      // Compute the keys associated with the current domain node. Note: We
+      // must check whether the domain node has more than one key, before we
+      // do any insertions in the index.
       while (more)
       {
         if (domainNode->getCollection() == NULL && !index->isTemporary())
         {
-          throw ZORBA_EXCEPTION(
-            zerr::ZDDY0020_INDEX_DOMAIN_NODE_NOT_IN_COLLECTION,
-            ERROR_PARAMS( index->getName()->getStringValue() )
-          );
+          RAISE_ERROR_NO_LOC(zerr::ZDDY0020_INDEX_DOMAIN_NODE_NOT_IN_COLLECTION,
+          ERROR_PARAMS(index->getName()->getStringValue()));
         }
 
-        // Compute the keys of the current domain node. We must check whether
-        // the domain node has more than one key, before we do any insertions
-        // in the index.
-
-        if (key == NULL)
-          key = new store::IndexKey(numColumns);
-
         // Compute 1st key, or next domain node
         more = sourceIter->next(firstKeyItem);
 
+        // If current node has no keys, put it in the "null" entry and continue
+        // with the next domain node, if nay.
         if (!more || firstKeyItem->isNode())
         {
-          // Current node has no keys
-          (*key)[0] = NULL;
-          index->insert(key, domainNode, false);
-
-          if (more)
-            domainNode.transfer(firstKeyItem);
-
+          index->insert(keyItem, domainNode);
+
+          domainNode.transfer(firstKeyItem);
           continue;
         }
 
-        // Prepare to insert the 1st key. Note: we have to copy domainNode
-        // rchandle because index->insert() will transfer the given node.
-        store::Item_t node = domainNode;
-        (*key)[0].transfer(firstKeyItem);
-
         // Compute 2nd key, or next domain node
         more = sourceIter->next(keyItem);
 
+        // If current domain node has exactly 1 key, insert it in the index
+        // and continue with next domain node, if any.
         if (!more || keyItem->isNode())
         {
-          // Current domain node has exactly 1 key. So insert it in the
-          // index and continue with next domain node, if any.
-          index->insert(key, node, false);
+          index->insert(firstKeyItem, domainNode);
 
           domainNode.transfer(keyItem);
           continue;
         }
 
         // Current domain node has at least 2 keys. So insert them in the index.
-        index->insert(key, node, true);
-
-        if (key == NULL)
-          key = new store::IndexKey(numColumns);
-
+        // Note: we have to copy the domainNode rchandle because index->insert()
+        // will transfer the given node.
+        index->setMultiKey();
+
+        store::Item_t node = domainNode;
+        index->insert(firstKeyItem, node);
         node = domainNode;
-        (*key)[0].transfer(keyItem);
-
-        index->insert(key, node, true);
+        index->insert(keyItem, node);
 
         // Compute next keys or next domain node.
         while ((more = sourceIter->next(keyItem)))
@@ -705,30 +691,19 @@
             break;
           }
 
-          if (key == NULL)
-            key = new store::IndexKey(numColumns);
-
-          (*key)[0].transfer(keyItem);
           node = domainNode;
-
-          index->insert(key, node);
+          index->insert(keyItem, node);
         }
       }
     }
   }
   catch(...)
   {
-    if (key != NULL)
-      delete key;
-
     sourceIter->close();
 
     throw;
   }
 
-  if (key != NULL)
-    delete key;
-
   sourceIter->close();
 }
 

=== modified file 'test/rbkt/ExpQueryResults/zorba/index/auctions1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/auctions1.xml.res	2011-10-04 05:51:53 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/auctions1.xml.res	2011-10-13 19:58:25 +0000
@@ -148,7 +148,7 @@
 
 Full Probe
 
-<open_auction id="open_auction0"></open_auction><open_auction id="open_auction1"></open_auction><open_auction id="open_auction2"></open_auction><open_auction id="open_auction3"></open_auction><open_auction id="open_auction4"></open_auction><open_auction id="open_auction5"></open_auction><open_auction id="open_auction6"></open_auction><open_auction id="open_auction7"></open_auction><open_auction id="open_auction8"></open_auction><open_auction id="open_auction9"></open_auction><open_auction id="open_auction10"></open_auction><open_auction id="open_auction11"></open_auction>
+<open_auction id="open_auction0"/><open_auction id="open_auction1"/><open_auction id="open_auction2"/><open_auction id="open_auction3"/><open_auction id="open_auction4"/><open_auction id="open_auction5"/><open_auction id="open_auction6"/><open_auction id="open_auction7"/><open_auction id="open_auction8"/><open_auction id="open_auction9"/><open_auction id="open_auction10"/><open_auction id="open_auction11"/>
 
 -------------------------------------------------------
 Probing the untyped AuctionDates2 sorted general index
@@ -192,7 +192,7 @@
 
 probe 3:
 
-<person id="person0" income="55386.86"/><person id="person4" income="9876.00"/><person id="person9" income="57878.50"/><person id="person14" income="53231.89"/>
+<person id="person0" income="55386.86"/><person id="person4" income="9876.00"/><person id="person9" income="57878.50"/><person id="person14" income="53231.89"/><person id="person17" income="9223372036854770178"/>
 
 probe 4:
 
@@ -204,4 +204,4 @@
 
 probe 6 (full probe):
 
-<person id="person0" income="55386.86"/><person id="person3" income="41889.41"/><person id="person4" income="9876.00"/><person id="person9" income="57878.50"/><person id="person10" income="44300.88"/><person id="person11" income="33731.14"/><person id="person12" income="43552.04"/><person id="person13" income="41407.27"/><person id="person14" income="53231.89"/><person id="person16" income="26302.86"/><person id="person18" income="32624.17"/>
+<person id="person0" income="55386.86"/><person id="person3" income="41889.41"/><person id="person4" income="9876.00"/><person id="person9" income="57878.50"/><person id="person10" income="44300.88"/><person id="person11" income="33731.14"/><person id="person12" income="43552.04"/><person id="person13" income="41407.27"/><person id="person14" income="53231.89"/><person id="person16" income="26302.86"/><person id="person17" income="9223372036854770178"/><person id="person18" income="32624.17"/>

=== added file 'test/rbkt/ExpQueryResults/zorba/index/numbers.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/numbers.xml.res	1970-01-01 00:00:00 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/numbers.xml.res	2011-10-13 19:58:25 +0000
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+-------------------------------------
+Probing long keys with a double
+-------------------------------------
+
+probe 1 (eq - hash):
+
+<xs_long num="9223372036854770178"/><xs_long num="9223372036854770688" noloss="t"/><xs_long num="9223372036854770888"/>
+
+probe 2 (eq - hash):
+
+<xs_long num="9223372036854770178"/><xs_long num="9223372036854770688" noloss="t"/><xs_long num="9223372036854770888"/>
+
+probe 3 (gt):
+
+<xs_long num="9223372036854771200"/>
+
+probe 4 (ge):
+
+<xs_long num="9223372036854770178"/><xs_long num="9223372036854770688" noloss="t"/><xs_long num="9223372036854770888"/><xs_long num="9223372036854771200"/>

=== modified file 'test/rbkt/Queries/zorba/index/auctions1.xml'
--- test/rbkt/Queries/zorba/index/auctions1.xml	2011-06-24 19:58:33 +0000
+++ test/rbkt/Queries/zorba/index/auctions1.xml	2011-10-13 19:58:25 +0000
@@ -1123,6 +1123,7 @@
 <emailaddress>mailto:Singleton@xxxxxxxxxxxx</emailaddress>
 <city>Mendocino</city>
 <phone>+0 (735) 97531072</phone>
+<profile income="9223372036854770178"/>
 </person>
 
 

=== modified file 'test/rbkt/Queries/zorba/index/auctions1.xq'
--- test/rbkt/Queries/zorba/index/auctions1.xq	2011-10-04 05:28:07 +0000
+++ test/rbkt/Queries/zorba/index/auctions1.xq	2011-10-13 19:58:25 +0000
@@ -391,7 +391,7 @@
 for $person in index_dml:probe-index-range-value($auctions:PersonIncome2, 
                                                  10000,
                                                  50000,
-                                                 fn:false(),
+                                                 fn:true(),
                                                  fn:false(),
                                                  fn:true(),
                                                  fn:true())

=== added file 'test/rbkt/Queries/zorba/index/numbers.xml'
--- test/rbkt/Queries/zorba/index/numbers.xml	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/numbers.xml	2011-10-13 19:58:25 +0000
@@ -0,0 +1,10 @@
+<?xml version="1.0" standalone="yes"?>
+<numbers>
+<xs_long num="1"/>
+
+<xs_long num="9223372036854770178"/>
+<xs_long num="9223372036854770688" noloss="t"/>
+<xs_long num="9223372036854770888"/>
+
+<xs_long num="9223372036854771200"/>
+</numbers>

=== added file 'test/rbkt/Queries/zorba/index/numbers.xq'
--- test/rbkt/Queries/zorba/index/numbers.xq	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/numbers.xq	2011-10-13 19:58:25 +0000
@@ -0,0 +1,75 @@
+
+import module namespace num = "http://www.w3.org/TestModules/numbers"; at "numbers.xqlib";
+
+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";;
+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+import module namespace iddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";;
+import module namespace idml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";;
+
+
+ddl:create($num:collname);
+
+dml:insert-nodes($num:collname, doc("numbers.xml"));
+
+iddl:create($num:idx-g-h-long);
+iddl:create($num:idx-g-t-long);
+
+"
+-------------------------------------
+Probing long keys with a double
+-------------------------------------
+
+probe 1 (eq - hash):
+
+",
+for $num in idml:probe-index-point-general($num:idx-g-h-long, 
+                                           9223372036854770688E0)
+return $num,
+
+"
+
+probe 2 (eq - hash):
+
+",
+for $num in idml:probe-index-point-general($num:idx-g-h-long, 
+                                           9223372036854770689E0)
+return $num,
+
+"
+
+probe 3 (gt):
+
+",
+for $num in idml:probe-index-range-value($num:idx-g-t-long, 
+                                         9223372036854770178E0,
+                                         0E0,
+                                         fn:true() , fn:false(),
+                                         fn:false(), fn:false())
+return $num,
+
+"
+
+probe 4 (ge):
+
+",
+for $num in idml:probe-index-range-value($num:idx-g-t-long, 
+                                         9223372036854770178E0,
+                                         0E0,
+                                         fn:true() , fn:false(),
+                                         fn:true(), fn:false())
+return $num,
+
+"
+
+"
+
+(:
+,
+for $node in dml:collection(xs:QName("num:numbers"))//xs_long
+where xs:long($node//@num) ge 9223372036854770178E0
+return $node,
+"
+"
+:)
+
+

=== added file 'test/rbkt/Queries/zorba/index/numbers.xqlib'
--- test/rbkt/Queries/zorba/index/numbers.xqlib	1970-01-01 00:00:00 +0000
+++ test/rbkt/Queries/zorba/index/numbers.xqlib	2011-10-13 19:58:25 +0000
@@ -0,0 +1,28 @@
+
+module namespace num = "http://www.w3.org/TestModules/numbers";;
+
+import module namespace ddl = "http://www.zorba-xquery.com/modules/store/static/collections/ddl";;
+import module namespace dml = "http://www.zorba-xquery.com/modules/store/static/collections/dml";;
+import module namespace index_ddl = "http://www.zorba-xquery.com/modules/store/static/indexes/ddl";;
+import module namespace index_dml = "http://www.zorba-xquery.com/modules/store/static/indexes/dml";;
+
+declare namespace ann = "http://www.zorba-xquery.com/annotations";;
+
+
+declare variable $num:collname := xs:QName("num:numbers");
+
+declare variable $num:idx-g-h-long := xs:QName("num:idx-g-h-long");
+declare variable $num:idx-g-t-long := xs:QName("num:idx-g-t-long");
+
+declare collection num:numbers as node()*;
+
+
+declare %ann:general-equality %ann:manual index num:idx-g-h-long
+on nodes dml:collection(xs:QName("num:numbers"))//xs_long
+by xs:long(.//@num);
+
+
+declare %ann:general-range %ann:manual index num:idx-g-t-long
+on nodes dml:collection(xs:QName("num:numbers"))//xs_long
+by xs:long(.//@num);
+


Follow ups