Skip to content

Commit 7de0a23

Browse files
committed
[bugfix] Fix arity in XQuery error when there are duplicate functions in
a main module Closes #3790
1 parent a85b483 commit 7de0a23

File tree

2 files changed

+96
-2
lines changed

2 files changed

+96
-2
lines changed

exist-core/src/main/java/org/exist/xquery/XQueryContext.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,9 +1717,10 @@ public void declareFunction(final UserDefinedFunction function) throws XPathExce
17171717
throw new XPathException(function, ErrorCodes.XQST0060, "Every declared function name must have a non-null namespace URI, but function '" + name + "' does not meet this requirement.");
17181718
}
17191719

1720-
final FunctionId functionKey = function.getSignature().getFunctionId();
1720+
final FunctionSignature signature = function.getSignature();
1721+
final FunctionId functionKey = signature.getFunctionId();
17211722
if (declaredFunctions.containsKey(functionKey)) {
1722-
throw new XPathException(ErrorCodes.XQST0034, "Function " + function.getName() + "#" + function.getArgumentCount() + " is already defined.");
1723+
throw new XPathException(ErrorCodes.XQST0034, "Function " + signature.getName().toURIQualifiedName() + '#' + signature.getArgumentCount() + " is already defined.");
17231724
} else {
17241725
declaredFunctions.put(functionKey, function);
17251726
}

exist-core/src/test/java/org/exist/xquery/ImportModuleTest.java

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,6 +532,98 @@ public void functionSameAsOtherModule() throws EXistException, IOException, Perm
532532
transaction.commit();
533533

534534
assertEquals(ErrorCodes.XQST0034, e.getErrorCode());
535+
assertTrue(e.getMessage().contains("{http://example.com/impl}f1#1"));
536+
}
537+
}
538+
}
539+
540+
/**
541+
* Checks that XQST0034 is raised if a main module contains two functions of the same name and arity.
542+
*/
543+
@Test
544+
public void functionDuplicateInMainModule() throws EXistException, IOException, PermissionDeniedException, LockException, TriggerException, XPathException {
545+
final String query =
546+
"declare function local:f1($a as xs:string) as xs:string {\n" +
547+
" <first>{$a}</first>\n" +
548+
"};\n" +
549+
"\n" +
550+
"declare function local:f1($a as xs:string) as xs:string {\n" +
551+
" <second>{$a}</second>\n" +
552+
"};\n" +
553+
"\n" +
554+
"<result>\n" +
555+
" <impl1>{local:f1(\"to impl1\")}</impl1>" +
556+
" <impl2>{local:f1(\"to impl1\")}</impl2>" +
557+
"</result>\n";
558+
559+
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
560+
final Source source = new StringSource(query);
561+
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
562+
final Txn transaction = pool.getTransactionManager().beginTransaction()) {
563+
564+
// execute query
565+
try {
566+
final Tuple2<XQueryContext, Sequence> contextAndResult = withCompiledQuery(broker, source, compiledXQuery -> {
567+
final Sequence result = executeQuery(broker, compiledXQuery);
568+
return Tuple(compiledXQuery.getContext(), result);
569+
});
570+
571+
transaction.commit();
572+
573+
fail("expected XQST0034");
574+
575+
} catch (final XPathException e) {
576+
transaction.commit();
577+
578+
assertEquals(ErrorCodes.XQST0034, e.getErrorCode());
579+
assertTrue(e.getMessage().contains("{http://www.w3.org/2005/xquery-local-functions}f1#1"));
580+
}
581+
}
582+
}
583+
584+
/**
585+
* Checks that XQST0034 is raised if a main module contains two functions of the same name and arity.
586+
*/
587+
@Test
588+
public void functionDuplicateNsInMainModule() throws EXistException, IOException, PermissionDeniedException, LockException, TriggerException, XPathException {
589+
final String query =
590+
"declare namespace ns1 = 'http://ns1';\n" +
591+
"declare namespace ns12 = 'http://ns1';\n" +
592+
"\n" +
593+
"declare function ns1:f1($a as xs:string) as xs:string {\n" +
594+
" <first>{$a}</first>\n" +
595+
"};\n" +
596+
"\n" +
597+
"declare function ns12:f1($a as xs:string) as xs:string {\n" +
598+
" <second>{$a}</second>\n" +
599+
"};\n" +
600+
"\n" +
601+
"<result>\n" +
602+
" <impl1>{ns1:f1(\"to impl1\")}</impl1>" +
603+
" <impl2>{ns12:f1(\"to impl1\")}</impl2>" +
604+
"</result>\n";
605+
606+
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
607+
final Source source = new StringSource(query);
608+
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
609+
final Txn transaction = pool.getTransactionManager().beginTransaction()) {
610+
611+
// execute query
612+
try {
613+
final Tuple2<XQueryContext, Sequence> contextAndResult = withCompiledQuery(broker, source, compiledXQuery -> {
614+
final Sequence result = executeQuery(broker, compiledXQuery);
615+
return Tuple(compiledXQuery.getContext(), result);
616+
});
617+
618+
transaction.commit();
619+
620+
fail("expected XQST0034");
621+
622+
} catch (final XPathException e) {
623+
transaction.commit();
624+
625+
assertEquals(ErrorCodes.XQST0034, e.getErrorCode());
626+
assertTrue(e.getMessage().contains("{http://ns1}f1#1"));
535627
}
536628
}
537629
}
@@ -583,6 +675,7 @@ public void functionSameAsImportingModule() throws EXistException, IOException,
583675
transaction.commit();
584676

585677
assertEquals(ErrorCodes.XQST0034, e.getErrorCode());
678+
assertTrue(e.getMessage().contains("{http://example.com/impl}f1#1"));
586679
}
587680
}
588681
}

0 commit comments

Comments
 (0)