Skip to content

Commit

Permalink
Merge pull request #3508 from adamretter/hotfix/string-length-inside-…
Browse files Browse the repository at this point in the history
…predicate

Fix an issue with the context item as an argument to fn:string-length inside a predicate
  • Loading branch information
dizzzz committed Aug 21, 2020
2 parents 528dce9 + 0ed3f91 commit 4080747
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 4 deletions.
17 changes: 14 additions & 3 deletions exist-core/src/main/java/org/exist/xquery/AnalyzeContextInfo.java
Expand Up @@ -114,18 +114,29 @@ public int getFlags() {
*
* @param flags processing flags to be passed to child expression
*/
public void setFlags(int flags) {
public void setFlags(final int flags) {
this.flags = flags;
}

public void addFlag(int flag) {
public void addFlag(final int flag) {
flags |= flag;
}

public void removeFlag(int flag) {
public void removeFlag(final int flag) {
flags &= ~flag;
}

/**
* Determines if a flag is set.
*
* @param flag the flag to test for
*
* @return true if the flag is set, false otherwise.
*/
public boolean hasFlag(final int flag) {
return (flags & flag) == flag;
}

/**
* Returns the parent of the current expression.
*
Expand Down
Expand Up @@ -69,7 +69,8 @@ public FunStrLength(final XQueryContext context, final FunctionSignature signatu
protected Tuple2<Expression, Integer> strictCheckArgumentType(Expression argument,
@Nullable final SequenceType argType, final AnalyzeContextInfo argContextInfo, final int argPosition,
int returnType) {
if (getArgumentCount() == 1 && (argContextInfo.getFlags() & LocationStep.DOT_TEST) == LocationStep.DOT_TEST) {
if (getArgumentCount() == 1 && argContextInfo.hasFlag(LocationStep.DOT_TEST)
&& !argContextInfo.hasFlag(Expression.IN_PREDICATE)) {
/*
fn:string-length has different behaviour with regards the context item...
See https://www.biglist.com/lists/lists.mulberrytech.com/xsl-list/archives/201906/msg00021.html
Expand Down
@@ -0,0 +1,69 @@
/*
* eXist-db Open Source Native XML Database
* Copyright (C) 2001 The eXist-db Authors
*
* info@exist-db.org
* http://www.exist-db.org
*
* 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; either
* version 2.1 of the License, or (at your option) any later version.
*
* 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
*/
package org.exist.xquery.functions.fn;

import org.exist.test.ExistXmldbEmbeddedServer;
import org.junit.ClassRule;
import org.junit.Test;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XPathQueryService;

import static org.junit.Assert.assertEquals;

public class FunStrLengthTest {

@ClassRule
public static final ExistXmldbEmbeddedServer server = new ExistXmldbEmbeddedServer(true, true, true);

@Test
public void contextItemWithinPredicate() throws XMLDBException {
final XPathQueryService queryService = (XPathQueryService) server.getRoot().getService("XQueryService", "1.0");

ResourceSet results = null;

// upon empty sequence
results = queryService.query("()[fn:string-length(.) gt 0]");
assertEquals(0, results.getSize());

// upon computed empty sequence
results = queryService.query("fn:tokenize('', '/')[fn:string-length(.) gt 0]");
assertEquals(0, results.getSize());

// upon non-empty sequence
results = queryService.query("('a', '', 'bc', '', 'def')[fn:string-length(.) gt 0]");
assertEquals(3, results.getSize());
assertEquals("a", results.getResource(0).getContent());
assertEquals("bc", results.getResource(1).getContent());
assertEquals("def", results.getResource(2).getContent());

// upon computed non-empty sequence
results = queryService.query("fn:tokenize('ab/c//def//g//', '/')[fn:string-length(.) gt 0]");
assertEquals(4, results.getSize());
assertEquals("ab", results.getResource(0).getContent());
assertEquals("c", results.getResource(1).getContent());
assertEquals("def", results.getResource(2).getContent());
assertEquals("g", results.getResource(3).getContent());
}


}

0 comments on commit 4080747

Please sign in to comment.