This is an automated email from the ASF dual-hosted git repository.
jackietien pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 2710cb3db65 Add state predicate push down for system table
current_queries (#16904)
2710cb3db65 is described below
commit 2710cb3db653d8c674495647bd34cd5afdbc3544
Author: Weihao Li <[email protected]>
AuthorDate: Mon Dec 15 18:05:43 2025 +0800
Add state predicate push down for system table current_queries (#16904)
---
.../informationschema/IoTDBCurrentQueriesIT.java | 9 +-
.../InformationSchemaContentSupplierFactory.java | 30 ++++++-
.../iotdb/db/queryengine/plan/Coordinator.java | 33 +++++++
.../plan/planner/TableOperatorGenerator.java | 1 +
.../optimizations/PushPredicateIntoTableScan.java | 100 +++++++++++++++++++++
.../planner/assertions/ColumnReference.java | 10 +--
.../planner/assertions/PlanMatchPattern.java | 20 +++--
.../informationschema/CurrentQueriesTest.java | 77 ++++++++++++++++
8 files changed, 259 insertions(+), 21 deletions(-)
diff --git
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/informationschema/IoTDBCurrentQueriesIT.java
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/informationschema/IoTDBCurrentQueriesIT.java
index a68bd92b50b..4f9c8cab794 100644
---
a/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/informationschema/IoTDBCurrentQueriesIT.java
+++
b/integration-test/src/test/java/org/apache/iotdb/relational/it/query/recent/informationschema/IoTDBCurrentQueriesIT.java
@@ -83,7 +83,7 @@ public class IoTDBCurrentQueriesIT {
statement.execute("set configuration \"query_cost_stat_window\"='1'");
// 1. query current_queries table
- String sql = "SELECT * FROM current_queries";
+ String sql = "SELECT * FROM current_queries WHERE state='RUNNING'";
ResultSet resultSet = statement.executeQuery(sql);
ResultSetMetaData metaData = resultSet.getMetaData();
Assert.assertEquals(CURRENT_QUERIES_COLUMN_NUM,
metaData.getColumnCount());
@@ -116,7 +116,7 @@ public class IoTDBCurrentQueriesIT {
Assert.assertEquals(61, rowNum);
// 3. requery current_queries table
- sql = "SELECT * FROM current_queries";
+ sql = "SELECT * FROM current_queries WHERE state='FINISHED'";
resultSet = statement.executeQuery(sql);
metaData = resultSet.getMetaData();
Assert.assertEquals(CURRENT_QUERIES_COLUMN_NUM,
metaData.getColumnCount());
@@ -128,13 +128,14 @@ public class IoTDBCurrentQueriesIT {
}
rowNum++;
}
- // three rows in the result, 2 FINISHED and 1 RUNNING
- Assert.assertEquals(3, rowNum);
+ // two rows in the result, 2 FINISHED
+ Assert.assertEquals(2, rowNum);
Assert.assertEquals(2, finishedQueries);
resultSet.close();
// 4. test the expired QueryInfo was evicted
Thread.sleep(61_001);
+ sql = "SELECT * FROM current_queries";
resultSet = statement.executeQuery(sql);
rowNum = 0;
while (resultSet.next()) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
index 76d84c741de..fe0727ec3f2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/source/relational/InformationSchemaContentSupplierFactory.java
@@ -69,11 +69,15 @@ import org.apache.iotdb.db.protocol.session.IClientSession;
import org.apache.iotdb.db.protocol.session.SessionManager;
import org.apache.iotdb.db.queryengine.common.ConnectionInfo;
import org.apache.iotdb.db.queryengine.common.QueryId;
+import org.apache.iotdb.db.queryengine.execution.QueryState;
import org.apache.iotdb.db.queryengine.plan.Coordinator;
import org.apache.iotdb.db.queryengine.plan.execution.IQueryExecution;
import
org.apache.iotdb.db.queryengine.plan.execution.config.metadata.relational.ShowCreateViewTask;
import
org.apache.iotdb.db.queryengine.plan.relational.function.TableBuiltinTableFunction;
import org.apache.iotdb.db.queryengine.plan.relational.security.AccessControl;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Expression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.util.ReservedIdentifiers;
import org.apache.iotdb.db.relational.grammar.sql.RelationalSqlKeywords;
import org.apache.iotdb.db.schemaengine.table.InformationSchemaUtils;
@@ -130,7 +134,10 @@ public class InformationSchemaContentSupplierFactory {
private InformationSchemaContentSupplierFactory() {}
public static Iterator<TsBlock> getSupplier(
- final String tableName, final List<TSDataType> dataTypes, final
UserEntity userEntity) {
+ final String tableName,
+ final List<TSDataType> dataTypes,
+ Expression predicate,
+ final UserEntity userEntity) {
try {
switch (tableName) {
case InformationSchema.QUERIES:
@@ -168,7 +175,7 @@ public class InformationSchemaContentSupplierFactory {
case InformationSchema.CONNECTIONS:
return new ConnectionsSupplier(dataTypes, userEntity);
case InformationSchema.CURRENT_QUERIES:
- return new CurrentQueriesSupplier(dataTypes, userEntity);
+ return new CurrentQueriesSupplier(dataTypes, predicate, userEntity);
case InformationSchema.QUERIES_COSTS_HISTOGRAM:
return new QueriesCostsHistogramSupplier(dataTypes, userEntity);
default:
@@ -1188,9 +1195,24 @@ public class InformationSchemaContentSupplierFactory {
private int nextConsumedIndex;
private List<Coordinator.StatedQueriesInfo> queriesInfo;
- private CurrentQueriesSupplier(final List<TSDataType> dataTypes, final
UserEntity userEntity) {
+ private CurrentQueriesSupplier(
+ final List<TSDataType> dataTypes, Expression predicate, final
UserEntity userEntity) {
super(dataTypes);
- queriesInfo = Coordinator.getInstance().getCurrentQueriesInfo();
+
+ if (predicate == null) {
+ queriesInfo = Coordinator.getInstance().getCurrentQueriesInfo();
+ } else if (QueryState.RUNNING
+ .toString()
+ .equals(((StringLiteral) ((ComparisonExpression)
predicate).getRight()).getValue())) {
+ queriesInfo = Coordinator.getInstance().getRunningQueriesInfos();
+ } else if (QueryState.FINISHED
+ .toString()
+ .equals(((StringLiteral) ((ComparisonExpression)
predicate).getRight()).getValue())) {
+ queriesInfo = Coordinator.getInstance().getFinishedQueriesInfos();
+ } else {
+ queriesInfo = Collections.emptyList();
+ }
+
try {
accessControl.checkUserGlobalSysPrivilege(userEntity);
} catch (final AccessDeniedException e) {
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
index 78cdee720da..57e3d071074 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/Coordinator.java
@@ -865,6 +865,39 @@ public class Coordinator {
}
}
+ public List<StatedQueriesInfo> getRunningQueriesInfos() {
+ long currentTime = System.currentTimeMillis();
+ return getAllQueryExecutions().stream()
+ .map(
+ queryExecution ->
+ new StatedQueriesInfo(
+ QueryState.RUNNING,
+ queryExecution.getQueryId(),
+ queryExecution.getStartExecutionTime(),
+ DEFAULT_END_TIME,
+ (currentTime - queryExecution.getStartExecutionTime()) /
1000,
+ queryExecution.getExecuteSQL().orElse("UNKNOWN"),
+ queryExecution.getUser(),
+ queryExecution.getClientHostname()))
+ .collect(Collectors.toList());
+ }
+
+ public List<StatedQueriesInfo> getFinishedQueriesInfos() {
+ long currentTime = System.currentTimeMillis();
+ List<StatedQueriesInfo> result = new ArrayList<>();
+ Iterator<QueryInfo> historyQueriesIterator = currentQueriesInfo.iterator();
+ long needRecordTime = currentTime - CONFIG.getQueryCostStatWindow() * 60 *
1_000L;
+ while (historyQueriesIterator.hasNext()) {
+ QueryInfo queryInfo = historyQueriesIterator.next();
+ if (queryInfo.endTime < needRecordTime) {
+ // out of time window, ignore it
+ } else {
+ result.add(new StatedQueriesInfo(QueryState.FINISHED, queryInfo));
+ }
+ }
+ return result;
+ }
+
public List<StatedQueriesInfo> getCurrentQueriesInfo() {
List<IQueryExecution> runningQueries = getAllQueryExecutions();
Set<String> runningQueryIdSet =
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
index c5ffb2752ee..6c6ae5cf327 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/TableOperatorGenerator.java
@@ -1294,6 +1294,7 @@ public class TableOperatorGenerator extends
PlanVisitor<Operator, LocalExecution
getSupplier(
node.getQualifiedObjectName().getObjectName(),
dataTypes,
+ node.getPushDownPredicate(),
context
.getDriverContext()
.getFragmentInstanceContext()
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
index fab09a2e3f5..55905f67682 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/planner/optimizations/PushPredicateIntoTableScan.java
@@ -56,6 +56,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.AggregationN
import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.AssignUniqueId;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.DeviceTableScanNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.FilterNode;
+import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.InformationSchemaTableScanNode;
import org.apache.iotdb.db.queryengine.plan.relational.planner.node.JoinNode;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.ProjectNode;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.SemiJoinNode;
@@ -68,6 +69,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.FunctionCall;
import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.LogicalExpression;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.Node;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.NullLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference;
import org.apache.iotdb.db.utils.TimestampPrecisionUtils;
@@ -99,6 +101,8 @@ import static
com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static java.util.Objects.requireNonNull;
+import static
org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.STATE_TABLE_MODEL;
+import static
org.apache.iotdb.commons.schema.table.InformationSchema.CURRENT_QUERIES;
import static
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.ATTRIBUTE;
import static
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.FIELD;
import static
org.apache.iotdb.commons.schema.table.column.TsTableColumnCategory.TIME;
@@ -440,6 +444,102 @@ public class PushPredicateIntoTableScan implements
PlanOptimizer {
return output;
}
+ @Override
+ public PlanNode visitInformationSchemaTableScan(
+ InformationSchemaTableScanNode node, RewriteContext context) {
+ // no predicate or table is not current_queries, just return dierectly
+ if (TRUE_LITERAL.equals(context.inheritedPredicate)) {
+ return node;
+ }
+
+ // push-down for CURRENT_QUERIES
+ if
(CURRENT_QUERIES.equals(node.getQualifiedObjectName().getObjectName())) {
+ SplitExpression splitExpression =
splitCurrentQueriesPredicate(context.inheritedPredicate);
+ // exist expressions can push down to scan operator
+ if (!splitExpression.getExpressionsCanPushDown().isEmpty()) {
+ List<Expression> expressions =
splitExpression.getExpressionsCanPushDown();
+ checkState(expressions.size() == 1, "Unexpected number of
expressions in table scan");
+ node.setPushDownPredicate(expressions.get(0));
+ }
+
+ // exist expressions cannot push down
+ if (!splitExpression.getExpressionsCannotPushDown().isEmpty()) {
+ List<Expression> expressions =
splitExpression.getExpressionsCannotPushDown();
+ return new FilterNode(
+ queryId.genPlanNodeId(),
+ node,
+ expressions.size() == 1
+ ? expressions.get(0)
+ : new LogicalExpression(LogicalExpression.Operator.AND,
expressions));
+ }
+ return node;
+ }
+
+ FilterNode filterNode =
+ new FilterNode(queryId.genPlanNodeId(), node,
context.inheritedPredicate);
+ context.inheritedPredicate = TRUE_LITERAL;
+ return filterNode;
+ }
+
+ private SplitExpression splitCurrentQueriesPredicate(Expression predicate)
{
+ List<Expression> expressionsCanPushDown = new ArrayList<>();
+ List<Expression> expressionsCannotPushDown = new ArrayList<>();
+
+ if (predicate instanceof LogicalExpression
+ && ((LogicalExpression) predicate).getOperator() ==
LogicalExpression.Operator.AND) {
+
+ // predicate like state = 'xxx' can be push down
+ // Note: the optimizer CanonicalizeExpressionRewriter will ensure the
predicate like 'xxx' =
+ // state will be canonicalized to state = 'xxx'
+ boolean hasExpressionPushDown = false;
+ for (Expression expression : ((LogicalExpression)
predicate).getTerms()) {
+ if (isStateComparedWithConstant(expression) &&
!hasExpressionPushDown) {
+ // if there are more than one state = 'xxx' terms, only add first
to push-down candidate
+ expressionsCanPushDown.add(expression);
+ hasExpressionPushDown = true;
+ } else {
+ expressionsCannotPushDown.add(expression);
+ }
+ }
+
+ return new SplitExpression(
+ Collections.emptyList(), expressionsCanPushDown,
expressionsCannotPushDown, null);
+ }
+
+ if (isStateComparedWithConstant(predicate)) {
+ expressionsCanPushDown.add(predicate);
+ } else {
+ expressionsCannotPushDown.add(predicate);
+ }
+
+ return new SplitExpression(
+ Collections.emptyList(), expressionsCanPushDown,
expressionsCannotPushDown, null);
+ }
+
+ private boolean isStateComparedWithConstant(Expression expression) {
+ if (!(expression instanceof ComparisonExpression)) {
+ return false;
+ }
+
+ ComparisonExpression comparisonExpression = (ComparisonExpression)
expression;
+
+ if (ComparisonExpression.Operator.EQUAL !=
comparisonExpression.getOperator()) {
+ return false;
+ }
+
+ if (!(comparisonExpression.getLeft() instanceof SymbolReference)
+ || !STATE_TABLE_MODEL.equals(
+ ((SymbolReference) comparisonExpression.getLeft()).getName())) {
+ return false;
+ }
+
+ if (!(comparisonExpression.getRight() instanceof StringLiteral)) {
+ return false;
+ }
+
+ return true;
+ }
+
@Override
public PlanNode visitDeviceTableScan(
DeviceTableScanNode tableScanNode, RewriteContext context) {
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/ColumnReference.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/ColumnReference.java
index 6dc2e6d9f96..a93176c19a8 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/ColumnReference.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/ColumnReference.java
@@ -25,7 +25,7 @@ import
org.apache.iotdb.db.queryengine.plan.relational.metadata.ColumnSchema;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.Metadata;
import org.apache.iotdb.db.queryengine.plan.relational.planner.Symbol;
import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.AggregationTableScanNode;
-import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.DeviceTableScanNode;
+import
org.apache.iotdb.db.queryengine.plan.relational.planner.node.TableScanNode;
import java.util.Map;
import java.util.Optional;
@@ -49,10 +49,10 @@ public class ColumnReference implements RvalueMatcher {
String actualTableName;
Map<Symbol, ColumnSchema> assignments;
- if (node instanceof DeviceTableScanNode) {
- DeviceTableScanNode deviceTableScanNode = (DeviceTableScanNode) node;
- actualTableName =
deviceTableScanNode.getQualifiedObjectName().toString();
- assignments = deviceTableScanNode.getAssignments();
+ if (node instanceof TableScanNode) {
+ TableScanNode tableScanNode = (TableScanNode) node;
+ actualTableName = tableScanNode.getQualifiedObjectName().toString();
+ assignments = tableScanNode.getAssignments();
}
/*else if (node instanceof IndexSourceNode indexSourceNode) {
tableHandle = indexSourceNode.getTableHandle();
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/PlanMatchPattern.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/PlanMatchPattern.java
index 9146f46eeca..3ec60536aec 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/PlanMatchPattern.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/assertions/PlanMatchPattern.java
@@ -149,14 +149,18 @@ public final class PlanMatchPattern {
public static PlanMatchPattern infoSchemaTableScan(
String expectedTableName, Optional<Integer> dataNodeId, List<String>
outputSymbols) {
- return node(InformationSchemaTableScanNode.class)
- .with(
- new InformationSchemaTableScanMatcher(
- expectedTableName,
- Optional.empty(),
- outputSymbols,
- Collections.emptySet(),
- dataNodeId));
+ PlanMatchPattern pattern =
+ node(InformationSchemaTableScanNode.class)
+ .with(
+ new InformationSchemaTableScanMatcher(
+ expectedTableName,
+ Optional.empty(),
+ outputSymbols,
+ Collections.emptySet(),
+ dataNodeId));
+ outputSymbols.forEach(
+ symbol -> pattern.withAlias(symbol, new
ColumnReference(expectedTableName, symbol)));
+ return pattern;
}
public static PlanMatchPattern treeDeviceViewTableScan(
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/informationschema/CurrentQueriesTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/informationschema/CurrentQueriesTest.java
index 1e3163321ec..c2f4eb68399 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/informationschema/CurrentQueriesTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/relational/planner/informationschema/CurrentQueriesTest.java
@@ -20,6 +20,9 @@ package
org.apache.iotdb.db.queryengine.plan.relational.planner.informationschem
import org.apache.iotdb.db.queryengine.plan.planner.plan.LogicalQueryPlan;
import org.apache.iotdb.db.queryengine.plan.relational.planner.PlanTester;
+import
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.StringLiteral;
+import org.apache.iotdb.db.queryengine.plan.relational.sql.ast.SymbolReference;
import com.google.common.collect.ImmutableList;
import org.junit.Test;
@@ -40,8 +43,10 @@ import static
org.apache.iotdb.commons.schema.column.ColumnHeaderConstant.USER_T
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanAssert.assertPlan;
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.collect;
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.exchange;
+import static
org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.filter;
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.infoSchemaTableScan;
import static
org.apache.iotdb.db.queryengine.plan.relational.planner.assertions.PlanMatchPattern.output;
+import static
org.apache.iotdb.db.queryengine.plan.relational.sql.ast.ComparisonExpression.Operator.EQUAL;
public class CurrentQueriesTest {
private final PlanTester planTester = new PlanTester();
@@ -80,6 +85,78 @@ public class CurrentQueriesTest {
infoSchemaTableScan("information_schema.current_queries",
Optional.of(2)));
}
+ @Test
+ public void testCurrentQueriesFilterPushDown() {
+ // Normal case
+ LogicalQueryPlan logicalQueryPlan =
+ planTester.createPlan(
+ "select * from information_schema.current_queries where
state='RUNNING'");
+ assertPlan(
+ logicalQueryPlan,
+ output(
+ infoSchemaTableScan(
+ "information_schema.current_queries",
+ Optional.empty(),
+ ImmutableList.of(
+ QUERY_ID_TABLE_MODEL,
+ STATE_TABLE_MODEL,
+ START_TIME_TABLE_MODEL,
+ END_TIME_TABLE_MODEL,
+ DATA_NODE_ID_TABLE_MODEL,
+ COST_TIME,
+ STATEMENT_TABLE_MODEL,
+ USER_TABLE_MODEL,
+ CLIENT_IP))));
+
+ // mixed push down and cannot push down term
+ logicalQueryPlan =
+ planTester.createPlan(
+ "select * from information_schema.current_queries where
state='RUNNING' and query_id='1'");
+ assertPlan(
+ logicalQueryPlan,
+ output(
+ filter(
+ new ComparisonExpression(
+ EQUAL, new SymbolReference(QUERY_ID_TABLE_MODEL), new
StringLiteral("1")),
+ infoSchemaTableScan(
+ "information_schema.current_queries",
+ Optional.empty(),
+ ImmutableList.of(
+ QUERY_ID_TABLE_MODEL,
+ STATE_TABLE_MODEL,
+ START_TIME_TABLE_MODEL,
+ END_TIME_TABLE_MODEL,
+ DATA_NODE_ID_TABLE_MODEL,
+ COST_TIME,
+ STATEMENT_TABLE_MODEL,
+ USER_TABLE_MODEL,
+ CLIENT_IP)))));
+
+ // More than one state='xxx' terms
+ logicalQueryPlan =
+ planTester.createPlan(
+ "select * from information_schema.current_queries where
state='RUNNING' and state='xx'");
+ assertPlan(
+ logicalQueryPlan,
+ output(
+ filter(
+ new ComparisonExpression(
+ EQUAL, new SymbolReference(STATE_TABLE_MODEL), new
StringLiteral("xx")),
+ infoSchemaTableScan(
+ "information_schema.current_queries",
+ Optional.empty(),
+ ImmutableList.of(
+ QUERY_ID_TABLE_MODEL,
+ STATE_TABLE_MODEL,
+ START_TIME_TABLE_MODEL,
+ END_TIME_TABLE_MODEL,
+ DATA_NODE_ID_TABLE_MODEL,
+ COST_TIME,
+ STATEMENT_TABLE_MODEL,
+ USER_TABLE_MODEL,
+ CLIENT_IP)))));
+ }
+
@Test
public void testQueriesCostsHistogram() {
LogicalQueryPlan logicalQueryPlan =