Skip to content

Commit 819f1bd

Browse files
do not inherit dynamic namespaces in nested queries (fixes #2640) (#2643)
1 parent 0be3cea commit 819f1bd

7 files changed

Lines changed: 39 additions & 9 deletions

File tree

basex-core/src/main/java/org/basex/query/QueryContext.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,10 @@ public final class QueryContext extends Job implements Closeable {
153153
/**
154154
* Constructor.
155155
* @param parent parent context
156+
* @param nsContext inherited namespace context (can be {@code null})
156157
*/
157-
public QueryContext(final QueryContext parent) {
158-
this(parent.context, parent, parent.info);
158+
public QueryContext(final QueryContext parent, final NSDynContext nsContext) {
159+
this(parent.context, parent, nsContext, parent.info);
159160
parent.pushJob(this);
160161
updates = parent.updates;
161162
}
@@ -165,20 +166,22 @@ public QueryContext(final QueryContext parent) {
165166
* @param context database context
166167
*/
167168
public QueryContext(final Context context) {
168-
this(context, null, null);
169+
this(context, null, null, null);
169170
}
170171

171172
/**
172173
* Constructor.
173174
* @param context database context
174175
* @param parent parent context (can be {@code null})
176+
* @param nsContext inherited namespace context (can be {@code null})
175177
* @param info query info (can be {@code null})
176178
*/
177-
public QueryContext(final Context context, final QueryContext parent, final QueryInfo info) {
179+
public QueryContext(final Context context, final QueryContext parent,
180+
final NSDynContext nsContext, final QueryInfo info) {
178181
this.context = context;
179182
this.parent = parent;
180183
this.info = info != null ? info : new QueryInfo(context);
181-
ns = parent != null ? new NSDynContext(parent.ns) : new NSDynContext(null);
184+
ns = new NSDynContext(nsContext);
182185
resources = parent != null ? parent.resources : new QueryResources(this);
183186
ftPosData = parent != null ? parent.ftPosData : null;
184187
shared = parent != null ? parent.shared : new SharedData();

basex-core/src/main/java/org/basex/query/QueryProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public QueryProcessor(final String query, final Context ctx) {
5050
public QueryProcessor(final String query, final String uri, final Context ctx,
5151
final QueryInfo info) {
5252
this.query = query;
53-
qc = pushJob(new QueryContext(ctx, null, info));
53+
qc = pushJob(new QueryContext(ctx, null, null, info));
5454
sc = new StaticContext(qc);
5555
sc.baseURI(uri != null && uri.isEmpty() ? "./" : uri);
5656
}

basex-core/src/main/java/org/basex/query/func/fn/FnLoadXQueryModule.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public XQMap item(final QueryContext qc, final InputInfo ii) throws QueryExcepti
9191
if(!isSupported(version)) throw MODULE_XQUERY_VERSION_X.get(info, version);
9292
}
9393

94-
final QueryContext mqc = new QueryContext(qc);
94+
final QueryContext mqc = new QueryContext(qc, null);
9595
for(final byte[] uri : qc.modDeclared) mqc.modDeclared.put(uri, qc.modDeclared.get(uri));
9696
int nParsed = 0;
9797
final Value ctx = opt.get(CONTEXT_ITEM);

basex-core/src/main/java/org/basex/query/func/xquery/XQueryEval.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ final Value eval(final IOContent query, final boolean updating, final QueryConte
7575
if(!user.has(perm)) throw XQUERY_PERMREQUIRED_X.get(info, perm);
7676

7777
Timer to = null;
78-
try(QueryContext qctx = new QueryContext(qc)) {
78+
try(QueryContext qctx = new QueryContext(qc, null)) {
7979
qctx.user = new User(user).permission(perm);
8080

8181
// limit memory consumption: enforce garbage collection and calculate usage

basex-core/src/main/java/org/basex/query/func/xquery/XQueryTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected Value compute() {
4545
final int size = end - start;
4646
if(size == 1) {
4747
// perform the work
48-
try(QueryContext qc = new QueryContext(tc.qc)) {
48+
try(QueryContext qc = new QueryContext(tc.qc, tc.qc.ns)) {
4949
return tc.funcs.get(start).invoke(qc, tc.info);
5050
} catch(final QueryException ex) {
5151
if(tc.errors) {

basex-core/src/test/java/org/basex/query/func/FnModuleTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,13 @@ public final class FnModuleTest extends SandboxTest {
20032003
query(func.args("x", " { 'content': 'module namespace x=\"x\";\ndeclare variable $x:x := 1;', "
20042004
+ "'xquery-version': 4.0 }") + "?variables?#Q{x}x", 1);
20052005

2006+
// GH-2640
2007+
error("<e xmlns:p='p'>{\n"
2008+
+ " load-xquery-module(\"m\", {\n"
2009+
+ " 'content': ``[module namespace m='m'; declare function m:f() {<p:x/>};]``\n"
2010+
+ " })?functions?#Q{m}f?0()\n"
2011+
+ "}</e>", MODULE_STATIC_ERROR_X_X);
2012+
20062013
error(func.args(""), MODULE_URI_EMPTY);
20072014
error(func.args("x"), MODULE_NOT_FOUND_X);
20082015
error(func.args("x", " { 'content': '%@?$' }"), MODULE_STATIC_ERROR_X_X);

basex-core/src/test/java/org/basex/query/func/XQueryModuleTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ public final class XQueryModuleTest extends SandboxTest {
3636
// GH-2332
3737
query("try {" + func.args("declare function local:f() { local:f() }; local:f()") +
3838
"} catch xquery:error { 'STOP' }", "STOP");
39+
40+
// GH-2640
41+
query("element e { attribute { QName('', 'a') } {}, " + func.args("true()") + " }",
42+
"<e a=\"\">true</e>");
43+
query("<e xmlns:p='p'\n"
44+
+ " p:a='{\n"
45+
+ " map:keys(in-scope-namespaces(<x/>))\n"
46+
+ " }'\n"
47+
+ " p:b='{xquery:eval('\n"
48+
+ " map:keys(in-scope-namespaces(<x/>))\n"
49+
+ " ')}'/>", "<e xmlns:p=\"p\" p:a=\"p xml\" p:b=\"xml\"/>");
3950
}
4051

4152
/** Test method. */
@@ -183,6 +194,15 @@ public final class XQueryModuleTest extends SandboxTest {
183194
+ " }")
184195
+ "=> distinct-values()", "a b c d e");
185196

197+
// GH-2640: fork-join inherits parent dynamic namespace context
198+
query("<e xmlns:p='p'\n"
199+
+ " p:a='{\n"
200+
+ " " + func.args(" \n"
201+
+ " (1 to 100) ! fn() {map:keys(in-scope-namespaces(<x/>))}\n"
202+
+ " ") + "[. = 'p'] => count()\n"
203+
+ " }'\n"
204+
+ "/>", "<e xmlns:p=\"p\" p:a=\"100\"/>");
205+
186206
// optimizations
187207
check(func.args(" ()"), "", empty());
188208
check(func.args(" false#0"), false, root(DynFuncCall.class));

0 commit comments

Comments
 (0)