Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #312 from wolfgangmm/develop

[bugfix] choose correct type for range index lookup
  • Loading branch information...
commit 14097ffcd62f7f5f7ace13073b31e2ffd47e1431 2 parents f1c18ce + 2b6411d
@shabanovd shabanovd authored
View
12 extensions/indexes/range/src/org/exist/indexing/range/RangeIndexConfig.java
@@ -163,6 +163,18 @@ public boolean matches(NodePath path) {
return false;
}
+ public int getType(String field) {
+ for (RangeIndexConfigElement conf : paths.values()) {
+ if (conf.isComplex()) {
+ int type = conf.getType(field);
+ if (type != Type.ITEM) {
+ return type;
+ }
+ }
+ }
+ return Type.ITEM;
+ }
+
private class PathIterator implements Iterator<RangeIndexConfigElement> {
private RangeIndexConfigElement nextConfig;
View
36 extensions/indexes/range/src/org/exist/xquery/modules/range/FieldLookup.java
@@ -21,13 +21,19 @@
*/
package org.exist.xquery.modules.range;
+import org.exist.collections.Collection;
import org.exist.dom.DocumentSet;
import org.exist.dom.NodeSet;
import org.exist.dom.QName;
import org.exist.dom.VirtualNodeSet;
import org.exist.indexing.range.RangeIndex;
+import org.exist.indexing.range.RangeIndexConfig;
+import org.exist.indexing.range.RangeIndexConfigElement;
import org.exist.indexing.range.RangeIndexWorker;
import org.exist.storage.ElementValue;
+import org.exist.storage.IndexSpec;
+import org.exist.storage.NodePath;
+import org.exist.xmldb.XmldbURI;
import org.exist.xquery.*;
import org.exist.xquery.util.*;
import org.exist.xquery.util.Error;
@@ -36,6 +42,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
public class FieldLookup extends Function implements Optimizable {
@@ -275,8 +282,17 @@ public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathExc
}
}
Sequence[] keys = new Sequence[getArgumentCount() - j];
+ SequenceIterator fieldIter = fields.unorderedIterator();
for (int i = j; i < getArgumentCount(); i++) {
keys[i - j] = getArgument(i).eval(contextSequence);
+ int targetType = Type.ITEM;
+ if (fieldIter.hasNext()) {
+ String field = fieldIter.nextItem().getStringValue();
+ targetType = getType(contextSequence, field);
+ }
+ if (targetType != Type.ITEM) {
+ keys[i -j] = keys[i - j].convertTo(targetType);
+ }
}
RangeIndexWorker index = (RangeIndexWorker) context.getBroker().getIndexController().getWorkerByIndexId(RangeIndex.ID);
@@ -309,6 +325,26 @@ public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathExc
return RangeIndexModule.OPERATOR_MAP.get(calledAs.substring("field-".length()));
}
+ public int getType(Sequence contextSequence, String field) {
+ for (final Iterator<Collection> i = contextSequence.getCollectionIterator(); i.hasNext(); ) {
+ final Collection collection = i.next();
+ if (collection.getURI().startsWith(XmldbURI.SYSTEM_COLLECTION_URI)) {
+ continue;
+ }
+ IndexSpec idxConf = collection.getIndexConfiguration(context.getBroker());
+ if (idxConf != null) {
+ RangeIndexConfig config = (RangeIndexConfig) idxConf.getCustomIndexSpec(RangeIndex.ID);
+ if (config != null) {
+ int type = config.getType(field);
+ if (type != Type.ITEM) {
+ return type;
+ }
+ }
+ }
+ }
+ return Type.ITEM;
+ }
+
@Override
public boolean canOptimize(Sequence contextSequence) {
return true;
View
8 extensions/indexes/range/src/org/exist/xquery/modules/range/Lookup.java
@@ -278,10 +278,16 @@ public NodeSet preSelect(Sequence contextSequence, boolean useContext) throws XP
}
private AtomicValue[] getKeys(Sequence contextSequence) throws XPathException {
+ RangeIndexConfigElement config = findConfiguration(contextSequence);
+ int targetType = config != null ? config.getType() : Type.ITEM;
Sequence keySeq = getArgument(1).eval(contextSequence);
AtomicValue[] keys = new AtomicValue[keySeq.getItemCount()];
for (int i = 0; i < keys.length; i++) {
- keys[i] = (AtomicValue) keySeq.itemAt(i);
+ if (targetType == Type.ITEM) {
+ keys[i] = (AtomicValue) keySeq.itemAt(i);
+ } else {
+ keys[i] = keySeq.itemAt(i).convertTo(targetType);
+ }
}
return keys;
}
View
70 extensions/indexes/range/test/src/xquery/types.xql
@@ -15,9 +15,11 @@ declare variable $tt:COLLECTION_CONFIG :=
<create qname="dateTime" type="xs:dateTime"/>
<create qname="entry">
<field name="date" match="date2" type="xs:date"/>
+ <field name="int2" match="int2" type="xs:integer"/>
</create>
<create qname="string-lc" type="xs:string" case="no"/>
<create qname="string" type="xs:string"/>
+ <create qname="int" type="xs:integer"/>
</range>
</index>
</collection>;
@@ -32,6 +34,8 @@ declare variable $tt:XML :=
<dateTime>1918-02-11T09:00:00Z</dateTime>
<string-lc>UPPERCASE</string-lc>
<string>UPPERCASE</string>
+ <int>1</int>
+ <int2>1</int2>
</entry>
<entry>
<id>E2</id>
@@ -41,6 +45,8 @@ declare variable $tt:XML :=
<dateTime>2012-01-20T10:00:00Z</dateTime>
<string-lc>lowercase</string-lc>
<string>lowercase</string>
+ <int>2</int>
+ <int2>2</int2>
</entry>
<entry>
<id>E3</id>
@@ -50,6 +56,8 @@ declare variable $tt:XML :=
<dateTime>2012-01-20T11:00:00+01:00</dateTime>
<string-lc>MiXeDmOdE</string-lc>
<string>MiXeDmOdE</string>
+ <int>3</int>
+ <int2>3</int2>
</entry>
</test>;
@@ -94,6 +102,23 @@ declare
%test:assertEquals("<id>E2</id>")
%test:args("1918-02-11")
%test:assertEquals("<id>E1</id>")
+function tt:eq-date-type-conversion($date as xs:string) {
+ collection($tt:COLLECTION)//entry[date = $date]/id
+};
+
+declare
+ %test:stats
+ %test:args("2012-01-20")
+ %test:assertXPath("$result//stats:index[@type = 'new-range'][@optimization = 2]")
+function tt:eq-date-type-conversion-optimize($date as xs:string) {
+ collection($tt:COLLECTION)//entry[date = $date]
+};
+
+declare
+ %test:args("2012-01-20")
+ %test:assertEquals("<id>E2</id>")
+ %test:args("1918-02-11")
+ %test:assertEquals("<id>E1</id>")
function tt:eq-date-field($date as xs:date) {
collection($tt:COLLECTION)//entry[date2 = $date]/id
};
@@ -108,6 +133,23 @@ function tt:eq-date-field-optimize($date as xs:date) {
declare
%test:args("2012-01-20")
+ %test:assertEquals("<id>E2</id>")
+ %test:args("1918-02-11")
+ %test:assertEquals("<id>E1</id>")
+function tt:eq-date-field-type-conversion($date as xs:string) {
+ collection($tt:COLLECTION)//entry[date2 = $date]/id
+};
+
+declare
+ %test:stats
+ %test:args("2012-01-20")
+ %test:assertXPath("$result//stats:index[@type = 'new-range'][@optimization = 2]")
+function tt:eq-date-field-type-conversion-optimize($date as xs:string) {
+ collection($tt:COLLECTION)//entry[date2 = $date]
+};
+
+declare
+ %test:args("2012-01-20")
%test:assertEquals("E3")
%test:args("1900-01-01")
%test:assertEquals("E1", "E2", "E3")
@@ -250,6 +292,34 @@ function tt:lt-dateTime($dateTime as xs:dateTime) {
collection($tt:COLLECTION)//entry[dateTime < $dateTime]/id/string()
};
+declare
+ %test:args("2")
+ %test:assertEquals("E2")
+function tt:int-equals-type-conversion($n as xs:string) {
+ collection($tt:COLLECTION)//entry[int = $n]/id/string()
+};
+
+declare
+ %test:args("2")
+ %test:assertEquals("E2")
+function tt:int-field-type-conversion($n as xs:string) {
+ collection($tt:COLLECTION)//entry[int2 = $n]/id/string()
+};
+
+declare
+ %test:args(2.4)
+ %test:assertEquals("E2")
+function tt:int-equals-type-conversion($n as xs:double) {
+ collection($tt:COLLECTION)//entry[int = $n]/id/string()
+};
+
+declare
+ %test:args("X2")
+ %test:assertError
+function tt:int-field-wrong-type($n as xs:string) {
+ collection($tt:COLLECTION)//entry[int2 = $n]/id/string()
+};
+
declare
%test:stats
%test:args("up")
Please sign in to comment.
Something went wrong with that request. Please try again.