Skip to content

Commit

Permalink
feat: support xml, yaml format in explain output
Browse files Browse the repository at this point in the history
  • Loading branch information
lyang24 committed Nov 15, 2024
1 parent 310b1c3 commit e040ed5
Show file tree
Hide file tree
Showing 12 changed files with 196 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions src/frontend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ pretty-xmlish = "0.1.13"
pretty_assertions = "1"
prometheus = { version = "0.13", features = ["process"] }
prost = { workspace = true }
quick-xml = { version = "0.35", features = ["serialize"] }
rand = { version = "0.8", features = ["small_rng"] }
risingwave_batch = { workspace = true }
risingwave_common = { workspace = true }
Expand All @@ -79,6 +80,7 @@ risingwave_variables = { workspace = true }
rw_futures_util = { workspace = true }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
serde_yaml = "0.9"
sha2 = "0.10.7"
smallvec = { version = "1.13.1", features = ["serde"] }
speedate = "0.15.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- name: test xml output format (logical)
sql: |
CREATE TABLE t (v1 int);
explain (logical, format xml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
expected_outputs:
- explain_output
- name: test xml output format (batch)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format xml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
expected_outputs:
- explain_output
- name: test xml output format (stream)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format xml) create materialized view m1 as SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
expected_outputs:
- explain_output
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- name: test yaml output format (logical)
sql: |
CREATE TABLE t (v1 int);
explain (logical, format yaml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
expected_outputs:
- explain_output
- name: test yaml output format (batch)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format yaml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
expected_outputs:
- explain_output
- name: test yaml output format (stream)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format yaml) create materialized view m1 as SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
expected_outputs:
- explain_output
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This file is automatically generated. See `src/frontend/planner_test/README.md` for more information.
- name: test xml output format (logical)
sql: |
CREATE TABLE t (v1 int);
explain (logical, format xml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
explain_output: |
<XmlNode><name>LogicalAgg</name><fields><aggs>approx_percentile($expr1)</aggs></fields><children><name>LogicalProject</name><fields><exprs>t.v1::Float64 as $expr1</exprs></fields><children><name>LogicalScan</name><fields><columns>v1</columns><table>t</table></fields></children></children></XmlNode>
- name: test xml output format (batch)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format xml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
explain_output: |
<XmlNode><name>BatchSimpleAgg</name><fields><aggs>approx_percentile($expr1)</aggs></fields><children><name>BatchExchange</name><fields><dist>Single</dist></fields><children><name>BatchProject</name><fields><exprs>t.v1::Float64 as $expr1</exprs></fields><children><name>BatchScan</name><fields><columns>v1</columns><table>t</table></fields></children></children></children></XmlNode>
- name: test xml output format (stream)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format xml) create materialized view m1 as SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
explain_output: |
<XmlNode><name>StreamMaterialize</name><fields><columns>approx_percentile</columns><pk_conflict>NoCheck</pk_conflict></fields><children><name>StreamGlobalApproxPercentile</name><fields><quantile>0.5:Float64</quantile><relative_error>0.01:Float64</relative_error></fields><children><name>StreamExchange</name><fields><dist>Single</dist></fields><children><name>StreamLocalApproxPercentile</name><fields><percentile_col>$expr1</percentile_col><quantile>0.5:Float64</quantile><relative_error>0.01:Float64</relative_error></fields><children><name>StreamProject</name><fields><exprs>t.v1::Float64 as $expr1</exprs><exprs>t._row_id</exprs></fields><children><name>StreamTableScan</name><fields><columns>v1</columns><columns>_row_id</columns><table>t</table></fields></children></children></children></children></children></XmlNode>
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# This file is automatically generated. See `src/frontend/planner_test/README.md` for more information.
- name: test yaml output format (logical)
sql: |
CREATE TABLE t (v1 int);
explain (logical, format yaml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
explain_output: |
name: LogicalAgg
fields:
aggs:
- approx_percentile($expr1)
children:
- name: LogicalProject
fields:
exprs:
- t.v1::Float64 as $expr1
children:
- name: LogicalScan
fields:
columns:
- v1
table: t
children: []
- name: test yaml output format (batch)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format yaml) SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
explain_output: |
name: BatchSimpleAgg
fields:
aggs:
- approx_percentile($expr1)
children:
- name: BatchExchange
fields:
dist: Single
order: []
children:
- name: BatchProject
fields:
exprs:
- t.v1::Float64 as $expr1
children:
- name: BatchScan
fields:
columns:
- v1
table: t
children: []
- name: test yaml output format (stream)
sql: |
CREATE TABLE t (v1 int);
explain (physical, format yaml) create materialized view m1 as SELECT approx_percentile(0.5) WITHIN GROUP (order by v1) from t;
explain_output: |
name: StreamMaterialize
fields:
columns:
- approx_percentile
pk_columns: []
pk_conflict: NoCheck
stream_key: []
children:
- name: StreamGlobalApproxPercentile
fields:
quantile: 0.5:Float64
relative_error: 0.01:Float64
children:
- name: StreamExchange
fields:
dist: Single
children:
- name: StreamLocalApproxPercentile
fields:
percentile_col: $expr1
quantile: 0.5:Float64
relative_error: 0.01:Float64
children:
- name: StreamProject
fields:
exprs:
- t.v1::Float64 as $expr1
- t._row_id
children:
- name: StreamTableScan
fields:
columns:
- v1
- _row_id
table: t
children: []
2 changes: 2 additions & 0 deletions src/frontend/src/handler/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,8 @@ async fn do_handle_explain(
match explain_format {
ExplainFormat::Text => blocks.push(plan.explain_to_string()),
ExplainFormat::Json => blocks.push(plan.explain_to_json()),
ExplainFormat::Xml => blocks.push(plan.explain_to_xml()),
ExplainFormat::Yaml => blocks.push(plan.explain_to_yaml()),
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/frontend/src/optimizer/logical_optimization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,12 @@ impl LogicalOptimizer {
ExplainFormat::Json => {
ctx.store_logical(plan.explain_to_json());
}
ExplainFormat::Xml => {
ctx.store_logical(plan.explain_to_xml());
}
ExplainFormat::Yaml => {
ctx.store_logical(plan.explain_to_yaml());
}
}
}

Expand Down Expand Up @@ -806,6 +812,12 @@ impl LogicalOptimizer {
ExplainFormat::Json => {
ctx.store_logical(plan.explain_to_json());
}
ExplainFormat::Xml => {
ctx.store_logical(plan.explain_to_xml());
}
ExplainFormat::Yaml => {
ctx.store_logical(plan.explain_to_yaml());
}
}
}

Expand Down
20 changes: 20 additions & 0 deletions src/frontend/src/optimizer/plan_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,12 @@ pub trait Explain {

/// Explain the plan node and return a json string.
fn explain_to_json(&self) -> String;

/// Explain the plan node and return a xml string.
fn explain_to_xml(&self) -> String;

/// Explain the plan node and return a yaml string.
fn explain_to_yaml(&self) -> String;
}

impl Explain for PlanRef {
Expand Down Expand Up @@ -677,6 +683,20 @@ impl Explain for PlanRef {
serde_json::to_string_pretty(&PrettySerde(explain_ir))
.expect("failed to serialize plan to json")
}

/// Explain the plan node and return a xml string.
fn explain_to_xml(&self) -> String {
let plan = reorganize_elements_id(self.clone());
let explain_ir = plan.explain();
quick_xml::se::to_string(&PrettySerde(explain_ir)).expect("failed to serialize plan to xml")
}

/// Explain the plan node and return a yaml string.
fn explain_to_yaml(&self) -> String {
let plan = reorganize_elements_id(self.clone());
let explain_ir = plan.explain();
serde_yaml::to_string(&PrettySerde(explain_ir)).expect("failed to serialize plan to yaml")
}
}

pub(crate) fn pretty_config() -> PrettyConfig {
Expand Down
4 changes: 4 additions & 0 deletions src/sqlparser/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1139,13 +1139,17 @@ impl fmt::Display for ExplainType {
pub enum ExplainFormat {
Text,
Json,
Xml,
Yaml,
}

impl fmt::Display for ExplainFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ExplainFormat::Text => f.write_str("TEXT"),
ExplainFormat::Json => f.write_str("JSON"),
ExplainFormat::Xml => f.write_str("XML"),
ExplainFormat::Yaml => f.write_str("YAML"),
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/sqlparser/src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,9 @@ define_keywords!(
WITHOUT,
WORK,
WRITE,
XML,
XOR,
YAML,
YEAR,
ZONE
);
Expand Down
9 changes: 8 additions & 1 deletion src/sqlparser/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4062,9 +4062,16 @@ impl Parser<'_> {
Keyword::DISTSQL => options.explain_type = ExplainType::DistSql,
Keyword::FORMAT => {
options.explain_format = {
match parser.expect_one_of_keywords(&[Keyword::TEXT, Keyword::JSON])? {
match parser.expect_one_of_keywords(&[
Keyword::TEXT,
Keyword::JSON,
Keyword::XML,
Keyword::YAML,
])? {
Keyword::TEXT => ExplainFormat::Text,
Keyword::JSON => ExplainFormat::Json,
Keyword::XML => ExplainFormat::Xml,
Keyword::YAML => ExplainFormat::Yaml,
_ => unreachable!("{}", keyword),
}
}
Expand Down

0 comments on commit e040ed5

Please sign in to comment.