Skip to content

Commit a57109c

Browse files
authored
fix: DH-21914: ComposedFilters and Delegating filters should manage all liveness artifacts. (deephaven#7779)
1 parent 6b51add commit a57109c

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

engine/table/src/main/java/io/deephaven/engine/table/impl/select/ComposedFilter.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ public abstract class ComposedFilter extends WhereFilterLivenessArtifactImpl imp
3131
this.componentFilters = componentFilters;
3232

3333
for (WhereFilter f : this.componentFilters) {
34-
if (f instanceof LivenessArtifact && f.isRefreshing()) {
34+
// We do not check for isRefreshing here (the filters are not dynamic nodes, they have a distinct
35+
// isRefreshing method), because we don't actually know if a filter is going to be refreshing until we
36+
// initialize it.
37+
if (f instanceof LivenessArtifact) {
3538
manage((LivenessArtifact) f);
3639
}
3740
}

engine/table/src/main/java/io/deephaven/engine/table/impl/select/WhereFilterDelegatingBase.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ public abstract class WhereFilterDelegatingBase
2828

2929
protected WhereFilterDelegatingBase(WhereFilter filter) {
3030
this.filter = Objects.requireNonNull(filter);
31-
if (filter instanceof LivenessArtifact && filter.isRefreshing()) {
31+
if (filter instanceof LivenessArtifact) {
32+
// We manage all LivenessArtifact filters; we do not know if they are refreshing at the time of
33+
// construction.
3234
manage((LivenessArtifact) filter);
3335
}
3436
}

engine/table/src/test/java/io/deephaven/engine/table/impl/QueryTableWhereInTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import io.deephaven.chunk.ChunkType;
99
import io.deephaven.engine.context.ExecutionContext;
1010
import io.deephaven.engine.context.QueryScope;
11+
import io.deephaven.engine.liveness.SingletonLivenessManager;
1112
import io.deephaven.engine.table.*;
1213
import io.deephaven.engine.table.impl.indexer.DataIndexer;
1314
import io.deephaven.engine.table.impl.select.*;
@@ -232,6 +233,41 @@ public void testWhereDynamicIn() {
232233
});
233234
}
234235

236+
@Test
237+
public void testWhereInStaticSet() {
238+
final Table setTable = testTable(i(2, 4, 6, 8).toTracking(), col("X", "A", "B", "C", "B"));
239+
assertFalse(setTable.isRefreshing());
240+
241+
final QueryTable filteredTable = testRefreshingTable(i(1, 2, 3, 4, 5).toTracking(),
242+
col("X", "A", "B", "C", "D", "E"));
243+
244+
final ControlledUpdateGraph updateGraph = ExecutionContext.getContext().getUpdateGraph().cast();
245+
246+
final Table result = updateGraph.exclusiveLock().computeLocked(
247+
() -> filteredTable.whereIn(setTable, "X"));
248+
show(result);
249+
assertEquals(3, result.size());
250+
assertArrayEquals(new String[] {"A", "B", "C"}, ColumnVectors.ofObject(result, "X", String.class).toArray());
251+
252+
updateGraph.runWithinUnitTestCycle(() -> {
253+
addToTable(filteredTable, i(6), col("X", "A"));
254+
filteredTable.notifyListeners(i(6), i(), i());
255+
});
256+
show(result);
257+
assertEquals(4, result.size());
258+
assertArrayEquals(new String[] {"A", "B", "C", "A"},
259+
ColumnVectors.ofObject(result, "X", String.class).toArray());
260+
261+
final DynamicWhereFilter dynamicWhereFilter =
262+
new DynamicWhereFilter((QueryTable) setTable, true, MatchPairFactory.getExpressions("X"));
263+
final WhereFilter invert = WhereFilterInvertedImpl.of(dynamicWhereFilter);
264+
265+
final Table filteredInvert = updateGraph.exclusiveLock().computeLocked(() -> filteredTable.where(invert));
266+
assertEquals(2, filteredInvert.size());
267+
assertArrayEquals(new String[] {"D", "E"},
268+
ColumnVectors.ofObject(filteredInvert, "X", String.class).toArray());
269+
}
270+
235271
@Test
236272
public void testWhereDynamicInIncremental() {
237273
testWhereDynamicIncrementalInternal(false, false, true, true);

engine/table/src/test/java/io/deephaven/engine/table/impl/select/TestTimeSeriesFilter.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,4 +420,31 @@ public void testStatic() {
420420
assertFalse(filtered2.isRefreshing());
421421
assertEquals(size, filtered2.size());
422422
}
423+
424+
public void testComposed() {
425+
final long start = DateTimeUtils.epochNanos(DateTimeUtils.parseInstant("2026-03-10T09:00:00 NY"));
426+
427+
final TestClock testClock = new TestClock().setNanos(start + 30 * DateTimeUtils.MINUTE);
428+
429+
final TimeSeriesFilter timeSeriesFilter =
430+
TimeSeriesFilter.newBuilder().columnName("Timestamp").period("PT5m").clock(testClock).invert(true)
431+
.build();
432+
433+
final Filter disjunctiveOne = DisjunctiveFilter.of(timeSeriesFilter);
434+
assertTrue(disjunctiveOne instanceof TimeSeriesFilter);
435+
436+
final Filter disjunctiveTwo =
437+
DisjunctiveFilter.of(timeSeriesFilter, WhereFilterFactory.getExpression("A in `Apple`"));
438+
assertTrue(disjunctiveTwo instanceof DisjunctiveFilter);
439+
440+
final Filter conjunctiveOne = ConjunctiveFilter.of(timeSeriesFilter);
441+
assertTrue(conjunctiveOne instanceof TimeSeriesFilter);
442+
443+
final Filter conjunctiveTwo =
444+
ConjunctiveFilter.of(timeSeriesFilter, WhereFilterFactory.getExpression("A in `Apple`"));
445+
assertTrue(conjunctiveTwo instanceof ConjunctiveFilter);
446+
447+
final WhereFilter inverted = WhereFilterInvertedImpl.of(timeSeriesFilter);
448+
assertTrue(inverted instanceof WhereFilterInvertedImpl);
449+
}
423450
}

0 commit comments

Comments
 (0)