diff --git a/extensions/indexes/range/pom.xml b/extensions/indexes/range/pom.xml
index a31c10e1da..c26feebee2 100644
--- a/extensions/indexes/range/pom.xml
+++ b/extensions/indexes/range/pom.xml
@@ -186,6 +186,7 @@
pom.xml
src/test/resources-filtered/conf.xml
src/test/resources/log4j2.xml
+ src/test/xquery/range/conditions.xql
src/main/java/org/exist/indexing/range/RangeIndexAnalyzer.java
src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java
src/main/java/org/exist/indexing/range/RangeIndexConfigElement.java
@@ -203,6 +204,7 @@
pom.xml
src/test/resources-filtered/conf.xml
src/test/resources/log4j2.xml
+ src/test/xquery/range/conditions.xql
src/main/java/org/exist/indexing/range/RangeIndexAnalyzer.java
src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java
src/main/java/org/exist/indexing/range/RangeIndexConfigElement.java
diff --git a/extensions/indexes/range/src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java b/extensions/indexes/range/src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java
index 65e8b243e4..697d7c2006 100644
--- a/extensions/indexes/range/src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java
+++ b/extensions/indexes/range/src/main/java/org/exist/indexing/range/RangeIndexConfigAttributeCondition.java
@@ -46,6 +46,8 @@
package org.exist.indexing.range;
import org.exist.dom.QName;
+import org.exist.dom.persistent.ElementImpl;
+import org.exist.dom.persistent.NodeImpl;
import org.exist.storage.ElementValue;
import org.exist.storage.NodePath;
import org.exist.util.DatabaseConfigurationException;
@@ -77,8 +79,7 @@
*/
public class RangeIndexConfigAttributeCondition extends RangeIndexConfigCondition{
- private final String attributeName;
- private final QName attribute;
+ private final QName attributeName;
private @Nullable final String value;
private final Operator operator;
private final boolean caseSensitive;
@@ -94,13 +95,23 @@ public RangeIndexConfigAttributeCondition(Element elem, NodePath parentPath) thr
throw new DatabaseConfigurationException("Range index module: Attribute condition cannot be defined for an attribute:" + parentPath.toString());
}
- this.attributeName = elem.getAttribute("attribute");
- if (this.attributeName.isEmpty()) {
+ final String attributeValue = elem.getAttribute("attribute");
+ if (attributeValue.isEmpty()) {
throw new DatabaseConfigurationException("Range index module: Empty or no attribute qname in condition");
}
try {
- this.attribute = new QName(QName.extractLocalName(this.attributeName), XMLConstants.NULL_NS_URI, QName.extractPrefix(this.attributeName), ElementValue.ATTRIBUTE);
+ final String attrLocalName = QName.extractLocalName(attributeValue);
+ @Nullable final String attrPrefix = QName.extractPrefix(attributeValue);
+ if (attrPrefix != null) {
+ @Nullable final String attrNamespace = findNamespaceForPrefix(attrPrefix, (ElementImpl) elem);
+ if (attrNamespace == null) {
+ throw new DatabaseConfigurationException("Range index module: Missing namespace declaration for attribute qname in condition");
+ }
+ this.attributeName = new QName(attrLocalName, attrNamespace, attrPrefix, ElementValue.ATTRIBUTE);
+ } else {
+ this.attributeName = new QName(attrLocalName, XMLConstants.NULL_NS_URI, null, ElementValue.ATTRIBUTE);
+ }
} catch (final QName.IllegalQNameException e) {
throw new DatabaseConfigurationException("Rand index module error: " + e.getMessage(), e);
}
@@ -169,6 +180,24 @@ public RangeIndexConfigAttributeCondition(Element elem, NodePath parentPath) thr
}
+ private static @Nullable String findNamespaceForPrefix(final String prefix, ElementImpl contextElem) {
+ while (contextElem != null) {
+ final String namespace = contextElem.getNamespaceForPrefix(prefix);
+ if (namespace != null) {
+ return namespace;
+ }
+
+ @Nullable final Node parentNode = contextElem.getParentNode();
+ if (parentNode != null && parentNode instanceof ElementImpl) {
+ contextElem = (ElementImpl) parentNode;
+ } else {
+ contextElem = null;
+ }
+ }
+
+ return null;
+ }
+
// lazily evaluate lowercase value to convert once when needed
private String getLowercaseValue() {
if (this.lowercaseValue == null) {
@@ -180,15 +209,18 @@ private String getLowercaseValue() {
return this.lowercaseValue;
}
-
@Override
- public boolean matches(Node node) {
-
- if (node.getNodeType() == Node.ELEMENT_NODE && matchValue(((Element)node).getAttribute(attributeName))) {
- return true;
+ public boolean matches(final Node node) {
+ final String attrValue;
+ if (attributeName.hasNamespace()) {
+ attrValue = ((Element) node).getAttributeNS(attributeName.getNamespaceURI(), attributeName.getLocalPart());
+ } else {
+ attrValue = ((Element) node).getAttribute(attributeName.getLocalPart());
}
- return false;
+ return node.getNodeType() == Node.ELEMENT_NODE
+ && matchValue(attrValue);
+
}
private boolean matchValue(String testValue) {
@@ -365,7 +397,7 @@ public boolean find(Predicate predicate) {
if (qname.getNameType() == ElementValue.ATTRIBUTE
&& operator.equals(this.operator)
- && qname.equals(this.attribute)
+ && qname.equals(attributeName)
&& valueTypeMatches
&& foundValue.equals(requiredValue)) {
diff --git a/extensions/indexes/range/src/test/xquery/range/conditions.xql b/extensions/indexes/range/src/test/xquery/range/conditions.xql
index bed3116e3a..5f45944c06 100644
--- a/extensions/indexes/range/src/test/xquery/range/conditions.xql
+++ b/extensions/indexes/range/src/test/xquery/range/conditions.xql
@@ -1,4 +1,28 @@
(:
+ : Elemental
+ : Copyright (C) 2024, Evolved Binary Ltd
+ :
+ : admin@evolvedbinary.com
+ : https://www.evolvedbinary.com | https://www.elemental.xyz
+ :
+ : This library is free software; you can redistribute it and/or
+ : modify it under the terms of the GNU Lesser General Public
+ : License as published by the Free Software Foundation; version 2.1.
+ :
+ : This library is distributed in the hope that it will be useful,
+ : but WITHOUT ANY WARRANTY; without even the implied warranty of
+ : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ : Lesser General Public License for more details.
+ :
+ : You should have received a copy of the GNU Lesser General Public
+ : License along with this library; if not, write to the Free Software
+ : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ :
+ : NOTE: Parts of this file contain code from 'The eXist-db Authors'.
+ : The original license header is included below.
+ :
+ : =====================================================================
+ :
: eXist-db Open Source Native XML Database
: Copyright (C) 2001 The eXist-db Authors
:
@@ -36,7 +60,9 @@ declare namespace stats="http://exist-db.org/xquery/profiling";
declare variable $ct:COLLECTION_CONFIG :=
+ xmlns:tei="http://www.tei-c.org/ns/1.0"
+ xmlns:other1="http://other1"
+ xmlns:other2="http://other2">
@@ -59,6 +85,14 @@ declare variable $ct:COLLECTION_CONFIG :=
+
+
+
+
+
+
+
+
@@ -134,7 +168,7 @@ declare variable $ct:COLLECTION_CONFIG :=
declare variable $ct:DATA :=
-
+
conditional fields!
@@ -143,7 +177,7 @@ declare variable $ct:DATA :=
- publiziert
+ publiziert
literarisch
@@ -161,10 +195,11 @@ declare variable $ct:DATA :=
Alexandria
- startswithendswith
- foo
- foo
- literarisch
+ startswithendswith
+ foo
+ foo
+ literarisch
+ other1-not-same-namespace
@@ -533,3 +568,20 @@ function ct:optimize-matches-no-case() {
collection($ct:COLLECTION)//tei:p[matches(@type, "bb")][. = "something"]
};
+(:~
+ : See: https://github.com/eXist-db/exist/issues/5189
+ :)
+declare
+ %test:assertEquals("publiziert", "startswithendswith")
+function ct:other1-index-keys() {
+ range:index-keys-for-field("other1", function($k, $n) { $k }, 10)
+};
+
+(:~
+ : See: https://github.com/eXist-db/exist/issues/5189
+ :)
+declare
+ %test:assertEquals("foo", "literarisch", "startswithendswith")
+function ct:other2-index-keys() {
+ range:index-keys-for-field("other2", function($k, $n) { $k }, 10)
+};
diff --git a/schema/collection.xconf.xsd b/schema/collection.xconf.xsd
index 43574fe1ea..7a40be0898 100644
--- a/schema/collection.xconf.xsd
+++ b/schema/collection.xconf.xsd
@@ -333,7 +333,7 @@
-
+