Skip to content

Commit fe3ff5c

Browse files
committed
[bugfix] Fix cardinality enforcement of fn:tokenize; no need for it to extend fn:matches
Closes #4863
1 parent 4c77620 commit fe3ff5c

File tree

3 files changed

+25
-38
lines changed

3 files changed

+25
-38
lines changed

exist-core/src/main/java/org/exist/xquery/functions/fn/FunMatches.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
*
6060
* @author <a href="mailto:[email protected]">Wolfgang Meier</a>
6161
*/
62-
public class FunMatches extends Function implements Optimizable, IndexUseReporter {
62+
public final class FunMatches extends Function implements Optimizable, IndexUseReporter {
6363

6464
private static final FunctionParameterSequenceType FS_PARAM_INPUT = optParam("input", Type.STRING, "The input string");
6565
private static final FunctionParameterSequenceType FS_PARAM_PATTERN = param("pattern", Type.STRING, "The pattern");

exist-core/src/main/java/org/exist/xquery/functions/fn/FunTokenize.java

Lines changed: 12 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,13 @@
2121
*/
2222
package org.exist.xquery.functions.fn;
2323

24+
import java.util.regex.Pattern;
2425
import java.util.regex.PatternSyntaxException;
2526

2627
import org.exist.dom.QName;
2728
import org.exist.util.PatternFactory;
28-
import org.exist.xquery.Dependency;
29-
import org.exist.xquery.ErrorCodes;
30-
import org.exist.xquery.Function;
31-
import org.exist.xquery.FunctionSignature;
32-
import org.exist.xquery.Profiler;
33-
import org.exist.xquery.XPathException;
34-
import org.exist.xquery.XQueryContext;
29+
import org.exist.xquery.*;
3530
import org.exist.xquery.value.FunctionParameterSequenceType;
36-
import org.exist.xquery.value.Item;
3731
import org.exist.xquery.value.Sequence;
3832
import org.exist.xquery.value.StringValue;
3933
import org.exist.xquery.value.Type;
@@ -46,7 +40,7 @@
4640
* @author <a href="mailto:[email protected]">Wolfgang Meier</a>
4741
* @see <a href="https://www.w3.org/TR/xpath-functions-31/#func-tokenize">https://www.w3.org/TR/xpath-functions-31/#func-tokenize</a>
4842
*/
49-
public class FunTokenize extends FunMatches {
43+
public class FunTokenize extends BasicFunction {
5044

5145
private static final QName FS_TOKENIZE_NAME = new QName("tokenize", Function.BUILTIN_FUNCTION_NS);
5246

@@ -78,20 +72,9 @@ public FunTokenize(final XQueryContext context, final FunctionSignature signatur
7872
}
7973

8074
@Override
81-
public Sequence eval(final Sequence contextSequence, final Item contextItem) throws XPathException {
82-
if (context.getProfiler().isEnabled()) {
83-
context.getProfiler().start(this);
84-
context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
85-
if (contextSequence != null) {
86-
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
87-
}
88-
if (contextItem != null) {
89-
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
90-
}
91-
}
92-
75+
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
9376
final Sequence result;
94-
final Sequence stringArg = getArgument(0).eval(contextSequence, contextItem);
77+
final Sequence stringArg = args[0];
9578
if (stringArg.isEmpty()) {
9679
result = Sequence.EMPTY_SEQUENCE;
9780
} else {
@@ -100,34 +83,30 @@ public Sequence eval(final Sequence contextSequence, final Item contextItem) thr
10083
result = Sequence.EMPTY_SEQUENCE;
10184
} else {
10285
final int flags;
103-
if (getSignature().getArgumentCount() == 3) {
104-
flags = parseFlags(this, getArgument(2).eval(contextSequence, contextItem)
105-
.getStringValue());
86+
if (args.length == 3) {
87+
flags = parseFlags(this, args[2].itemAt(0).getStringValue());
10688
} else {
10789
flags = 0;
10890
}
10991

11092
final String pattern;
111-
if(getArgumentCount() == 1) {
93+
if (args.length == 1) {
11294
pattern = " ";
11395
string = FunNormalizeSpace.normalize(string);
11496
} else {
11597
if(hasLiteral(flags)) {
11698
// no need to change anything
117-
pattern = getArgument(1).eval(contextSequence, contextItem).getStringValue();
99+
pattern = args[1].itemAt(0).getStringValue();
118100
} else {
119101
final boolean ignoreWhitespace = hasIgnoreWhitespace(flags);
120102
final boolean caseBlind = hasCaseInsensitive(flags);
121-
pattern = translateRegexp(this, getArgument(1).eval(contextSequence, contextItem).getStringValue(), ignoreWhitespace, caseBlind);
103+
pattern = translateRegexp(this, args[1].itemAt(0).getStringValue(), ignoreWhitespace, caseBlind);
122104
}
123105
}
124106

125107
try {
126-
if (pat == null || (!pattern.equals(pat.pattern())) || flags != pat.flags()) {
127-
pat = PatternFactory.getInstance().getPattern(pattern, flags);
128-
}
129-
130-
if(pat.matcher("").matches()) {
108+
final Pattern pat = PatternFactory.getInstance().getPattern(pattern, flags);
109+
if (pat.matcher("").matches()) {
131110
throw new XPathException(this, ErrorCodes.FORX0003, "regular expression could match empty string");
132111
}
133112

@@ -144,10 +123,6 @@ public Sequence eval(final Sequence contextSequence, final Item contextItem) thr
144123
}
145124
}
146125

147-
if (context.getProfiler().isEnabled()) {
148-
context.getProfiler().end(this, "", result);
149-
}
150-
151126
return result;
152127
}
153128

exist-core/src/test/xquery/regex.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,16 @@
143143
<expected>12 3 5 6</expected>
144144
</test>
145145

146+
<test output="text">
147+
<task>fn:tokenize-single-input-1</task>
148+
<code>fn:tokenize("x,y", ",")</code>
149+
<expected>x y</expected>
150+
</test>
151+
152+
<test output="text">
153+
<task>fn:tokenize-single-input-2</task>
154+
<code>fn:tokenize(("a", "b", "x,y"), ",")</code>
155+
<error>XPTY0004</error>
156+
</test>
157+
146158
</TestSet>

0 commit comments

Comments
 (0)