zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #01058
[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
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: noreply, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Zorba Build Bot, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Zorba Build Bot, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Matthias Brantner, 2011-11-01
-
Re: [Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Matthias Brantner, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Zorba Build Bot, 2011-11-01
-
Re: [Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Zorba Build Bot, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Zorba Build Bot, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Zorba Build Bot, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Markos Zaharioudakis, 2011-11-01
-
Re: [Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Markos Zaharioudakis, 2011-11-01
-
Re: [Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Matthias Brantner, 2011-11-01
-
Re: [Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Matthias Brantner, 2011-11-01
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Markos Zaharioudakis, 2011-10-13
-
Re: [Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Markos Zaharioudakis, 2011-10-13
-
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
From: Markos Zaharioudakis, 2011-10-13