aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store-query-interpreter/src/test/java/tools/refinery/store/query/interpreter/LeftJoinTest.java
blob: 4c849e9d0f36abf27c9636c92e8237af6ca5e2f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package tools.refinery.store.query.interpreter;

import org.junit.jupiter.api.Test;
import tools.refinery.store.model.ModelStore;
import tools.refinery.store.query.ModelQueryAdapter;
import tools.refinery.store.query.dnf.Query;
import tools.refinery.store.query.term.int_.IntTerms;
import tools.refinery.store.query.view.AnySymbolView;
import tools.refinery.store.query.view.FunctionView;
import tools.refinery.store.query.view.KeyOnlyView;
import tools.refinery.store.representation.Symbol;
import tools.refinery.store.tuple.Tuple;

import java.util.List;
import java.util.Map;
import java.util.Optional;

import static tools.refinery.store.query.interpreter.tests.QueryAssertions.assertNullableResults;
import static tools.refinery.store.query.interpreter.tests.QueryAssertions.assertResults;

class LeftJoinTest {
	private static final Symbol<Boolean> person = Symbol.of("Person", 1);
	private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class);
	private static final AnySymbolView personView = new KeyOnlyView<>(person);
	private static final FunctionView<Integer> ageView = new FunctionView<>(age);

	@Test
	void unarySymbolTest() {
		var query = Query.of("Query", Integer.class, (builder, p1, output) -> builder
				.clause(
						personView.call(p1),
						output.assign(ageView.leftJoin(18, p1))
				));

		var store = ModelStore.builder()
				.symbols(person, age)
				.with(QueryInterpreterAdapter.builder()
						.queries(query))
				.build();

		var model = store.createEmptyModel();
		var personInterpretation = model.getInterpretation(person);
		var ageInterpretation = model.getInterpretation(age);
		var queryEngine = model.getAdapter(ModelQueryAdapter.class);
		var queryResultSet = queryEngine.getResultSet(query);

		personInterpretation.put(Tuple.of(0), true);
		personInterpretation.put(Tuple.of(1), true);
		personInterpretation.put(Tuple.of(2), true);

		ageInterpretation.put(Tuple.of(2), 24);

		queryEngine.flushChanges();
		assertNullableResults(Map.of(
				Tuple.of(0), Optional.of(18),
				Tuple.of(1), Optional.of(18),
				Tuple.of(2), Optional.of(24),
				Tuple.of(3), Optional.empty()
		), queryResultSet);

		personInterpretation.put(Tuple.of(0), false);

		ageInterpretation.put(Tuple.of(1), 20);
		ageInterpretation.put(Tuple.of(2), null);

		queryEngine.flushChanges();
		assertNullableResults(Map.of(
				Tuple.of(0), Optional.empty(),
				Tuple.of(1), Optional.of(20),
				Tuple.of(2), Optional.of(18),
				Tuple.of(3), Optional.empty()
		), queryResultSet);
	}

	@Test
	void unarySymbolWithAssignmentTest() {
		// Tests an edge case where the outer joined variable is already bound in the query plan.
		var query = Query.of("Query", (builder, p1) -> builder
				.clause(Integer.class, v1 -> List.of(
						personView.call(p1),
						v1.assign(IntTerms.constant(18)),
						v1.assign(ageView.leftJoin(18, p1))
				)));

		var store = ModelStore.builder()
				.symbols(person, age)
				.with(QueryInterpreterAdapter.builder()
						.queries(query))
				.build();

		var model = store.createEmptyModel();
		var personInterpretation = model.getInterpretation(person);
		var ageInterpretation = model.getInterpretation(age);
		var queryEngine = model.getAdapter(ModelQueryAdapter.class);
		var queryResultSet = queryEngine.getResultSet(query);

		personInterpretation.put(Tuple.of(0), true);
		personInterpretation.put(Tuple.of(1), true);
		personInterpretation.put(Tuple.of(2), true);

		ageInterpretation.put(Tuple.of(2), 24);

		queryEngine.flushChanges();
		assertResults(Map.of(
				Tuple.of(0), true,
				Tuple.of(1), true,
				Tuple.of(2), false,
				Tuple.of(3), false
		), queryResultSet);

		personInterpretation.put(Tuple.of(0), false);

		ageInterpretation.put(Tuple.of(1), 20);
		ageInterpretation.put(Tuple.of(2), null);

		queryEngine.flushChanges();
		assertResults(Map.of(
				Tuple.of(0), false,
				Tuple.of(1), false,
				Tuple.of(2), true,
				Tuple.of(3), false
		), queryResultSet);
	}
}