This is an automated email from the ASF dual-hosted git repository.
kfaraz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git
The following commit(s) were added to refs/heads/master by this push:
new c98c66558f Include statement attributes in `EXPLAIN PLAN` output
(#14074)
c98c66558f is described below
commit c98c66558f7d5ad48edde681ba5192130268b24a
Author: Abhishek Radhakrishnan <[email protected]>
AuthorDate: Mon Apr 17 08:30:25 2023 -0700
Include statement attributes in `EXPLAIN PLAN` output (#14074)
This commit adds attributes that contain metadata information about the
query
in the EXPLAIN PLAN output. The attributes currently contain two items:
- `statementTyp`: SELECT, INSERT or REPLACE
- `targetDataSource`: provides the target datasource name for DML statements
It is added to both the legacy and native query plan outputs.
---
docs/querying/sql-translation.md | 220 +++++++++++----------
docs/querying/sql.md | 4 +-
.../druid/sql/calcite/planner/DruidPlanner.java | 1 +
.../sql/calcite/planner/ExplainAttributes.java | 73 +++++++
.../druid/sql/calcite/planner/IngestHandler.java | 18 ++
.../druid/sql/calcite/planner/PlannerContext.java | 16 ++
.../druid/sql/calcite/planner/QueryHandler.java | 26 ++-
.../sql/calcite/planner/SqlStatementHandler.java | 1 +
.../druid/sql/avatica/DruidAvaticaHandlerTest.java | 4 +-
.../druid/sql/calcite/BaseCalciteQueryTest.java | 3 +
.../druid/sql/calcite/CalciteExplainQueryTest.java | 47 ++---
.../druid/sql/calcite/CalciteInsertDmlTest.java | 50 ++++-
.../druid/sql/calcite/CalciteReplaceDmlTest.java | 47 ++++-
.../druid/sql/calcite/CalciteSelectQueryTest.java | 22 ++-
.../druid/sql/calcite/IngestTableFunctionTest.java | 3 +-
.../org/apache/druid/sql/http/SqlResourceTest.java | 4 +-
16 files changed, 388 insertions(+), 151 deletions(-)
diff --git a/docs/querying/sql-translation.md b/docs/querying/sql-translation.md
index 370ad002c1..39014f1b28 100644
--- a/docs/querying/sql-translation.md
+++ b/docs/querying/sql-translation.md
@@ -64,7 +64,11 @@ appreciated.
The [EXPLAIN PLAN](sql.md#explain-plan) functionality can help you understand
how a given SQL query will
be translated to native.
-EXPLAIN PLAN statements return a `RESOURCES` column that describes the
resource being queried as well as a `PLAN` column that contains a JSON array of
native queries that Druid will run.
+EXPLAIN PLAN statements return:
+- a `PLAN` column that contains a JSON array of native queries that Druid will
run
+- a `RESOURCES` column that describes the resource being queried as well as a
`PLAN` column that contains a JSON array of native queries that Druid will run
+- a `ATTRIBUTES` column that describes the attributes of a query, such as the
statement type and target data source
+
For example, consider the following query:
```sql
@@ -77,120 +81,132 @@ WHERE channel IN (SELECT page FROM wikipedia GROUP BY
page ORDER BY COUNT(*) DES
GROUP BY channel
```
-The EXPLAIN PLAN statement returns the following plan:
+The EXPLAIN PLAN statement returns the following result with plan, resources,
and attributes information in it:
```json
[
- {
- "query": {
- "queryType": "topN",
- "dataSource": {
- "type": "join",
- "left": {
- "type": "table",
- "name": "wikipedia"
- },
- "right": {
- "type": "query",
- "query": {
- "queryType": "groupBy",
- "dataSource": {
- "type": "table",
- "name": "wikipedia"
- },
- "intervals": {
- "type": "intervals",
- "intervals": [
- "-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
- ]
- },
- "granularity": {
- "type": "all"
- },
- "dimensions": [
- {
- "type": "default",
- "dimension": "page",
- "outputName": "d0",
- "outputType": "STRING"
- }
- ],
- "aggregations": [
- {
- "type": "count",
- "name": "a0"
- }
- ],
- "limitSpec": {
- "type": "default",
- "columns": [
+ [
+ {
+ "query": {
+ "queryType": "topN",
+ "dataSource": {
+ "type": "join",
+ "left": {
+ "type": "table",
+ "name": "wikipedia"
+ },
+ "right": {
+ "type": "query",
+ "query": {
+ "queryType": "groupBy",
+ "dataSource": {
+ "type": "table",
+ "name": "wikipedia"
+ },
+ "intervals": {
+ "type": "intervals",
+ "intervals": [
+
"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
+ ]
+ },
+ "granularity": {
+ "type": "all"
+ },
+ "dimensions": [
{
- "dimension": "a0",
- "direction": "descending",
- "dimensionOrder": {
- "type": "numeric"
- }
+ "type": "default",
+ "dimension": "page",
+ "outputName": "d0",
+ "outputType": "STRING"
}
],
- "limit": 10
- },
- "context": {
- "sqlOuterLimit": 101,
- "sqlQueryId": "ee616a36-c30c-4eae-af00-245127956e42",
- "useApproximateCountDistinct": false,
- "useApproximateTopN": false
+ "aggregations": [
+ {
+ "type": "count",
+ "name": "a0"
+ }
+ ],
+ "limitSpec": {
+ "type": "default",
+ "columns": [
+ {
+ "dimension": "a0",
+ "direction": "descending",
+ "dimensionOrder": {
+ "type": "numeric"
+ }
+ }
+ ],
+ "limit": 10
+ },
+ "context": {
+ "sqlOuterLimit": 101,
+ "sqlQueryId": "ee616a36-c30c-4eae-af00-245127956e42",
+ "useApproximateCountDistinct": false,
+ "useApproximateTopN": false
+ }
}
+ },
+ "rightPrefix": "j0.",
+ "condition": "(\"channel\" == \"j0.d0\")",
+ "joinType": "INNER"
+ },
+ "dimension": {
+ "type": "default",
+ "dimension": "channel",
+ "outputName": "d0",
+ "outputType": "STRING"
+ },
+ "metric": {
+ "type": "dimension",
+ "ordering": {
+ "type": "lexicographic"
}
},
- "rightPrefix": "j0.",
- "condition": "(\"channel\" == \"j0.d0\")",
- "joinType": "INNER"
- },
- "dimension": {
- "type": "default",
- "dimension": "channel",
- "outputName": "d0",
- "outputType": "STRING"
- },
- "metric": {
- "type": "dimension",
- "ordering": {
- "type": "lexicographic"
+ "threshold": 101,
+ "intervals": {
+ "type": "intervals",
+ "intervals": [
+ "-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
+ ]
+ },
+ "granularity": {
+ "type": "all"
+ },
+ "aggregations": [
+ {
+ "type": "count",
+ "name": "a0"
+ }
+ ],
+ "context": {
+ "sqlOuterLimit": 101,
+ "sqlQueryId": "ee616a36-c30c-4eae-af00-245127956e42",
+ "useApproximateCountDistinct": false,
+ "useApproximateTopN": false
}
},
- "threshold": 101,
- "intervals": {
- "type": "intervals",
- "intervals": [
- "-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z"
- ]
- },
- "granularity": {
- "type": "all"
- },
- "aggregations": [
+ "signature": [
{
- "type": "count",
- "name": "a0"
+ "name": "d0",
+ "type": "STRING"
+ },
+ {
+ "name": "a0",
+ "type": "LONG"
}
- ],
- "context": {
- "sqlOuterLimit": 101,
- "sqlQueryId": "ee616a36-c30c-4eae-af00-245127956e42",
- "useApproximateCountDistinct": false,
- "useApproximateTopN": false
- }
- },
- "signature": [
- {
- "name": "d0",
- "type": "STRING"
- },
- {
- "name": "a0",
- "type": "LONG"
- }
- ]
+ ]
+ }
+ ],
+ [
+ {
+ "name": "wikipedia",
+ "type": "DATASOURCE"
+ }
+ ],
+ {
+ "statementType": "SELECT",
+ "targetDataSource": null
}
]
```
diff --git a/docs/querying/sql.md b/docs/querying/sql.md
index 18c3b84272..5888989612 100644
--- a/docs/querying/sql.md
+++ b/docs/querying/sql.md
@@ -250,8 +250,8 @@ Add "EXPLAIN PLAN FOR" to the beginning of any query to get
information about ho
the query will not actually be executed. Refer to the [Query
translation](sql-translation.md#interpreting-explain-plan-output)
documentation for more information on the output of EXPLAIN PLAN.
-> Be careful when interpreting EXPLAIN PLAN output, and use [request
logging](../configuration/index.md#request-logging) if in doubt.
-Request logs show the exact native query that will be run.
+> For the legacy plan, be careful when interpreting EXPLAIN PLAN output, and
use [request logging](../configuration/index.md#request-logging) if in doubt.
+Request logs show the exact native query that will be run. Alternatively, to
see the native query plan, set `useNativeQueryExplain` to true in the query
context.
## Identifiers and literals
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
index b0912507a2..59c4cca285 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidPlanner.java
@@ -135,6 +135,7 @@ public class DruidPlanner implements Closeable
try {
handler.validate();
plannerContext.setResourceActions(handler.resourceActions());
+ plannerContext.setExplainAttributes(handler.explainAttributes());
}
catch (RuntimeException e) {
throw new ValidationException(e);
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/ExplainAttributes.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/ExplainAttributes.java
new file mode 100644
index 0000000000..b793fad96f
--- /dev/null
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/ExplainAttributes.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.sql.calcite.planner;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import org.apache.calcite.sql.SqlNode;
+
+import javax.annotation.Nullable;
+
+/**
+ * ExplainAttributes holds the attributes of a SQL statement that is used in
the EXPLAIN PLAN result.
+ */
+public final class ExplainAttributes
+{
+ private final String statementType;
+
+ @Nullable
+ private final SqlNode targetDataSource;
+
+ public ExplainAttributes(
+ @JsonProperty("statementType") final String statementType,
+ @JsonProperty("targetDataSource") @Nullable final SqlNode
targetDataSource)
+ {
+ this.statementType = statementType;
+ this.targetDataSource = targetDataSource;
+ }
+
+ /**
+ * @return the statement kind of a SQL statement. For example, SELECT,
INSERT, or REPLACE.
+ */
+ @JsonProperty
+ public String getStatementType()
+ {
+ return statementType;
+ }
+
+ /**
+ * @return the target datasource in a SQL statement. Returns null
+ * for SELECT/non-DML statements where there is no target datasource.
+ */
+ @Nullable
+ @JsonProperty
+ public String getTargetDataSource()
+ {
+ return targetDataSource == null ? null : targetDataSource.toString();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ExplainAttributes{" +
+ "statementType='" + statementType + '\'' +
+ ", targetDataSource=" + targetDataSource +
+ '}';
+ }
+}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/IngestHandler.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/IngestHandler.java
index 47ea855603..7aab7148b4 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/IngestHandler.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/IngestHandler.java
@@ -273,6 +273,15 @@ public abstract class IngestHandler extends QueryHandler
}
super.validate();
}
+
+ @Override
+ public ExplainAttributes explainAttributes()
+ {
+ return new ExplainAttributes(
+ DruidSqlInsert.OPERATOR.getName(),
+ sqlNode.getTargetTable()
+ );
+ }
}
/**
@@ -331,5 +340,14 @@ public abstract class IngestHandler extends QueryHandler
);
}
}
+
+ @Override
+ public ExplainAttributes explainAttributes()
+ {
+ return new ExplainAttributes(
+ DruidSqlReplace.OPERATOR.getName(),
+ sqlNode.getTargetTable()
+ );
+ }
}
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
index 280372462a..5c36ef72b6 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/PlannerContext.java
@@ -111,6 +111,8 @@ public class PlannerContext
private String planningError;
private QueryMaker queryMaker;
private VirtualColumnRegistry joinExpressionVirtualColumnRegistry;
+ // set of attributes for a SQL statement used in the EXPLAIN PLAN output
+ private ExplainAttributes explainAttributes;
private PlannerContext(
final PlannerToolbox plannerToolbox,
@@ -502,4 +504,18 @@ public class PlannerContext
{
this.joinExpressionVirtualColumnRegistry =
joinExpressionVirtualColumnRegistry;
}
+
+ public ExplainAttributes getExplainAttributes()
+ {
+ return this.explainAttributes;
+ }
+
+ public void setExplainAttributes(ExplainAttributes explainAttributes)
+ {
+ if (this.explainAttributes != null) {
+ throw new ISE("ExplainAttributes has already been set");
+ }
+ this.explainAttributes = explainAttributes;
+ }
+
}
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
index e5808e9737..4e9cc3e46b 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/QueryHandler.java
@@ -173,10 +173,11 @@ public abstract class QueryHandler extends
SqlStatementHandler.BaseStatementHand
{
return typeFactory.createStructType(
ImmutableList.of(
+ Calcites.createSqlType(typeFactory, SqlTypeName.VARCHAR),
Calcites.createSqlType(typeFactory, SqlTypeName.VARCHAR),
Calcites.createSqlType(typeFactory, SqlTypeName.VARCHAR)
),
- ImmutableList.of("PLAN", "RESOURCES")
+ ImmutableList.of("PLAN", "RESOURCES", "ATTRIBUTES")
);
}
@@ -229,6 +230,15 @@ public abstract class QueryHandler extends
SqlStatementHandler.BaseStatementHand
}
}
+ @Override
+ public ExplainAttributes explainAttributes()
+ {
+ return new ExplainAttributes(
+ "SELECT",
+ null
+ );
+ }
+
private static Set<RelOptTable> getBindableTables(final RelNode relNode)
{
class HasBindableVisitor extends RelVisitor
@@ -374,9 +384,19 @@ public abstract class QueryHandler extends
SqlStatementHandler.BaseStatementHand
log.error(jpe, "Encountered exception while serializing resources for
explain output");
resourcesString = null;
}
+
+ String explainAttributesString;
+ try {
+ explainAttributesString =
plannerContext.getJsonMapper().writeValueAsString(plannerContext.getExplainAttributes());
+ }
+ catch (JsonProcessingException jpe) {
+ log.error(jpe, "Encountered exception while serializing attributes for
explain output");
+ explainAttributesString = null;
+ }
+
final Supplier<QueryResponse<Object[]>> resultsSupplier =
Suppliers.ofInstance(
QueryResponse.withEmptyContext(
- Sequences.simple(ImmutableList.of(new Object[]{explanation,
resourcesString}))
+ Sequences.simple(ImmutableList.of(new Object[]{explanation,
resourcesString, explainAttributesString}))
)
);
return new PlannerResult(resultsSupplier,
getExplainStructType(rel.getCluster().getTypeFactory()));
@@ -384,7 +404,7 @@ public abstract class QueryHandler extends
SqlStatementHandler.BaseStatementHand
/**
* This method doesn't utilize the Calcite's internal {@link
RelOptUtil#dumpPlan} since that tends to be verbose
- * and not indicative of the native Druid Queries which will get executed
+ * and not indicative of the native Druid Queries which will get executed.
* This method assumes that the Planner has converted the RelNodes to
DruidRels, and thereby we can implicitly cast it
*
* @param rel Instance of the root {@link DruidRel} which is formed by
running the planner transformations on it
diff --git
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlStatementHandler.java
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlStatementHandler.java
index 7084751690..4cb263c522 100644
---
a/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlStatementHandler.java
+++
b/sql/src/main/java/org/apache/druid/sql/calcite/planner/SqlStatementHandler.java
@@ -41,6 +41,7 @@ public interface SqlStatementHandler
void prepare();
PrepareResult prepareResult();
PlannerResult plan() throws ValidationException;
+ ExplainAttributes explainAttributes();
/**
* Context available to statement handlers.
diff --git
a/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
b/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
index 51f536f41a..6de7316729 100644
---
a/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java
@@ -469,7 +469,9 @@ public class DruidAvaticaHandlerTest extends CalciteTestBase
DUMMY_SQL_QUERY_ID
),
"RESOURCES",
- "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]"
+ "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]",
+ "ATTRIBUTES",
+ "{\"statementType\":\"SELECT\",\"targetDataSource\":null}"
)
),
getRows(resultSet)
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
index 0bc2dc3ffc..2a0930912b 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/BaseCalciteQueryTest.java
@@ -170,6 +170,9 @@ public class BaseCalciteQueryTest extends CalciteTestBase
public static final PlannerConfig PLANNER_CONFIG_AUTHORIZE_SYS_TABLES =
PlannerConfig.builder().authorizeSystemTablesDirectly(true).build();
+ public static final PlannerConfig PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN =
+ PlannerConfig.builder().useNativeQueryExplain(false).build();
+
public static final PlannerConfig PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN =
PlannerConfig.builder().useNativeQueryExplain(true).build();
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteExplainQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteExplainQueryTest.java
index 480fca6aeb..0c694e372c 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteExplainQueryTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteExplainQueryTest.java
@@ -51,14 +51,15 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+
"\"signature\":[{\"name\":\"a0\",\"type\":\"LONG\"}]"
+ "}]";
final String resources = "[{\"name\":\"aview\",\"type\":\"VIEW\"}]";
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
query,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
- new Object[]{legacyExplanation, resources}
+ new Object[]{legacyExplanation, resources, attributes}
)
);
testQuery(
@@ -67,7 +68,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
- new Object[]{explanation, resources}
+ new Object[]{explanation, resources, attributes}
)
);
}
@@ -81,6 +82,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+ " BindableTableScan(table=[[INFORMATION_SCHEMA, COLUMNS]])\n";
final String resources = "[]";
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
"EXPLAIN PLAN FOR\n"
@@ -89,7 +91,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+ "WHERE TABLE_SCHEMA = 'druid' AND TABLE_NAME = 'foo'",
ImmutableList.of(),
ImmutableList.of(
- new Object[]{explanation, resources}
+ new Object[]{explanation, resources, attributes}
)
);
}
@@ -125,23 +127,24 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+
"\"signature\":[{\"name\":\"a0\",\"type\":\"LONG\"}]"
+ "}]";
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
query,
ImmutableList.of(),
- ImmutableList.of(new Object[]{explanation, resources})
+ ImmutableList.of(new Object[]{explanation, resources, attributes})
);
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
query,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
- ImmutableList.of(new Object[]{legacyExplanation, resources})
+ ImmutableList.of(new Object[]{legacyExplanation, resources,
attributes})
);
}
- // This testcase has been added here and not in CalciteSelectQueryTests
since this checks if the overrides are working
+ // This testcase has been added here and not in CalciteSelectQueryTest since
this checks if the overrides are working
// properly when displaying the output of "EXPLAIN PLAN FOR ..." queries
@Test
public void testExplainSelectStarWithOverrides()
@@ -181,16 +184,17 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+ "}]";
String sql = "EXPLAIN PLAN FOR SELECT * FROM druid.foo";
String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
// Test when default config and no overrides
- testQuery(sql, ImmutableList.of(), ImmutableList.of(new
Object[]{explanation, resources}));
+ testQuery(sql, ImmutableList.of(), ImmutableList.of(new
Object[]{explanation, resources, attributes}));
// Test when default config and useNativeQueryExplain is overridden in the
context
testQuery(
sql,
legacyExplainContext,
ImmutableList.of(),
- ImmutableList.of(new Object[]{legacyExplanationWithContext, resources})
+ ImmutableList.of(new Object[]{legacyExplanationWithContext, resources,
attributes})
);
// Test when useNativeQueryExplain enabled by default and no overrides
@@ -199,7 +203,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
sql,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
- ImmutableList.of(new Object[]{explanation, resources})
+ ImmutableList.of(new Object[]{explanation, resources, attributes})
);
// Test when useNativeQueryExplain enabled by default but is overriden in
the context
@@ -209,7 +213,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
sql,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
- ImmutableList.of(new Object[]{explanationWithContext, resources})
+ ImmutableList.of(new Object[]{explanationWithContext, resources,
attributes})
);
}
@@ -241,14 +245,14 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+
"\"signature\":[{\"name\":\"dim1\",\"type\":\"STRING\"}]"
+ "}]";
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
-
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
query,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
- new Object[]{legacyExplanation, resources}
+ new Object[]{legacyExplanation, resources, attributes}
)
);
testQuery(
@@ -257,7 +261,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
- new Object[]{explanation, resources}
+ new Object[]{explanation, resources, attributes}
)
);
}
@@ -294,12 +298,12 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+
"\"signature\":[{\"name\":\"v0\",\"type\":\"STRING\"},{\"name\":\"v1\",\"type\":\"STRING\"}]"
+ "}]";
final String expectedResources =
"[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
-
+ final String expectedAttributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
explainSql,
defaultExprContext,
ImmutableList.of(),
- ImmutableList.of(new Object[]{expectedPlanWithDefaultExpressions,
expectedResources})
+ ImmutableList.of(new Object[]{expectedPlanWithDefaultExpressions,
expectedResources, expectedAttributes})
);
// Test plan as mv-filtered virtual columns
@@ -318,7 +322,6 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+
"\"granularity\":{\"type\":\"all\"}},"
+
"\"signature\":[{\"name\":\"v0\",\"type\":\"STRING\"},{\"name\":\"v1\",\"type\":\"STRING\"}]"
+ "}]";
-
final Map<String, Object> mvFilteredContext = new
HashMap<>(QUERY_CONTEXT_DEFAULT);
mvFilteredContext.put(PlannerConfig.CTX_KEY_USE_NATIVE_QUERY_EXPLAIN,
true);
@@ -326,7 +329,7 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
explainSql,
mvFilteredContext,
ImmutableList.of(),
- ImmutableList.of(new Object[]{expectedPlanWithMvfiltered,
expectedResources})
+ ImmutableList.of(new Object[]{expectedPlanWithMvfiltered,
expectedResources, expectedAttributes})
);
}
@@ -358,13 +361,13 @@ public class CalciteExplainQueryTest extends
BaseCalciteQueryTest
+
"\"signature\":[{\"name\":\"v0\",\"type\":\"LONG\"}]"
+ "}]";
final String expectedResources =
"[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
-
+ final String expectedAttributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
// Verify the query plan
testQuery(
explainSql,
queryContext,
ImmutableList.of(),
- ImmutableList.of(new Object[]{expectedPlan, expectedResources})
+ ImmutableList.of(new Object[]{expectedPlan, expectedResources,
expectedAttributes})
);
}
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
index fb184e89c8..c8184d9706 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteInsertDmlTest.java
@@ -48,7 +48,6 @@ import org.apache.druid.sql.calcite.filtration.Filtration;
import org.apache.druid.sql.calcite.parser.DruidSqlInsert;
import org.apache.druid.sql.calcite.planner.Calcites;
import org.apache.druid.sql.calcite.planner.IngestHandler;
-import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.hamcrest.CoreMatchers;
@@ -870,14 +869,54 @@ public class CalciteInsertDmlTest extends
CalciteIngestionDmlTest
)
.build();
- final String expectedExplanation =
+ final String legacyExplanation =
"DruidQueryRel(query=["
+ queryJsonMapper.writeValueAsString(expectedQuery)
+ "], signature=[{x:STRING, y:STRING, z:LONG}])\n";
+ final String explanation =
+ "["
+ + "{\"query\":{\"queryType\":\"scan\","
+ +
"\"dataSource\":{\"type\":\"external\",\"inputSource\":{\"type\":\"inline\",\"data\":\"a,b,1\\nc,d,2\\n\"},"
+ + "\"inputFormat\":{\"type\":\"csv\",\"columns\":[\"x\",\"y\",\"z\"]},"
+ +
"\"signature\":[{\"name\":\"x\",\"type\":\"STRING\"},{\"name\":\"y\",\"type\":\"STRING\"},{\"name\":\"z\",\"type\":\"LONG\"}]},"
+ +
"\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
+ +
"\"resultFormat\":\"compactedList\",\"columns\":[\"x\",\"y\",\"z\"],\"legacy\":false,"
+ +
"\"context\":{\"sqlInsertSegmentGranularity\":\"{\\\"type\\\":\\\"all\\\"}\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
+ +
"\"granularity\":{\"type\":\"all\"}},\"signature\":[{\"name\":\"x\",\"type\":\"STRING\"},{\"name\":\"y\",\"type\":\"STRING\"},{\"name\":\"z\",\"type\":\"LONG\"}]"
+ + "}]";
+
+ final String resources =
"[{\"name\":\"EXTERNAL\",\"type\":\"EXTERNAL\"},{\"name\":\"dst\",\"type\":\"DATASOURCE\"}]";
+ final String attributes =
"{\"statementType\":\"INSERT\",\"targetDataSource\":\"dst\"}";
+
+
// Use testQuery for EXPLAIN (not testIngestionQuery).
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
+ ImmutableMap.of("sqlQueryId", "dummy"),
+ Collections.emptyList(),
+ StringUtils.format(
+ "EXPLAIN PLAN FOR INSERT INTO dst SELECT * FROM %s PARTITIONED BY
ALL TIME",
+ externSql(externalDataSource)
+ ),
+ CalciteTests.SUPER_USER_AUTH_RESULT,
+ ImmutableList.of(),
+ new DefaultResultsVerifier(
+ ImmutableList.of(
+ new Object[]{
+ legacyExplanation,
+ resources,
+ attributes
+ }
+ ),
+ null
+ ),
+ null
+ );
+
+
+ testQuery(
+ PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
ImmutableMap.of("sqlQueryId", "dummy"),
Collections.emptyList(),
StringUtils.format(
@@ -889,8 +928,9 @@ public class CalciteInsertDmlTest extends
CalciteIngestionDmlTest
new DefaultResultsVerifier(
ImmutableList.of(
new Object[]{
- expectedExplanation,
-
"[{\"name\":\"EXTERNAL\",\"type\":\"EXTERNAL\"},{\"name\":\"dst\",\"type\":\"DATASOURCE\"}]"
+ explanation,
+ resources,
+ attributes
}
),
null
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteReplaceDmlTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteReplaceDmlTest.java
index c51aac37c0..e78485416c 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteReplaceDmlTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteReplaceDmlTest.java
@@ -39,7 +39,6 @@ import org.apache.druid.sql.calcite.filtration.Filtration;
import org.apache.druid.sql.calcite.parser.DruidSqlInsert;
import org.apache.druid.sql.calcite.parser.DruidSqlParserUtils;
import org.apache.druid.sql.calcite.parser.DruidSqlReplace;
-import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.junit.Assert;
@@ -614,14 +613,51 @@ public class CalciteReplaceDmlTest extends
CalciteIngestionDmlTest
)
.build();
- final String expectedExplanation =
+ final String legacyExplanation =
"DruidQueryRel(query=["
+ queryJsonMapper.writeValueAsString(expectedQuery)
+ "], signature=[{x:STRING, y:STRING, z:LONG}])\n";
+ final String explanation = "[{"
+ + "\"query\":{\"queryType\":\"scan\","
+ +
"\"dataSource\":{\"type\":\"external\",\"inputSource\":{\"type\":\"inline\",\"data\":\"a,b,1\\nc,d,2\\n\"},"
+ +
"\"inputFormat\":{\"type\":\"csv\",\"columns\":[\"x\",\"y\",\"z\"]},"
+ +
"\"signature\":[{\"name\":\"x\",\"type\":\"STRING\"},{\"name\":\"y\",\"type\":\"STRING\"},{\"name\":\"z\",\"type\":\"LONG\"}]},"
+ +
"\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},"
+ +
"\"resultFormat\":\"compactedList\",\"columns\":[\"x\",\"y\",\"z\"],\"legacy\":false,"
+ +
"\"context\":{\"sqlInsertSegmentGranularity\":\"{\\\"type\\\":\\\"all\\\"}\",\"sqlQueryId\":\"dummy\","
+ +
"\"sqlReplaceTimeChunks\":\"all\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},\"granularity\":{\"type\":\"all\"}},"
+ +
"\"signature\":[{\"name\":\"x\",\"type\":\"STRING\"},{\"name\":\"y\",\"type\":\"STRING\"},{\"name\":\"z\",\"type\":\"LONG\"}]}]";
+
+ final String resources =
"[{\"name\":\"EXTERNAL\",\"type\":\"EXTERNAL\"},{\"name\":\"dst\",\"type\":\"DATASOURCE\"}]";
+ final String attributes =
"{\"statementType\":\"REPLACE\",\"targetDataSource\":\"dst\"}";
+
// Use testQuery for EXPLAIN (not testIngestionQuery).
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
+ ImmutableMap.of("sqlQueryId", "dummy"),
+ Collections.emptyList(),
+ StringUtils.format(
+ "EXPLAIN PLAN FOR REPLACE INTO dst OVERWRITE ALL SELECT * FROM %s
PARTITIONED BY ALL TIME",
+ externSql(externalDataSource)
+ ),
+ CalciteTests.SUPER_USER_AUTH_RESULT,
+ ImmutableList.of(),
+ new DefaultResultsVerifier(
+ ImmutableList.of(
+ new Object[]{
+ legacyExplanation,
+ resources,
+ attributes
+ }
+ ),
+ null
+ ),
+ null
+ );
+
+ testQuery(
+ PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
ImmutableMap.of("sqlQueryId", "dummy"),
Collections.emptyList(),
StringUtils.format(
@@ -633,8 +669,9 @@ public class CalciteReplaceDmlTest extends
CalciteIngestionDmlTest
new DefaultResultsVerifier(
ImmutableList.of(
new Object[]{
- expectedExplanation,
-
"[{\"name\":\"EXTERNAL\",\"type\":\"EXTERNAL\"},{\"name\":\"dst\",\"type\":\"DATASOURCE\"}]"
+ explanation,
+ resources,
+ attributes
}
),
null
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
index 0982f17807..f8e31d7e92 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteSelectQueryTest.java
@@ -45,7 +45,6 @@ import org.apache.druid.segment.column.RowSignature;
import org.apache.druid.segment.virtual.ExpressionVirtualColumn;
import org.apache.druid.sql.SqlPlanningException;
import org.apache.druid.sql.calcite.filtration.Filtration;
-import org.apache.druid.sql.calcite.planner.PlannerConfig;
import org.apache.druid.sql.calcite.planner.PlannerContext;
import org.apache.druid.sql.calcite.util.CalciteTests;
import org.joda.time.DateTime;
@@ -544,16 +543,18 @@ public class CalciteSelectQueryTest extends
BaseCalciteQueryTest
+ "}]";
final String legacyExplanation =
"DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"inline\",\"columnNames\":[\"EXPR$0\"],\"columnTypes\":[\"LONG\"],\"rows\":[[2]]},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"resultFormat\":\"compactedList\",\"columns\":[\"EXPR$0\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimesta
[...]
final String resources = "[]";
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
query,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
new Object[]{
legacyExplanation,
- resources
+ resources,
+ attributes
}
)
);
@@ -565,7 +566,8 @@ public class CalciteSelectQueryTest extends
BaseCalciteQueryTest
ImmutableList.of(
new Object[]{
explanation,
- resources
+ resources,
+ attributes
}
)
);
@@ -1284,19 +1286,20 @@ public class CalciteSelectQueryTest extends
BaseCalciteQueryTest
+ "\"legacy\":false,"
+
"\"context\":{\"defaultTimeout\":300000,\"maxScatterGatherBytes\":9223372036854775807,\"sqlCurrentTimestamp\":\"2000-01-01T00:00:00Z\",\"sqlQueryId\":\"dummy\",\"vectorize\":\"false\",\"vectorizeVirtualColumns\":\"false\"},"
+ "\"granularity\":{\"type\":\"all\"}},"
- +
"\"signature\":[{\"name\":\"__time\",\"type\":\"LONG\"},{\"name\":\"dim1\",\"type\":\"STRING\"},{\"name\":\"dim2\",\"type\":\"STRING\"},{\"name\":\"dim3\",\"type\":\"STRING\"},{\"name\":\"cnt\",\"type\":\"LONG\"},{\"name\":\"m1\",\"type\":\"FLOAT\"},{\"name\":\"m2\",\"type\":\"DOUBLE\"},{\"name\":\"unique_dim1\",\"type\":\"COMPLEX<hyperUnique>\"}]"
- + "}]";
+ +
"\"signature\":[{\"name\":\"__time\",\"type\":\"LONG\"},{\"name\":\"dim1\",\"type\":\"STRING\"},{\"name\":\"dim2\",\"type\":\"STRING\"},{\"name\":\"dim3\",\"type\":\"STRING\"},{\"name\":\"cnt\",\"type\":\"LONG\"},{\"name\":\"m1\",\"type\":\"FLOAT\"},{\"name\":\"m2\",\"type\":\"DOUBLE\"},{\"name\":\"unique_dim1\",\"type\":\"COMPLEX<hyperUnique>\"}]}]";
final String resources = "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]";
+ final String attributes =
"{\"statementType\":\"SELECT\",\"targetDataSource\":null}";
testQuery(
- PlannerConfig.builder().useNativeQueryExplain(false).build(),
+ PLANNER_CONFIG_LEGACY_QUERY_EXPLAIN,
query,
CalciteTests.REGULAR_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
new Object[]{
legacyExplanation,
- resources
+ resources,
+ attributes
}
)
);
@@ -1308,7 +1311,8 @@ public class CalciteSelectQueryTest extends
BaseCalciteQueryTest
ImmutableList.of(
new Object[]{
explanation,
- resources
+ resources,
+ attributes
}
)
);
diff --git
a/sql/src/test/java/org/apache/druid/sql/calcite/IngestTableFunctionTest.java
b/sql/src/test/java/org/apache/druid/sql/calcite/IngestTableFunctionTest.java
index 86136c7000..825198eefb 100644
---
a/sql/src/test/java/org/apache/druid/sql/calcite/IngestTableFunctionTest.java
+++
b/sql/src/test/java/org/apache/druid/sql/calcite/IngestTableFunctionTest.java
@@ -317,6 +317,7 @@ public class IngestTableFunctionTest extends
CalciteIngestionDmlTest
"\"granularity\":{\"type\":\"all\"}}," +
"\"signature\":[{\"name\":\"x\",\"type\":\"STRING\"},{\"name\":\"y\",\"type\":\"STRING\"},{\"name\":\"z\",\"type\":\"LONG\"}]}]";
final String resources =
"[{\"name\":\"EXTERNAL\",\"type\":\"EXTERNAL\"},{\"name\":\"dst\",\"type\":\"DATASOURCE\"}]";
+ final String attributes =
"{\"statementType\":\"INSERT\",\"targetDataSource\":\"dst\"}";
testQuery(
PLANNER_CONFIG_NATIVE_QUERY_EXPLAIN,
@@ -324,7 +325,7 @@ public class IngestTableFunctionTest extends
CalciteIngestionDmlTest
CalciteTests.SUPER_USER_AUTH_RESULT,
ImmutableList.of(),
ImmutableList.of(
- new Object[]{explanation, resources}
+ new Object[]{explanation, resources, attributes}
)
);
didTest = true;
diff --git a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
index 339e713e30..2a80011a9b 100644
--- a/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/http/SqlResourceTest.java
@@ -1326,7 +1326,9 @@ public class SqlResourceTest extends CalciteTestBase
"false"
),
"RESOURCES",
- "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]"
+ "[{\"name\":\"foo\",\"type\":\"DATASOURCE\"}]",
+ "ATTRIBUTES",
+ "{\"statementType\":\"SELECT\",\"targetDataSource\":null}"
)
),
rows
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]