zorba-coders team mailing list archive
-
zorba-coders team
-
Mailing list archive
-
Message #00418
[Merge] lp:~markos-za/zorba/indexes into lp:zorba
Markos Zaharioudakis has proposed merging lp:~markos-za/zorba/indexes into lp:zorba.
Requested reviews:
Markos Zaharioudakis (markos-za)
For more details, see:
https://code.launchpad.net/~markos-za/zorba/indexes/+merge/78060
--
https://code.launchpad.net/~markos-za/zorba/indexes/+merge/78060
Your team Zorba Coders is subscribed to branch lp:zorba.
=== modified file 'doc/zorba/xqddf.dox'
--- doc/zorba/xqddf.dox 2011-09-30 03:06:48 +0000
+++ doc/zorba/xqddf.dox 2011-10-04 08:30:40 +0000
@@ -1792,8 +1792,7 @@
Probing an index means retrieving the domain nodes associated with a particular
-search condition, which is either a single key item/tuple, or a "range" of key
-items/tuples. Probing can be done via the xqddf functions
+search condition Probing can be done via the xqddf functions
idml:probe-index-point-value, idml:probe-index-point-general,
idml:probe-index-range-value, or idml:probe-index-range-general.
For each of these functions, the first argument is a QName identifying an index.
@@ -1802,9 +1801,9 @@
of the invoking module; otherwise error <a href="#ERRZDDY0021">zerr:ZDDY0021</a>
or <a href="#ERRZDDY0023">zerr:ZDDY0023</a> is raised,
respectively. All of the functions return their result sorted in document order
-and without duplicate nodes. (For general probes, duplicate node elimination
-is performed as part of the function implementation; for value probes, duplicate
-nodes cannot appear in the result, so no duplicate elimination is needed.)
+and without duplicate nodes.
+
+<strong>idml:probe-index-point-value</strong>
<a name="probe_index_point_value" id="probe_index_point_value"></a>
\code
@@ -1815,33 +1814,36 @@
\endcode
For the probe-index-point-value function, the search condition is specified as a
-number of <strong>search key items</strong> comprising a <strong>search key
-tuple</strong>. A search key item is either an atomic item or the empty sequence.
-The number of search key items must be equal to the number of IndexKeySpecs found
+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
-key item as input). Furthermore, the type of each search key item must match
-the sequence type specified in the corresponding IndexKeyTypeDecl; otherwise,
-a type error is raised [err:XPTY0004].
+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 that
-satisfy the following xquery condition:
+The result of this function is either an error or the set of domain nodes for which
+the following xquery condition returns true:
\code
$key1 eq $node/keyExpr1 and ... and $keyM eq $node/keyExprM
\endcode
where keyExpr<sub>i</sub> is the expression specified in the i-th keyspec
-of the index.
+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 may raise
+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
-the search key item is something other than xs:untypedAtomic, xs:string, or
+any non-empty search key is something other than xs:untypedAtomic, xs:string, or
xs:anyURI (or subtype of these).
+<strong>idml:probe-index-point-general</strong>
+
<a name="probe_index_point_general" id="probe_index_point_general"></a>
\code
idml:probe-index-point-general($indexUri as xs:QName,
@@ -1849,13 +1851,14 @@
\endcode
This method is supported by general indexes only [<a href="#ERRZDDY0029">
-zerr:ZDDY0029</a>]. The search condition is specified as a sequence of
-atomic search key items. If the search sequence is non-empty, the type of each
-atomic item in it must match the atomic type specified by the IndexKeyTypeDecl
-of the index; otherwise, a type error is raised [err:XPTY0004].
+zerr:ZDDY0029</a>]. The search condition is specified as a <strong>search
+sequence</strong> consisting of an arbitrary number of <strong>search keys
+</strong>, where each search key is an atomic item. If the search sequence
+is non-empty, the type of each search key must match the atomic type specified
+by the IndexKeyTypeDecl of the index; otherwise, a type error is raised [err:XPTY0004].
-The result of this function is either an error or the set of domain nodes that
-satisfy the following xquery condition:
+The result of this function is either an error or the set of domain nodes for which
+the following xquery condition returns true:
\code
$keys = $node/keyExpr
@@ -1864,79 +1867,78 @@
where keyExpr is the expression specified in the keyspec of the index.
+<strong>idml:probe-index-range-value</strong>
+
<a name="probe_index_range_value" id="probe_index_range_value"></a>
\code
- probe-index-range-value($indexUri 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,
+ probe-index-range-value($indexUri 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,
....,
- $rangeLowerBoundM as xs:anyAtomicType?,
- $rangeUpperBoundM as xs:anyAtomicType?,
- $rangeHaveLowerBoundM as xs:boolean,
- $rangeHaveupperBoundM as xs:boolean,
- $rangeLowerBoundIncludedM as xs:boolean,
- $rangeupperBoundIncludedM as xs:boolean) as node()*
+ $lowerBoundM as xs:anyAtomicType?,
+ $upperBoundM as xs:anyAtomicType?,
+ $haveLowerBoundM as xs:boolean,
+ $haveUpperBoundM as xs:boolean,
+ $lowerBoundIncludedM as xs:boolean,
+ $upperBoundIncludedM as xs:boolean) as node()*
\endcode
The probe-index-range-value function can be invoked on range indices only
-(value or general) [<a href="#ERRZDDY0026">zerr:ZDDY0026</a>]. To describe the
-semantics of this function, we start by defining the i<sup>th</sup> <strong>key
-column</strong> of an index as the set of key items produced by evaluating the
-i<sup>th</sup> keyspec of the index for every domain node. Then, the search
-condition of a range probe can be defined as a number of
-<strong>rangespecs</strong>, where a rangespec describes a constraint on the
-values of a key column. The first rangespec applies to the first key column, the
-second rangespec to the second key column, etc. The number of rangespecs must be
-less or equal to the number of keyspecs found in the declaration of the given
-index [<a href="#ERRZDDY0025" title="zerr:ZDDY0025">zerr:ZDDY0025</a>]. Each
-rangespec consists of 6 values:
- <ul>
- <li>rangeLowerBound : The lower bound in a range of key values.</li>
- <li>rangeUpperBound : The upper bound in a range of key values.</li>
- <li>rangeHaveLowerBound : If false, then there is no lower bound, or
-equivalently, the lower bound is -INFINITY (the actual rangeLowerBound value is
-ignored). Otherwise, the lower bound is the one given by the rangeLowerBound
-value. The <strong>effective lower bound</strong> of the range is either the
-rangeLowerBound if rangeHaveLowerBound is true, or -INFINITY if
-rangeHaveLowerBound is false.</li>
- <li>rangeHaveUpperBound : If false, then there is no upper bound, or
-equivalently, the upper bound is +INFINITY (the actual rangeUpperBound value is
-ignored). Otherwise, the upper bound is the one given by the rangeUpperBound
-value. The <strong>effective upper bound</strong> of the range is either the
-rangeUpperBound if rangeHaveUpperBound is true, or +INFINITY if
-rangeHaveUpperBound is false.</li>
- <li>rangeLowerBoundIncluded : If false, then the range is open from below,
-i.e., the rangeLowerBound value is not considered part of the range. Otherwise,
-the range is closed from below, i.e., the rangeLowerBound value is part of the
-range.</li>
- <li>rangeUpperBoundIncluded : If false, then the range is open from above,
-i.e., the rangeUpperBound value is not considered part of the range. Otherwise,
-the range is closed from above, i.e., the rangeUpperBound value is part of the
-range.</li>
- </ul>
-
-If the number of rangespecs is less than the number of key columns, then the
-missing rangespecs are assumed to have the following value: [(), (), false,
-false, false, false].
-
-A key tuple K = [k<sub>1</sub>, ..., k<sub>M</sub>] satisfies a range search
-condition if for each i = 1, 2, ..., M the following is true:
-
-effectiveLowerBound<sub>i</sub> lOp k<sub>i</sub> uOp
-effectiveUpperBound<sub>i</sub>
-
-where lOp (uOp) is either the le operator if rangeLowerBoundIncluded<sub>i</sub>
-(rangeUpperBoundIncluded<sub>i</sub>) is true, or the lt operator if
-rangeLowerBoundIncluded<sub>i</sub> (rangeUpperBoundIncluded<sub>i</sub>) is
-false. The index-probe-range function finds all key tuples in the index that
-satisfy the given search condition, creates the union of the domain nodes
-associated with each such key tuple, puts the resulting sequence of nodes in
-document order, and finally returns this sequence to its caller.
-
+(value or general) [<a href="#ERRZDDY0026">zerr:ZDDY0026</a>]. The search
+condition is specified as a number M of <strong>rangespecs</strong>, where
+each rangespec consists of six values. The number M must be greater than
+0 and less than or equal to the number N of keyspecs found in the declaration
+of the given index [<a href="#ERRZDDY0025">zerr:ZDDY0025</a>]. If M is less
+than N, then the "missing" rangespecs are assumed to have the following
+value: [(), (), false, false, false, false]. As a result, from now on, we
+can assume that M is equal to N (Remember that for general indexes, there
+can be only one IndexKeySpec, and as a result, for general indexes, M = N = 1).
+
+The i<sup>th</sup> rangespec corresponds to the i<sup>th</sup> keyspec, and
+specifies a condition on the key values that are produced by evaluating that
+keyspec for every domain node. Specifically, we define the i<sup>th</sup>
+<strong>rangespec result</strong> as the set of domain nodes for which the
+following xquery condition returns true:
+
+\code
+if ($haveLowerBound-i and $haveUpperBound-i) then
+ $lowerBound-i lop $node/keyExpr-i and $node/keyExpr-i uop $upperBound-i
+else if ($haveLowerBound-i) then
+ $lowerBound-i lop $node/keyExpr-i
+else if ($haveUpperBound-i) then
+ $node/keyExpr-i uop $upperBound-i
+else
+ fn:true()
+\endcode
+
+where keyExpr-i is the expression specified by the i<sup>th</sup> keyspec
+of the index, lop is either the le or the lt operator depending on whether
+$lowerBoundsIncluded-i is true or false, and uop is either the le or the
+lt operator depending on whether $upperBoundsIncluded-i is true or false.
+
+In computing the i<sup>th</sup> rangespec result, a type error [err:XPTY0004]
+is raised in the following cases: (a) $haveLowerBound-i is true and
+$lowerBound-i is an atomic item whose type does not match the atomic
+type specified by i<sup>th</sup> keyspec, or (b) $haveUpperBound-i is
+true and $upperBound-i is an atomic item whose type does not match
+the atomic type specified by i<sup>th</sup> keyspec, or (c) the index is general
+and its multi-key flag is true, or (d) the index is general, its untyped flag
+is true, $haveLowerBound-i is true, and $lowerBound-i is
+an atomic item whose type is something other than xs:untypedAtomic, xs:string,
+or xs:anyURI (or subtype of these), or (e) the index is general, its untyped flag
+is true, $haveUpperBound-i is true, and $upperBound-i is
+an atomic item whose type is something other than xs:untypedAtomic, xs:string,
+or xs:anyURI (or subtype of these).
+
+The result of the probe-index-range-value is either one of the errors described
+above, or the intersection of all the rangespec results.
+
+
+<strong>idml:probe-index-range-general</strong>
<a name="probe_index_range_general" id="probe_index_range_general"></a>
\code
=== modified file 'include/zorba/pregenerated/diagnostic_list.h'
--- include/zorba/pregenerated/diagnostic_list.h 2011-10-03 19:38:22 +0000
+++ include/zorba/pregenerated/diagnostic_list.h 2011-10-04 08:30:40 +0000
@@ -592,6 +592,8 @@
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDDY0030_INDEX_RANGE_GENERAL_PROBE_NOT_ALLOWED;
+extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDDY0034_INDEX_RANGE_VALUE_PROBE_BAD_KEY_TYPES;
+
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDDY0031_IC_NOT_DECLARED;
extern ZORBA_DLL_PUBLIC ZorbaErrorCode ZDDY0032_IC_NOT_ACTIVATED;
=== modified file 'modules/com/zorba-xquery/www/modules/pregenerated/errors.xq'
--- modules/com/zorba-xquery/www/modules/pregenerated/errors.xq 2011-08-17 23:04:48 +0000
+++ modules/com/zorba-xquery/www/modules/pregenerated/errors.xq 2011-10-04 08:30:40 +0000
@@ -485,6 +485,10 @@
(:~
:)
+declare variable $zerr:ZDDY0034 as xs:QName := fn:QName($zerr:NS, "zerr:ZDDY0034");
+
+(:~
+:)
declare variable $zerr:ZDDY0031 as xs:QName := fn:QName($zerr:NS, "zerr:ZDDY0031");
(:~
=== modified file 'src/diagnostics/diagnostic_en.xml'
--- src/diagnostics/diagnostic_en.xml 2011-10-03 19:38:22 +0000
+++ src/diagnostics/diagnostic_en.xml 2011-10-04 08:30:40 +0000
@@ -1981,6 +1981,10 @@
<value>"$1": index range-general probe not allowed</value>
</diagnostic>
+ <diagnostic code="ZDDY0034" name="INDEX_RANGE_VALUE_PROBE_BAD_KEY_TYPES">
+ <value>"$1": index range-value probe has search keys with incompatible types</value>
+ </diagnostic>
+
<diagnostic code="ZDDY0031" name="IC_NOT_DECLARED">
<value>"$1": integrity constraint is not declared</value>
</diagnostic>
=== modified file 'src/diagnostics/pregenerated/diagnostic_list.cpp'
--- src/diagnostics/pregenerated/diagnostic_list.cpp 2011-10-03 19:38:22 +0000
+++ src/diagnostics/pregenerated/diagnostic_list.cpp 2011-10-04 08:30:40 +0000
@@ -867,6 +867,9 @@
ZorbaErrorCode ZDDY0030_INDEX_RANGE_GENERAL_PROBE_NOT_ALLOWED( "ZDDY0030" );
+ZorbaErrorCode ZDDY0034_INDEX_RANGE_VALUE_PROBE_BAD_KEY_TYPES( "ZDDY0034" );
+
+
ZorbaErrorCode ZDDY0031_IC_NOT_DECLARED( "ZDDY0031" );
=== modified file 'src/diagnostics/pregenerated/dict_en.cpp'
--- src/diagnostics/pregenerated/dict_en.cpp 2011-10-03 19:38:22 +0000
+++ src/diagnostics/pregenerated/dict_en.cpp 2011-10-04 08:30:40 +0000
@@ -293,6 +293,7 @@
{ "ZDDY0031", "\"$1\": integrity constraint is not declared" },
{ "ZDDY0032", "\"$1\": integrity constraint is not activated" },
{ "ZDDY0033", "\"$1\": integrity constraint not met for collection \"$2\"" },
+ { "ZDDY0034", "\"$1\": index range-value probe has search keys with incompatible types" },
{ "ZDST0001", "\"$1\": collection already declared" },
{ "ZDST0002", "\"$1\": collection already imported into module \"$2\"" },
{ "ZDST0003", "\"$1\": collection declaration not allowed in main module" },
=== modified file 'src/runtime/indexing/index_ddl.cpp'
--- src/runtime/indexing/index_ddl.cpp 2011-10-03 08:49:55 +0000
+++ src/runtime/indexing/index_ddl.cpp 2011-10-04 08:30:40 +0000
@@ -46,6 +46,40 @@
namespace zorba {
+SERIALIZABLE_CLASS_VERSIONS(CreateInternalIndexIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(CreateInternalIndexIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(CreateIndexIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(CreateIndexIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(DeleteIndexIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(DeleteIndexIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(RefreshIndexIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(RefreshIndexIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(ValueIndexEntryBuilderIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(ValueIndexEntryBuilderIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(GeneralIndexEntryBuilderIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(GeneralIndexEntryBuilderIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointValueIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointValueIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointGeneralIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointGeneralIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeValueIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeValueIterator)
+
+SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeGeneralIterator)
+END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeGeneralIterator)
+
+
+/*******************************************************************************
+
+********************************************************************************/
static void checkKeyType(
const QueryLoc& loc,
TypeManager* tm,
@@ -92,41 +126,10 @@
}
-SERIALIZABLE_CLASS_VERSIONS(CreateInternalIndexIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(CreateInternalIndexIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(CreateIndexIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(CreateIndexIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(DeleteIndexIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(DeleteIndexIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(RefreshIndexIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(RefreshIndexIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(ValueIndexEntryBuilderIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(ValueIndexEntryBuilderIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(GeneralIndexEntryBuilderIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(GeneralIndexEntryBuilderIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointValueIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointValueIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointGeneralIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexPointGeneralIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeValueIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeValueIterator)
-
-SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeGeneralIterator)
-END_SERIALIZABLE_CLASS_VERSIONS(ProbeIndexRangeGeneralIterator)
-
-
/*******************************************************************************
********************************************************************************/
-void createIndexSpec(
+static void createIndexSpec(
IndexDecl* indexDecl,
store::IndexSpecification& spec)
{
@@ -624,20 +627,14 @@
if ((state->theIndexDecl = theSctx->lookup_index(qnameItem)) == NULL)
{
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0021_INDEX_NOT_DECLARED,
- ERROR_PARAMS( qnameItem->getStringValue() ),
- ERROR_LOC( loc )
- );
+ RAISE_ERROR(zerr::ZDDY0021_INDEX_NOT_DECLARED, loc,
+ ERROR_PARAMS(qnameItem->getStringValue()));
}
if (state->theIndexDecl->getKeyExpressions().size() != numChildren-1)
{
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0025_INDEX_WRONG_NUMBER_OF_PROBE_ARGS,
- ERROR_PARAMS( qnameItem->getStringValue() ),
- ERROR_LOC( loc )
- );
+ RAISE_ERROR(zerr::ZDDY0025_INDEX_WRONG_NUMBER_OF_PROBE_ARGS, loc,
+ ERROR_PARAMS(qnameItem->getStringValue()));
}
state->theIndex = (state->theIndexDecl->isTemp() ?
@@ -646,11 +643,8 @@
if (state->theIndex == NULL)
{
- throw XQUERY_EXCEPTION(
- zerr::ZDDY0023_INDEX_DOES_NOT_EXIST,
- ERROR_PARAMS( qnameItem->getStringValue() ),
- ERROR_LOC( loc )
- );
+ RAISE_ERROR(zerr::ZDDY0023_INDEX_DOES_NOT_EXIST, loc,
+ ERROR_PARAMS(qnameItem->getStringValue()));
}
state->theIterator = GENV_STORE.getIteratorFactory()->
@@ -951,6 +945,8 @@
store::IndexCondition_t cond;
ulong numChildren = (ulong)theChildren.size();
bool status;
+ TypeManager* tm = theSctx->get_typemanager();
+ RootTypeManager& rtm = GENV_TYPESYSTEM;
ProbeIndexRangeValueIteratorState* state;
DEFAULT_STACK_INIT(ProbeIndexRangeValueIteratorState, state, planState);
@@ -1046,6 +1042,47 @@
checkKeyType(loc, theSctx->get_typemanager(), indexDecl, keyNo, tempRight);
}
+ if (indexDecl->isGeneral() &&
+ (indexDecl->getKeyTypes())[keyNo] == NULL)
+ {
+ xqtref_t leftType;
+ xqtref_t rightType;
+
+ if (tempLeft != NULL)
+ {
+ leftType = tm->create_value_type(tempLeft);
+
+ if (TypeOps::is_equal(tm, *leftType, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
+ {
+ zstring str = tempLeft->getStringValue();
+ GENV_ITEMFACTORY->createString(tempLeft, str);
+ leftType = rtm.STRING_TYPE_ONE;
+ }
+ }
+
+ if (tempRight != NULL)
+ {
+ rightType = tm->create_value_type(tempRight);
+
+ if (TypeOps::is_equal(tm, *rightType, *rtm.UNTYPED_ATOMIC_TYPE_ONE))
+ {
+ zstring str = tempRight->getStringValue();
+ GENV_ITEMFACTORY->createString(tempRight, str);
+ rightType = rtm.STRING_TYPE_ONE;
+ }
+ }
+
+ if (leftType != NULL && rightType != NULL)
+ {
+ if (!TypeOps::is_subtype(tm, *leftType, *rightType) &&
+ !TypeOps::is_subtype(tm, *rightType, *leftType))
+ {
+ RAISE_ERROR(zerr::ZDDY0034_INDEX_RANGE_VALUE_PROBE_BAD_KEY_TYPES, loc,
+ ERROR_PARAMS(qname->getStringValue()));
+ }
+ }
+ }
+
cond->pushRange(tempLeft, tempRight, haveLeft, haveRight, inclLeft, inclRight);
}
@@ -1255,6 +1292,7 @@
//
// Build hashmap from the nodes satisfying the lower bound condition
//
+
if (!getSearchItems(planState, state, true, false, inclLower, false))
goto done;
@@ -1291,6 +1329,7 @@
// Compute the nodes satisfying the upper bound condition and probe the
// node hashmap.
//
+
if (!getSearchItems(planState, state, false, true, false, inclUpper))
goto done;
=== modified file 'src/store/api/index.h'
--- src/store/api/index.h 2011-07-06 19:19:49 +0000
+++ src/store/api/index.h 2011-10-04 08:30:40 +0000
@@ -177,8 +177,9 @@
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.
+ (a) op? is one of <, <=, >, or >=,
+ (b) K is a key value, and
+ (c) bound is either an atomic item or -INFINITY or +INFINITY.
********************************************************************************/
class IndexCondition : public SimpleRCObject
=== modified file 'src/store/api/item.h'
--- src/store/api/item.h 2011-08-23 23:18:43 +0000
+++ src/store/api/item.h 2011-10-04 08:30:40 +0000
@@ -241,7 +241,7 @@
/**
* @return If this is an atomic item with a user-defined data type UT, return
* the underlying atomic item that stores the actual value and whose
- * data type is a builtin atomic supertype of UT.
+ * data type is a builtin atomic supertype of UT. Otherwise, return NULL.
*/
virtual store::Item* getBaseItem() const;
=== modified file 'src/store/naive/atomic_items.cpp'
--- src/store/naive/atomic_items.cpp 2011-08-26 04:19:57 +0000
+++ src/store/naive/atomic_items.cpp 2011-10-04 08:30:40 +0000
@@ -88,17 +88,21 @@
result = NULL;
- switch (getTypeCode())
+ const AtomicItem* item1 = static_cast<AtomicItem*>(getBaseItem());
+ if (item1 == NULL)
+ item1 = this;
+
+ switch (item1->getTypeCode())
{
case XS_UNTYPED_ATOMIC:
{
- const UntypedAtomicItem* item = static_cast<const UntypedAtomicItem*>(this);
+ const UntypedAtomicItem* item = static_cast<const UntypedAtomicItem*>(item1);
try
{
longValue = ztd::aton<xs_long>(item->theValue.c_str());
GET_FACTORY().createLong(result, longValue);
}
- catch ( std::exception const& )
+ catch (std::exception const&)
{
// ignore
}
@@ -108,7 +112,7 @@
case XS_DOUBLE:
case XS_FLOAT:
{
- double doubleValue = getDoubleValue().getNumber();
+ double doubleValue = item1->getDoubleValue().getNumber();
longValue = static_cast<xs_long>(doubleValue);
if (doubleValue == static_cast<double>(longValue))
@@ -119,13 +123,13 @@
case XS_DECIMAL:
{
- const DecimalItem* item = static_cast<const DecimalItem*>(this);
+ const DecimalItem* item = static_cast<const DecimalItem*>(item1);
try
{
longValue = to_xs_long(item->theValue);
GET_FACTORY().createLong(result, longValue);
}
- catch ( std::range_error const& )
+ catch (std::range_error const&)
{
// ignore
}
@@ -138,13 +142,13 @@
case XS_NON_NEGATIVE_INTEGER:
case XS_POSITIVE_INTEGER:
{
- const IntegerItem* item = static_cast<const IntegerItem*>(this);
+ const IntegerItem* item = static_cast<const IntegerItem*>(item1);
try
{
- longValue = to_xs_long( item->theValue );
+ longValue = to_xs_long(item->theValue);
GET_FACTORY().createLong(result, longValue);
}
- catch ( std::range_error const& )
+ catch (std::range_error const&)
{
// ignore
}
@@ -153,7 +157,7 @@
case XS_UNSIGNED_LONG:
{
- const UnsignedLongItem* item = static_cast<const UnsignedLongItem*>(this);
+ const UnsignedLongItem* item = static_cast<const UnsignedLongItem*>(item1);
if ((item->theValue >> 63) == 0)
{
longValue = static_cast<xs_long>(item->theValue);
@@ -185,11 +189,15 @@
result = NULL;
- switch (getTypeCode())
+ const AtomicItem* item1 = static_cast<AtomicItem*>(getBaseItem());
+ if (item1 == NULL)
+ item1 = this;
+
+ switch (item1->getTypeCode())
{
case XS_DECIMAL:
{
- const DecimalItem* item = static_cast<const DecimalItem*>(this);
+ const DecimalItem* item = static_cast<const DecimalItem*>(item1);
doubleValue = item->theValue;
@@ -205,7 +213,7 @@
case XS_NON_NEGATIVE_INTEGER:
case XS_POSITIVE_INTEGER:
{
- const IntegerItem* item = static_cast<const IntegerItem*>(this);
+ const IntegerItem* item = static_cast<const IntegerItem*>(item1);
doubleValue = item->theValue;
@@ -217,7 +225,7 @@
case XS_UNSIGNED_LONG:
{
- const UnsignedLongItem* item = static_cast<const UnsignedLongItem*>(this);
+ const UnsignedLongItem* item = static_cast<const UnsignedLongItem*>(item1);
doubleValue = item->theValue;
@@ -238,7 +246,7 @@
case XS_LONG:
{
- const LongItem* item = static_cast<const LongItem*>(this);
+ const LongItem* item = static_cast<const LongItem*>(item1);
doubleValue = item->theValue;
@@ -252,7 +260,7 @@
case XS_SHORT:
case XS_BYTE:
{
- doubleValue = getIntValue();
+ doubleValue = item1->getIntValue();
lossy = false;
break;
}
@@ -351,6 +359,22 @@
/*******************************************************************************
+ class UserTypedAtomicItem
+********************************************************************************/
+store::Item* UserTypedAtomicItem::getBaseItem() const
+{
+ store::Item* baseItem = theBaseItem.getp();
+
+ while (baseItem->getBaseItem() != NULL)
+ {
+ baseItem = baseItem->getBaseItem();
+ }
+
+ return baseItem;
+}
+
+
+/*******************************************************************************
class UntypedAtomicItem
********************************************************************************/
bool UntypedAtomicItem::castToUri(store::Item_t& result) const
=== modified file 'src/store/naive/atomic_items.h'
--- src/store/naive/atomic_items.h 2011-08-23 23:18:43 +0000
+++ src/store/naive/atomic_items.h 2011-10-04 08:30:40 +0000
@@ -110,7 +110,7 @@
UserTypedAtomicItem() {}
public:
- store::Item* getBaseItem() const { return theBaseItem.getp(); }
+ store::Item* getBaseItem() const;
SchemaTypeCode getTypeCode() const { return theBaseItem->getTypeCode(); }
=== modified file 'src/store/naive/simple_index.cpp'
--- src/store/naive/simple_index.cpp 2011-07-01 23:48:40 +0000
+++ src/store/naive/simple_index.cpp 2011-10-04 08:30:40 +0000
@@ -331,6 +331,30 @@
}
+/*******************************************************************************
+
+********************************************************************************/
+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 //
@@ -374,15 +398,6 @@
}
-void IndexBoxValueCondition::pushBound(
- store::Item_t& bound,
- bool isLower,
- bool boundIncl)
-{
- ZORBA_ASSERT(false);
-}
-
-
/*******************************************************************************
********************************************************************************/
@@ -509,21 +524,6 @@
/*******************************************************************************
********************************************************************************/
-void IndexBoxGeneralCondition::pushRange(
- store::Item_t& lower,
- store::Item_t& upper,
- bool haveLower,
- bool haveUpper,
- bool lowerIncl,
- bool upperIncl)
-{
- ZORBA_ASSERT(false);
-}
-
-
-/*******************************************************************************
-
-********************************************************************************/
void IndexBoxGeneralCondition::pushBound(
store::Item_t& bound,
bool isLower,
@@ -545,6 +545,7 @@
********************************************************************************/
bool IndexBoxGeneralCondition::test(const store::IndexKey& key) const
{
+ ZORBA_ASSERT(false);
return true;
}
=== modified file 'src/store/naive/simple_index.h'
--- src/store/naive/simple_index.h 2011-06-29 16:38:22 +0000
+++ src/store/naive/simple_index.h 2011-10-04 08:30:40 +0000
@@ -241,16 +241,37 @@
IndexBoxCondition(IndexImpl* idx) : theIndex(idx) { }
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);
+
+ virtual void pushBound(store::Item_t& bound, bool isLower, bool boundIncl);
};
/*******************************************************************************
-
+ It represents a condition that is satisfied by the index keys inside a
+ user-specified "box".
+
+ Let M be the number of key columns. Then, an M-dimensional box is defined as
+ a conjuction of M range conditions on columns 0 to M-1. Each range condition
+ specifies a range of acceptable values for some key column. Specifically, a
+ range is defined as the set of all key values K such that
+
+ lower_bound <? K <? upper_bound, where <? is either the lt or the le operator.
+
+ The lower bound may be -INFINITY and the upper bound may be +INFINTY.
********************************************************************************/
class IndexBoxValueCondition : public IndexBoxCondition
{
friend class ValueTreeIndex;
friend class ProbeValueTreeIndexIterator;
+ friend class ProbeGeneralTreeIndexIterator;
friend std::ostream& operator<<(std::ostream& os, const IndexBoxValueCondition& c);
@@ -278,8 +299,6 @@
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;
@@ -290,7 +309,23 @@
/*******************************************************************************
-
+ 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
{
@@ -312,14 +347,6 @@
void clear();
- 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;
=== modified file 'src/store/naive/simple_index_general.cpp'
--- src/store/naive/simple_index_general.cpp 2011-07-29 06:13:28 +0000
+++ src/store/naive/simple_index_general.cpp 2011-10-04 08:30:40 +0000
@@ -1415,32 +1415,65 @@
return true;
}
+
+/******************************************************************************
+
+*******************************************************************************/
ulong GeneralTreeIndex::size() const
{
return 0;
}
+
+/******************************************************************************
+
+*******************************************************************************/
+store::Index::KeyIterator_t GeneralTreeIndex::keys() const
+{
+ return 0;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+// //
+// GeneralTreeIndex::KeyIterator //
+// //
+/////////////////////////////////////////////////////////////////////////////////
+
+
+/******************************************************************************
+
+*******************************************************************************/
+GeneralTreeIndex::KeyIterator::~KeyIterator()
+{
+}
+
+
+/******************************************************************************
+
+*******************************************************************************/
void GeneralTreeIndex::KeyIterator::open()
{
}
+
+/******************************************************************************
+
+*******************************************************************************/
bool GeneralTreeIndex::KeyIterator::next(store::IndexKey&)
{
return false;
}
+
+/******************************************************************************
+
+*******************************************************************************/
void GeneralTreeIndex::KeyIterator::close()
{
}
-GeneralTreeIndex::KeyIterator::~KeyIterator()
-{
-}
-store::Index::KeyIterator_t GeneralTreeIndex::keys() const
-{
- return 0;
-}
/////////////////////////////////////////////////////////////////////////////////
// //
@@ -1452,8 +1485,26 @@
/////////////////////////////////////////////////////////////////////////////////
+#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; \
+}
+
+
/******************************************************************************
- Create an
+
********************************************************************************/
ProbeGeneralTreeIndexIterator::ProbeGeneralTreeIndexIterator(
const store::Index_t& index)
@@ -1470,6 +1521,36 @@
/******************************************************************************
********************************************************************************/
+void ProbeGeneralTreeIndexIterator::checkStringKeyType(AtomicItem* keyItem) const
+{
+ if (keyItem == NULL)
+ return;
+
+ 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()));
+ }
+}
+
+
+/******************************************************************************
+
+********************************************************************************/
void ProbeGeneralTreeIndexIterator::init(const store::IndexCondition_t& cond)
{
theProbeKind = cond->getKind();
@@ -1490,24 +1571,6 @@
}
-#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; \
-}
-
-
/******************************************************************************
********************************************************************************/
@@ -1515,12 +1578,17 @@
{
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())
{
- RAISE_ERROR_NO_LOC(zerr::ZSTR0005_INDEX_PARTIAL_KEY_PROBE,
- ERROR_PARAMS(key->toString(), theIndex->getName()->getStringValue()));
+ ZORBA_ASSERT(false);
}
if (theProbeKind == store::IndexCondition::POINT_VALUE)
@@ -1535,29 +1603,7 @@
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()));
- }
+ checkStringKeyType(keyItem);
}
}
@@ -1568,9 +1614,6 @@
if (theIndex->isTyped())
{
- // Note: the runtime (or compiler) makes sure that the search key is a
- // subtype of the index key type.
-
ite = theIndex->theSingleMap->find(key);
if (ite != theIndex->theSingleMap->end())
@@ -1714,6 +1757,8 @@
case XS_UNTYPED_ATOMIC:
{
+ ZORBA_ASSERT(theProbeKind == store::IndexCondition::POINT_GENERAL);
+
theIsUntypedProbe = true;
store::ItemHandle<UntypedAtomicItem> untypedItem =
@@ -1831,88 +1876,221 @@
void ProbeGeneralTreeIndexIterator::initValueBox(
const store::IndexCondition_t& cond)
{
-#if 0
- theBoxCondition = reinterpret_cast<IndexBoxCondition*>(cond.getp());
-
- long timezone = theIndex->getTimezone();
-
- bool haveLowerBound = true;
- bool haveUpperBound = true;
- bool lowIncl = true;
- bool highIncl = true;
-
- ulong numRanges = theBoxCond->numRanges();
+ 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)
{
- haveLowerBound = false;
- haveUpperBound = false;
- }
-
- if (numRanges > theIndex->getNumColumns())
- {
- ZORBA_ERROR_PARAM(ZSTR0006_INDEX_INVALID_BOX_PROBE,
- theIndex->getName()->getStringValue().c_str(),
- "The box condition has more columns than the index");
- }
-
- store::IndexKey& lowerBounds = theBoxCondition->theLowerBounds;
- store::IndexKey& upperBounds = theBoxCondition->theUpperBounds;
-
- RangeFlags& rangeFlags = theBoxCondition->theRangeFlags[0];
-#endif
+ ZORBA_ASSERT(false);
+ }
+
+ if (theIndex->theMultiKeyFlag)
+ {
+ RAISE_ERROR_NO_LOC(err::XPTY0004,
+ ERROR_PARAMS(ZED(NoMultiKeyNodeValues_2),
+ theIndex->getName()->getStringValue()));
+ }
+
+ 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, &aupperAltKey);
+ }
+
+ 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);
+
+
+ }
+
+ 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* key)
+ const store::IndexKey* lowerKey,
+ const store::IndexKey* upperKey)
{
if (map == NULL)
return;
- bool haveLower = theBoxGeneralCondition->theRangeFlags.theHaveLowerBound;
- bool haveUpper = theBoxGeneralCondition->theRangeFlags.theHaveUpperBound;
- bool lowerIncl = theBoxGeneralCondition->theRangeFlags.theLowerBoundIncl;
- bool upperIncl = theBoxGeneralCondition->theRangeFlags.theUpperBoundIncl;
-
- if (haveLower && haveUpper)
- {
- if (lowerIncl)
- theMapBegins.push_back(map->lower_bound(key));
- else
- theMapBegins.push_back(map->upper_bound(key));
-
- if (upperIncl)
- theMapEnds.push_back(map->upper_bound(key));
- else
- theMapEnds.push_back(map->lower_bound(key));
- }
- else if (haveLower)
- {
- theMapEnds.push_back(map->end());
-
- if (lowerIncl)
- theMapBegins.push_back(map->lower_bound(key));
- else
- theMapBegins.push_back(map->upper_bound(key));
- }
- else if (haveUpper)
- {
- theMapBegins.push_back(map->begin());
-
- if (upperIncl)
- theMapEnds.push_back(map->upper_bound(key));
- else
- theMapEnds.push_back(map->lower_bound(key));
- }
- else
- {
- theMapBegins.push_back(map->begin());
+ 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)
+ {
+ 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());
}
}
@@ -1998,8 +2176,6 @@
bool haveLower = theBoxGeneralCondition->theRangeFlags.theHaveLowerBound;
bool haveUpper = theBoxGeneralCondition->theRangeFlags.theHaveUpperBound;
- //bool lowerIncl = theBoxGeneralCondition->theRangeFlags.theLowerBoundIncl;
- //bool upperIncl = theBoxGeneralCondition->theRangeFlags.theUpperBoundIncl;
theMapBegins.clear();
theMapEnds.clear();
@@ -2010,12 +2186,10 @@
{
// Note: the runtime (or compiler) makes sure that the search key is a
// subtype of the index key type.
-
- probeMap(theIndex->theSingleMap, key);
+ probeMap(theIndex->theSingleMap, key, key);
}
else if (haveLower || haveUpper)
{
- //bool lossy;
store::Item_t castItem;
store::IndexKey altKey(1);
@@ -2036,7 +2210,7 @@
case XS_DATE:
case XS_TIME:
{
- probeMap(theIndex->theMaps[keyType], key);
+ probeMap(theIndex->theMaps[keyType], key, key);
break;
}
@@ -2044,23 +2218,23 @@
case XS_YM_DURATION:
case XS_DT_DURATION:
{
- probeMap(theIndex->theMaps[XS_DURATION], key);
+ probeMap(theIndex->theMaps[XS_DURATION], key, key);
break;
}
case XS_ANY_URI:
{
- probeMap(theIndex->theMaps[XS_ANY_URI], key);
+ probeMap(theIndex->theMaps[XS_ANY_URI], key, key);
if (theIndex->theMaps[XS_STRING])
{
zstring tmp;
keyItem->getStringValue2(tmp);
- GET_FACTORY().createAnyURI(castItem, tmp);
+ GET_FACTORY().createString(castItem, tmp);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_STRING], &altKey);
+ probeMap(theIndex->theMaps[XS_STRING], &altKey, &altKey);
}
break;
@@ -2077,7 +2251,7 @@
case XS_IDREF:
case XS_ENTITY:
{
- probeMap(theIndex->theMaps[XS_STRING], key);
+ probeMap(theIndex->theMaps[XS_STRING], key, key);
if (theIndex->theMaps[XS_ANY_URI])
{
@@ -2087,7 +2261,7 @@
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_ANY_URI], &altKey);
+ probeMap(theIndex->theMaps[XS_ANY_URI], &altKey, &altKey);
}
break;
@@ -2096,7 +2270,7 @@
case XS_DOUBLE:
case XS_FLOAT:
{
- probeMap(theIndex->theMaps[XS_DOUBLE], key);
+ probeMap(theIndex->theMaps[XS_DOUBLE], key, key);
if (theIndex->theMaps[XS_LONG])
{
@@ -2105,7 +2279,7 @@
if (castItem)
{
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_LONG], &altKey);
+ probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
}
}
@@ -2120,12 +2294,12 @@
case XS_POSITIVE_INTEGER:
case XS_UNSIGNED_LONG:
{
- probeMap(theIndex->theMaps[XS_DECIMAL], key);
+ probeMap(theIndex->theMaps[XS_DECIMAL], key, key);
if (theIndex->theMaps[XS_LONG])
{
altKey[0] = keyItem;
- probeMap(theIndex->theMaps[XS_LONG], &altKey);
+ probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
}
if (theIndex->theMaps[XS_DOUBLE])
@@ -2133,7 +2307,7 @@
xs_double doubleValue = keyItem->getDecimalValue();
GET_FACTORY().createDouble(castItem, doubleValue);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DOUBLE], &altKey);
+ probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
}
break;
@@ -2147,14 +2321,14 @@
case XS_UNSIGNED_SHORT:
case XS_UNSIGNED_BYTE:
{
- probeMap(theIndex->theMaps[XS_LONG], key);
+ 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);
+ probeMap(theIndex->theMaps[XS_DECIMAL], &altKey, &altKey);
}
if (theIndex->theMaps[XS_DOUBLE])
@@ -2162,7 +2336,7 @@
xs_double doubleValue = keyItem->getLongValue();
GET_FACTORY().createDouble(castItem, doubleValue);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DOUBLE], &altKey);
+ probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
}
break;
@@ -2180,14 +2354,14 @@
{
untypedItem->castToString(castItem);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_STRING], &altKey);
+ 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);
+ probeMap(theIndex->theMaps[XS_ANY_URI], &altKey, &altKey);
}
// try casting to xs:long
@@ -2202,7 +2376,7 @@
if (theIndex->theMaps[XS_LONG])
{
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_LONG], &altKey);
+ probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
}
if (theIndex->theMaps[XS_DOUBLE])
@@ -2210,7 +2384,7 @@
xs_double doubleValue = longItem->getLongValue();
GET_FACTORY().createDouble(castItem, doubleValue);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DOUBLE], &altKey);
+ probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
}
if (theIndex->theMaps[XS_DECIMAL])
@@ -2218,7 +2392,7 @@
xs_decimal decimalValue = longItem->getLongValue();
GET_FACTORY().createDecimal(castItem, decimalValue);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DECIMAL], &altKey);
+ probeMap(theIndex->theMaps[XS_DECIMAL], &altKey, &altKey);
}
}
@@ -2234,12 +2408,12 @@
if (theIndex->theMaps[XS_DECIMAL])
{
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DECIMAL], &altKey);
+ probeMap(theIndex->theMaps[XS_DECIMAL], &altKey, &altKey);
if (theIndex->theMaps[XS_LONG])
{
altKey[0] = decimalItem;
- probeMap(theIndex->theMaps[XS_LONG], &altKey);
+ probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
}
if (theIndex->theMaps[XS_DOUBLE])
@@ -2247,7 +2421,7 @@
xs_double doubleValue = decimalItem->getDecimalValue();
GET_FACTORY().createDouble(castItem, doubleValue);
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DOUBLE], &altKey);
+ probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
}
}
}
@@ -2263,7 +2437,7 @@
if (theIndex->theMaps[XS_DOUBLE])
{
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DOUBLE], &altKey);
+ probeMap(theIndex->theMaps[XS_DOUBLE], &altKey, &altKey);
}
if (theIndex->theMaps[XS_LONG])
@@ -2273,7 +2447,7 @@
if (castItem)
{
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_LONG], &altKey);
+ probeMap(theIndex->theMaps[XS_LONG], &altKey, &altKey);
}
}
}
@@ -2282,28 +2456,28 @@
else if (theIndex->theMaps[XS_DATETIME] && untypedItem->castToDateTime(castItem))
{
altKey[0].transfer(castItem);
- probeMap(theIndex->theMaps[XS_DATETIME], &altKey);
+ 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);
+ 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);
+ 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);
+ probeMap(theIndex->theMaps[XS_DURATION], &altKey, &altKey);
}
break;
@@ -2403,6 +2577,12 @@
{
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;
}
=== modified file 'src/store/naive/simple_index_general.h'
--- src/store/naive/simple_index_general.h 2011-07-06 19:19:49 +0000
+++ src/store/naive/simple_index_general.h 2011-10-04 08:30:40 +0000
@@ -285,6 +285,7 @@
store::IndexCondition::Kind theProbeKind;
rchandle<IndexPointCondition> thePointCondition;
+ rchandle<IndexBoxValueCondition> theBoxValueCondition;
rchandle<IndexBoxGeneralCondition> theBoxGeneralCondition;
bool theIsUntypedProbe;
@@ -321,11 +322,16 @@
void initGeneralBox(const store::IndexCondition_t& cond);
- void probeMap(GeneralTreeIndex::IndexMap* map, const store::IndexKey* key);
+ void probeMap(
+ GeneralTreeIndex::IndexMap* map,
+ const store::IndexKey* lowerKey,
+ const store::IndexKey* upperKey);
void doubleToLongProbe(
const AtomicItem* doubleItem,
store::Item_t& result) const;
+
+ void checkStringKeyType(AtomicItem* keyItem) const;
};
=== modified file 'src/store/naive/store_defs.h'
--- src/store/naive/store_defs.h 2011-09-15 07:18:45 +0000
+++ src/store/naive/store_defs.h 2011-10-04 08:30:40 +0000
@@ -106,6 +106,7 @@
XS_FLOAT,
XS_DOUBLE,
+
XS_DECIMAL,
XS_INTEGER,
XS_NON_POSITIVE_INTEGER,
@@ -133,34 +134,6 @@
};
-enum IndexKeyTypeCode
-{
- IDX_XS_STRING,
-
- IDX_XS_DOUBLE,
-
- IDX_XS_DECIMAL,
-
- IDX_XS_INTEGER,
-
- IDX_XS_LONG,
-
- IDX_XS_BASE64BINARY,
-
- IDX_XS_HEXBINARY,
-
- IDX_XS_BOOLEAN,
-
- IDX_XS_DATETIME,
-
- IDX_XS_DURATION,
-
- IDX_XS_QNAME,
-
- IDX_XS_LAST
-};
-
-
}
}
#endif
=== modified file 'src/zorbaserialization/zorba_class_serializer.cpp'
--- src/zorbaserialization/zorba_class_serializer.cpp 2011-07-29 23:27:03 +0000
+++ src/zorbaserialization/zorba_class_serializer.cpp 2011-10-04 08:30:40 +0000
@@ -404,12 +404,15 @@
{
ar.dont_allow_delay();
ar & type;//save qname of type
+
+ ar.set_is_temp_field(false);
+ ar.dont_allow_delay();
+
///check for User Typed Atomic Item
- store::Item* baseItem;
- if(ar.is_serializing_out())
+ store::Item* baseItem;
+ if(ar.is_serializing_out())
baseItem = (store::Item*)obj->getBaseItem();
- ar.set_is_temp_field(false);
- ar.dont_allow_delay();
+
ar & baseItem;
ar.set_is_temp_field(true);
if(baseItem)
=== modified file 'test/rbkt/ExpQueryResults/zorba/index/auctions1.xml.res'
--- test/rbkt/ExpQueryResults/zorba/index/auctions1.xml.res 2011-07-01 05:22:12 +0000
+++ test/rbkt/ExpQueryResults/zorba/index/auctions1.xml.res 2011-10-04 08:30:40 +0000
@@ -110,20 +110,31 @@
Probing the typed AuctionDates sorted general index
---------------------------------------------------
+probe 1:
<exception>err:XPTY0004 : node with more than one key value found during probe on index "auctions:AuctionDates"</exception>
+probe 2:
<exception>err:XPTY0004 : "xs:integer": search key type for index "auctions:AuctionDates" does not match expected type "xs:date"</exception>
+probe 3:
<open_auction id="open_auction2"/><open_auction id="open_auction3"/>
+probe 4:
<exception>err:XPTY0004 : "xs:string": search key type for index "auctions:AuctionDates" does not match expected type "xs:date"</exception>
+probe 5:
+<exception>err:XPTY0004 : node with more than one key value found during probe on index "auctions:AuctionDates"</exception>
+
+probe 6:
<open_auction id="open_auction0"/><open_auction id="open_auction1"/><open_auction id="open_auction3"/><open_auction id="open_auction4"/><open_auction id="open_auction9"/><open_auction id="open_auction10"/><open_auction id="open_auction11"/>
+probe 7:
<open_auction id="open_auction1"/><open_auction id="open_auction4"/><open_auction id="open_auction9"/>
+probe 8:
<open_auction id="open_auction1"/><open_auction id="open_auction9"/>
+probe 9:
<open_auction id="open_auction9"/>
Empty Probe
=== modified file 'test/rbkt/Queries/zorba/index/auctions1.xq'
--- test/rbkt/Queries/zorba/index/auctions1.xq 2011-08-02 17:52:47 +0000
+++ test/rbkt/Queries/zorba/index/auctions1.xq 2011-10-04 08:30:40 +0000
@@ -72,6 +72,7 @@
Probing the typed AuctionDates sorted general index
---------------------------------------------------
+probe 1:
",
try
@@ -85,6 +86,7 @@
"
+probe 2:
",
try
@@ -98,6 +100,7 @@
"
+probe 3:
",
for $id in index_dml:probe-index-point-general($auctions:AuctionDates,
@@ -108,20 +111,39 @@
"
+probe 4:
",
try
{
index_dml:probe-index-point-general($auctions:AuctionDates,
- (xs:date("2000-12-04"), "2000-12-04"))
-}
-catch *
-{
- <exception>{$err:code} : {$err:description}</exception>
-},
-
-"
-
+ (xs:date("2000-12-04"), "2000-12-04"))
+}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+},
+
+"
+
+probe 5:
+",
+
+try
+{
+ index_dml:probe-index-range-value($auctions:AuctionDates,
+ xs:date("1998-12-11"),
+ xs:date("1999-12-11"),
+ fn:true(), fn:true(), fn:true(), fn:true())
+}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+},
+
+"
+
+probe 6:
",
for $id in index_dml:probe-index-range-general($auctions:AuctionDates,
@@ -136,34 +158,37 @@
"
-",
-
-for $id in index_dml:probe-index-range-general($auctions:AuctionDates,
- (xs:date("2001-11-11"),
- xs:date("2001-12-13")),
- (),
- fn:true(),
- fn:false(),
- fn:true(),
- fn:true())/@id
-return <open_auction>{$id}</open_auction>,
-
-"
-
-",
-
-for $id in index_dml:probe-index-range-general($auctions:AuctionDates,
- (xs:date("2001-11-11"),
- xs:date("2001-12-13")),
- (),
- fn:true(),
- fn:false(),
- fn:false(),
- fn:true())/@id
-return <open_auction>{$id}</open_auction>,
-
-"
-
+probe 7:
+",
+
+for $id in index_dml:probe-index-range-general($auctions:AuctionDates,
+ (xs:date("2001-11-11"),
+ xs:date("2001-12-13")),
+ (),
+ fn:true(),
+ fn:false(),
+ fn:true(),
+ fn:true())/@id
+return <open_auction>{$id}</open_auction>,
+
+"
+
+probe 8:
+",
+
+for $id in index_dml:probe-index-range-general($auctions:AuctionDates,
+ (xs:date("2001-11-11"),
+ xs:date("2001-12-13")),
+ (),
+ fn:true(),
+ fn:false(),
+ fn:false(),
+ fn:true())/@id
+return <open_auction>{$id}</open_auction>,
+
+"
+
+probe 9:
",
for $id in index_dml:probe-index-range-general($auctions:AuctionDates,
@@ -352,6 +377,47 @@
return <open_auction>{$id}</open_auction>,
"
+
+-----------------------------------------------------------
+Probing the untyped PersonIncome2 sorted general 1-1 index
+-----------------------------------------------------------
+
+probe 1:
+
+",
+
+try
+{
+for $person in index_dml:probe-index-range-value($auctions:PersonIncome2,
+ 10000,
+ 50000,
+ fn:false(),
+ fn:false(),
+ fn:true(),
+ fn:true())
+return <person>{$person/@id, $person//@income}</person>
+}
+catch *
+{
+ <exception>{$err:code} : {$err:description}</exception>
+},
+
+"
+
+probe 2:
+
+",
+
+for $person in index_dml:probe-index-range-value($auctions:PersonIncome2,
+ "10000",
+ "50000",
+ fn:true(),
+ fn:true(),
+ fn:true(),
+ fn:true())
+return <person>{$person/@id, $person//@income}</person>,
+
+"
"
)
=== modified file 'test/rbkt/Queries/zorba/index/auctions_module1.xqlib'
--- test/rbkt/Queries/zorba/index/auctions_module1.xqlib 2011-08-12 16:07:57 +0000
+++ test/rbkt/Queries/zorba/index/auctions_module1.xqlib 2011-10-04 08:30:40 +0000
@@ -15,6 +15,7 @@
declare variable $auctions:PersonWatches2 := xs:QName("auctions:PersonWatches2");
declare variable $auctions:AuctionDates := xs:QName("auctions:AuctionDates");
declare variable $auctions:AuctionDates2 := xs:QName("auctions:AuctionDates2");
+declare variable $auctions:PersonIncome2 := xs:QName("auctions:PersonIncome2");
declare collection auctions:auctions as node()*;
@@ -39,7 +40,8 @@
(:
- The PersonWatches index maps each open auction to the persons who watch that auction.
+ The PersonWatches index maps each open auction to the persons who watch that
+ auction. A person may watch multiple open auctions.
:)
declare %ann:general-equality %ann:manual index auctions:PersonWatches
@@ -58,7 +60,7 @@
(:
The AuctionDates index maps dates to the open auctions that had a biding on the
- associated date.
+ associated date. An open auction may have biddings on it on multiple dates.
:)
declare %ann:general-range %ann:manual index auctions:AuctionDates
@@ -77,6 +79,16 @@
(:
+ The PersonIncome2 maps each income to the persons who have that income.
+ Each person has at most one income.
+:)
+
+declare %ann:general-range %ann:manual index auctions:PersonIncome2
+on nodes dml:collection(xs:QName("auctions:auctions"))//person
+by .//@income;
+
+
+(:
Create and populate the collection, and then create the indexes
:)
@@ -97,6 +109,8 @@
index_ddl:create($auctions:AuctionDates);
index_ddl:create($auctions:AuctionDates2);
+
+ index_ddl:create($auctions:PersonIncome2);
};
Follow ups