Skip to content

Commit 6e56609

Browse files
[MOD] XQuery: Value materialization revised
1 parent 37174ae commit 6e56609

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+352
-144
lines changed

basex-api/src/main/java/org/basex/query/func/request/RequestSetAttribute.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ public final class RequestSetAttribute extends ApiFunc {
1919
@Override
2020
public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
2121
final String name = toString(exprs[0], qc);
22-
final Value value = exprs[1].value(qc);
22+
final Value value = exprs[1].value(qc), v = value.materialize(qc, n -> false, ii);
23+
if(v == null) throw REQUEST_ATTRIBUTE_X.get(info, value);
2324

24-
request(qc).setAttribute(name, value.materialize(qc, REQUEST_ATTRIBUTE_X, info));
25+
request(qc).setAttribute(name, v);
2526
return Empty.VALUE;
2627
}
2728
}

basex-api/src/main/java/org/basex/query/func/session/SessionSet.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ public final class SessionSet extends SessionFn {
1919
public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
2020
final ASession session = session(qc, true);
2121
final byte[] name = toToken(exprs[0], qc);
22-
final Value value = exprs[1].value(qc);
22+
final Value value = exprs[1].value(qc), v = value.materialize(qc, n -> false, ii);
23+
if(v == null) throw SESSION_SET_X.get(info, value);
2324

24-
session.set(name, value.materialize(qc, SESSION_SET_X, info));
25+
session.set(name, v);
2526
return Empty.VALUE;
2627
}
2728
}

basex-api/src/main/java/org/basex/query/func/sessions/SessionsSet.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ public final class SessionsSet extends SessionsFn {
2020
public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
2121
final ASession session = session(qc);
2222
final byte[] name = toToken(exprs[1], qc);
23-
final Value value = exprs[2].value(qc);
23+
final Value value = exprs[2].value(qc), v = value.materialize(qc, n -> false, ii);
24+
if(v == null) throw SESSIONS_SET_X.get(info, value);
2425

25-
session.set(name, value.materialize(qc, SESSIONS_SET_X, info));
26+
session.set(name, v);
2627
return Empty.VALUE;
2728
}
2829
}

basex-api/src/main/java/org/basex/query/func/ws/WsSet.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ public final class WsSet extends WsFn {
2020
public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
2121
final WebSocket client = client(qc);
2222
final String key = toString(exprs[1], qc);
23-
final Value value = exprs[2].value(qc);
23+
final Value value = exprs[2].value(qc), v = value.materialize(qc, n -> false, ii);
24+
if(v == null) throw WS_SET_X.get(info, value);
2425

25-
client.atts.put(key, value.materialize(qc, WS_SET_X, info));
26+
client.atts.put(key, v);
2627
return Empty.VALUE;
2728
}
2829
}

basex-core/src/main/java/org/basex/core/jobs/QueryJob.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
import java.util.function.*;
88

99
import org.basex.core.*;
10+
import org.basex.data.*;
1011
import org.basex.query.*;
1112
import org.basex.query.value.*;
1213
import org.basex.query.value.item.*;
14+
import org.basex.query.value.node.*;
1315
import org.basex.query.value.seq.*;
1416
import org.basex.server.Log.*;
1517
import org.basex.util.*;
@@ -204,7 +206,13 @@ public void run() {
204206
if(remove) ctx.jobs.tasks.remove(id);
205207

206208
// retrieve result; copy persistent database nodes
207-
result.value = qp.value().materialize(qp.qc, BASEX_CACHE_X, null);
209+
final Predicate<ANode> test = node -> {
210+
final Data d = node.data();
211+
return d == null || d.inMemory();
212+
};
213+
final Value value = qp.value(), v = value.materialize(qp.qc, test, null);
214+
if(v == null) throw BASEX_CACHE_X.get(null, value);
215+
result.value = v;
208216

209217
} catch(final JobException ex) {
210218
// query was interrupted: remove cached result

basex-core/src/main/java/org/basex/core/users/User.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,11 @@ public User(final String name, final String password) {
9696
/**
9797
* Returns user information as XML.
9898
* @param qc query context ({@code null} if element will only be created for serialization)
99+
* @param ii input info
99100
* @return user element
100101
* @throws QueryException query exception
101102
*/
102-
public synchronized FElem toXML(final QueryContext qc) throws QueryException {
103+
public synchronized FElem toXML(final QueryContext qc, final InputInfo ii) throws QueryException {
103104
final FElem user = new FElem(USER).add(NAME, name).add(PERMISSION, perm.toString());
104105
passwords.forEach((key, value) -> {
105106
final FElem pw = new FElem(PASSWORD).add(ALGORITHM, key.toString());
@@ -113,7 +114,7 @@ public synchronized FElem toXML(final QueryContext qc) throws QueryException {
113114
if(info != null) {
114115
if(qc != null) {
115116
// create copy of the info node if query context is available
116-
user.add(info.materialize(qc, true));
117+
user.add(info.materialize(qc, n -> true, ii));
117118
} else {
118119
// otherwise, referenced original info node and invalidate parent reference
119120
user.add(info);

basex-core/src/main/java/org/basex/core/users/Users.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public void write() {
9292
file.parent().md();
9393
final FElem root = new FElem(USERS);
9494
for(final User user : users.values()) {
95-
root.add(user.toXML(null));
95+
root.add(user.toXML(null, null));
9696
}
9797
if(info != null) {
9898
root.add(info);

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

+10-11
Original file line numberDiff line numberDiff line change
@@ -672,19 +672,18 @@ private Value update() throws QueryException {
672672
// create copies of results that will be modified by an update operation
673673
final HashSet<Data> datas = updates.prepare(this);
674674
final StringList dbs = updates.databases();
675-
final QueryFunction<Item, Item> materialize = item -> {
676-
checkStop();
677-
final Data d = item.data();
678-
final boolean copy = d != null && (datas.contains(d) ||
679-
!d.inMemory() && dbs.contains(d.meta.name));
680-
final Item it = item.materialize(this, copy);
681-
if(it == null) throw BASEX_CACHE_X.get(null, item);
682-
return it;
683-
};
684675

685676
final ValueBuilder vb = new ValueBuilder(this);
686-
for(final Item item : value) vb.add(materialize.apply(item));
687-
for(final Item item : updates.output(true)) vb.add(materialize.apply(item));
677+
final QueryConsumer<Value> materialize = val -> {
678+
final Value v = val.materialize(this, node -> {
679+
final Data d = node.data();
680+
return d != null && (datas.contains(d) || !d.inMemory() && dbs.contains(d.meta.name));
681+
}, null);
682+
if(v == null) throw BASEX_CACHE_X.get(null, value);
683+
vb.add(v);
684+
};
685+
materialize.accept(value);
686+
materialize.accept(updates.output(true));
688687

689688
// invalidate current node set in context, apply updates
690689
if(context.data() != null) context.invalidate();

basex-core/src/main/java/org/basex/query/expr/constr/Constr.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ private boolean add(final QueryContext qc, final Item item, final QNmSet qnames)
159159

160160
// add text node
161161
if(!text.isEmpty()) children.add(new FTxt(text.next()));
162-
final boolean copy = qc.context.options.get(MainOptions.COPYNODE);
163-
children.add(node.materialize(qc, copy));
162+
final boolean keep = !qc.context.options.get(MainOptions.COPYNODE);
163+
children.add(node.materialize(qc, n -> keep, info));
164164
}
165165
more = false;
166166
} else {

basex-core/src/main/java/org/basex/query/func/jobs/JobsEval.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ final Str eval(final IOContent query, final QueryContext qc) throws QueryExcepti
4747

4848
// copy variable values
4949
for(final Entry<String, Value> it : bindings.entrySet()) {
50-
bindings.put(it.getKey(), it.getValue().materialize(qc, BASEX_CACHE_X, info));
50+
final Value value = it.getValue(), v = value.materialize(qc, n -> true, info);
51+
if(v == null) throw BASEX_CACHE_X.get(info, v);
52+
bindings.put(it.getKey(), v);
5153
}
5254

5355
final QueryJobSpec spec = new QueryJobSpec(opts, bindings, query);

basex-core/src/main/java/org/basex/query/func/user/UserCreate.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Item item(final QueryContext qc, final InputInfo ii) throws QueryExceptio
3333
if(exprs.length > 4) {
3434
final ANode node = toElem(exprs[4], qc);
3535
if(!T_INFO.matches(node)) throw ELM_X_X.get(info, Q_INFO.prefixId(), node);
36-
user.info(node.materialize(qc, true));
36+
user.info(node.materialize(qc, n -> true, info));
3737
}
3838

3939
qc.updates().add(new Create(user, perms, patterns, qc, info), qc);

basex-core/src/main/java/org/basex/query/func/user/UserListDetails.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ public final class UserListDetails extends UserList {
1515
@Override
1616
public Value value(final QueryContext qc) throws QueryException {
1717
// return information on single user
18-
if(exprs.length > 0) return toUser(0, qc).toXML(qc);
18+
if(exprs.length > 0) return toUser(0, qc).toXML(qc, info);
1919

2020
// return information for all users
2121
final Context ctx = qc.context;
2222
final ValueBuilder vb = new ValueBuilder(qc);
23-
for(final User us : ctx.users.users(null, ctx)) vb.add(us.toXML(qc));
23+
for(final User us : ctx.users.users(null, ctx)) vb.add(us.toXML(qc, info));
2424
return vb.value(this);
2525
}
2626
}

basex-core/src/main/java/org/basex/query/func/user/UserUpdateInfo.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public Item item(final QueryContext qc, final InputInfo ii) throws QueryExceptio
2323
if(!T_INFO.matches(node)) throw ELM_X_X.get(info, Q_INFO.prefixId(), node);
2424
final User user = exprs.length > 1 ? toUser(1, qc) : null;
2525

26-
qc.updates().add(new UpdateInfo(node.materialize(qc, true), user, qc, info), qc);
26+
qc.updates().add(new UpdateInfo(node.materialize(qc, n -> true, info), user, qc, info), qc);
2727
return Empty.VALUE;
2828
}
2929

basex-core/src/main/java/org/basex/query/value/Value.java

+18-15
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import java.io.*;
66
import java.util.*;
7+
import java.util.function.*;
78

89
import org.basex.data.*;
910
import org.basex.io.out.*;
@@ -14,6 +15,7 @@
1415
import org.basex.query.iter.*;
1516
import org.basex.query.util.*;
1617
import org.basex.query.value.item.*;
18+
import org.basex.query.value.node.*;
1719
import org.basex.query.value.type.*;
1820
import org.basex.query.var.*;
1921
import org.basex.util.*;
@@ -77,24 +79,25 @@ public Expr simplifyFor(final Simplify mode, final CompileContext cc) throws Que
7779
}
7880

7981
/**
80-
* Returns a materialized, context-independent version of this value.
81-
* @param qc query context (if {@code null}, process cannot be interrupted)
82-
* @param error query error
83-
* @param info input info
84-
* @return item copy, or {@code null}) if the value cannot be materialized
82+
* Returns a materialized version of this value without dependencies to persistent data.
83+
* @param qc query context
84+
* @param test test if node is materialized
85+
* @param ii input info
86+
* @return materialized value, or {@code null} if the value contains function items
8587
* @throws QueryException query exception
8688
*/
87-
public Value materialize(final QueryContext qc, final QueryError error, final InputInfo info)
88-
throws QueryException {
89+
public abstract Value materialize(QueryContext qc, Predicate<ANode> test, InputInfo ii)
90+
throws QueryException;
8991

90-
final ValueBuilder vb = new ValueBuilder(qc);
91-
for(final Item item : this) {
92-
final Item it = item.materialize(qc, item.persistent());
93-
if(it == null) throw error.get(info, item);
94-
vb.add(it);
95-
}
96-
return vb.value(this);
97-
}
92+
/**
93+
* Checks if this value is materialized, i.e., contains no persistent database nodes or
94+
* function items.
95+
* @param test test for copying nodes
96+
* @param ii input info
97+
* @return result of check
98+
* @throws QueryException query exception
99+
*/
100+
public abstract boolean materialized(Predicate<ANode> test, InputInfo ii) throws QueryException;
98101

99102
/**
100103
* Tests if this is an empty sequence.

basex-core/src/main/java/org/basex/query/value/array/XQArray.java

+23-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.basex.query.QueryText.*;
55

66
import java.util.*;
7+
import java.util.function.*;
78

89
import org.basex.query.*;
910
import org.basex.query.func.fn.*;
@@ -12,6 +13,7 @@
1213
import org.basex.query.value.*;
1314
import org.basex.query.value.item.*;
1415
import org.basex.query.value.map.*;
16+
import org.basex.query.value.node.*;
1517
import org.basex.query.value.type.*;
1618
import org.basex.util.*;
1719
import org.basex.util.list.*;
@@ -329,13 +331,30 @@ public final void string(final boolean indent, final TokenBuilder tb, final int
329331
}
330332

331333
@Override
332-
public Item materialize(final QueryContext qc, final boolean copy) throws QueryException {
334+
public Item materialize(final QueryContext qc, final Predicate<ANode> test, final InputInfo ii)
335+
throws QueryException {
336+
337+
if(materialized(test, ii)) return this;
338+
339+
final ArrayBuilder ab = new ArrayBuilder();
333340
for(final Value value : members()) {
334-
for(final Item item : value) {
335-
if(item.persistent() || item.materialize(null, false) == null) return null;
341+
qc.checkStop();
342+
final Value v = value.materialize(qc, test, ii);
343+
if(v == null) return null;
344+
ab.append(v);
345+
}
346+
return ab.array(this);
347+
}
348+
349+
@Override
350+
public boolean materialized(final Predicate<ANode> test, final InputInfo ii)
351+
throws QueryException {
352+
if(!(funcType().declType.type.instanceOf(AtomType.ANY_ATOMIC_TYPE))) {
353+
for(final Value value : members()) {
354+
if(!value.materialized(test, ii)) return false;
336355
}
337356
}
338-
return this;
357+
return true;
339358
}
340359

341360
@Override

basex-core/src/main/java/org/basex/query/value/item/B64Lazy.java

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package org.basex.query.value.item;
22

33
import java.io.*;
4+
import java.util.function.*;
45

56
import org.basex.io.*;
67
import org.basex.io.in.*;
78
import org.basex.query.*;
8-
import org.basex.query.func.*;
9+
import org.basex.query.func.Function;
10+
import org.basex.query.value.node.*;
911
import org.basex.util.*;
1012

1113
/**
@@ -69,6 +71,20 @@ public boolean isCached() {
6971
return data != null;
7072
}
7173

74+
@Override
75+
public Item materialize(final QueryContext qc, final Predicate<ANode> test, final InputInfo ii)
76+
throws QueryException {
77+
cache(ii);
78+
return this;
79+
}
80+
81+
@Override
82+
public boolean materialized(final Predicate<ANode> test, final InputInfo ii)
83+
throws QueryException {
84+
cache(ii);
85+
return true;
86+
}
87+
7288
@Override
7389
public void toString(final QueryString qs) {
7490
if(isCached()) {

basex-core/src/main/java/org/basex/query/value/item/FuncItem.java

+10-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static org.basex.query.QueryText.*;
55

66
import java.util.*;
7+
import java.util.function.*;
78

89
import org.basex.query.*;
910
import org.basex.query.ann.*;
@@ -15,6 +16,7 @@
1516
import org.basex.query.util.collation.*;
1617
import org.basex.query.util.list.*;
1718
import org.basex.query.value.*;
19+
import org.basex.query.value.node.*;
1820
import org.basex.query.value.type.*;
1921
import org.basex.query.var.*;
2022
import org.basex.util.*;
@@ -225,10 +227,17 @@ public byte[] string(final InputInfo ii) throws QueryException {
225227
}
226228

227229
@Override
228-
public Item materialize(final QueryContext qc, final boolean copy) {
230+
public Item materialize(final QueryContext qc, final Predicate<ANode> test, final InputInfo ii)
231+
throws QueryException {
229232
return null;
230233
}
231234

235+
@Override
236+
public boolean materialized(final Predicate<ANode> test, final InputInfo ii)
237+
throws QueryException {
238+
return false;
239+
}
240+
232241
@Override
233242
public boolean deep(final Item item, final Collation coll, final InputInfo ii)
234243
throws QueryException {

0 commit comments

Comments
 (0)