Skip to content

Commit 3fd78ca

Browse files
refactor(planner): move DDL compiler into streaming_planner
Relocate ast_utils and ddl_compiler from the coordinator plan module into streaming_planner (common and schema/introspection). Add try_compile_connector_create_table so coordinator logical plan visitors compile connector CREATE TABLE statements via the planner crate without duplicating AST routing logic. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a9ba1c1 commit 3fd78ca

7 files changed

Lines changed: 49 additions & 27 deletions

File tree

src/coordinator/src/plan/logical_plan_visitor.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
// limitations under the License.
1212

1313
use datafusion::sql::sqlparser::ast::{ObjectType, Statement as DFStatement};
14-
use sqlparser::ast::Statement;
1514
use tracing::debug;
1615

1716
use crate::coordinator::analyze::analysis::Analysis;
@@ -28,9 +27,8 @@ use crate::coordinator::statement::{
2827
StatementVisitorResult, StopFunction, StreamingTableStatement,
2928
};
3029
use crate::sql::analysis::StreamSchemaProvider;
30+
use crate::sql::schema::try_compile_connector_create_table;
3131

32-
use super::ast_utils::AstUtils;
33-
use super::ddl_compiler::DdlCompiler;
3432
use super::streaming_compiler::StreamingCompiler;
3533

3634
#[derive(Clone)]
@@ -135,15 +133,12 @@ impl StatementVisitor for LogicalPlanVisitor {
135133
stmt: &CreateTable,
136134
_ctx: &StatementVisitorContext,
137135
) -> StatementVisitorResult {
138-
if let Statement::CreateTable(ast_node) = &stmt.statement
139-
&& ast_node.query.is_none()
140-
&& AstUtils::contains_connector_property(&ast_node.with_options)
136+
if let Some(result) =
137+
try_compile_connector_create_table(&self.schema_provider, &stmt.statement)
141138
{
142-
let declared_role = AstUtils::peek_table_role(&ast_node.with_options);
143-
let compiler = DdlCompiler::new(&self.schema_provider);
144-
return match compiler.compile(ast_node, declared_role.as_deref()) {
145-
Ok(external_table) => StatementVisitorResult::Plan(Box::new(
146-
CreateTablePlan::external_table(external_table, ast_node.if_not_exists),
139+
return match result {
140+
Ok((external_table, if_not_exists)) => StatementVisitorResult::Plan(Box::new(
141+
CreateTablePlan::external_table(external_table, if_not_exists),
147142
)),
148143
Err(err) => StatementVisitorResult::Plan(Box::new(CompileErrorPlan::new(format!(
149144
"Ingest table resolution failed - {err:#}"

src/coordinator/src/plan/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@
1010
// See the License for the specific language governing permissions and
1111
// limitations under the License.
1212

13-
mod ast_utils;
1413
mod compile_error_plan;
1514
mod create_function_plan;
1615
mod create_python_function_plan;
1716
mod create_table_plan;
18-
mod ddl_compiler;
1917
mod drop_function_plan;
2018
mod drop_streaming_table_plan;
2119
mod drop_table_plan;

src/coordinator/src/plan/ast_utils.rs renamed to src/streaming_planner/src/common/ast_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
use datafusion::common::{Result, plan_err};
2121
use datafusion::sql::sqlparser::ast::{Expr as SqlExpr, SqlOption, TableConstraint};
2222

23-
use crate::sql::common::with_option_keys as opt;
23+
use crate::common::with_option_keys as opt;
2424

2525
/// Namespace for AST extraction helpers.
2626
pub struct AstUtils;

src/streaming_planner/src/common/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
//! analogous to `arroyo-types` + `arroyo-rpc` in Arroyo.
1717
1818
pub mod arrow_ext;
19+
pub mod ast_utils;
1920
pub mod connector_options;
2021
pub mod constants;
2122
pub mod control;
@@ -38,6 +39,7 @@ pub use function_stream_runtime_common::streaming_protocol::{CheckpointBarrier,
3839
pub use time_utils::{from_nanos, to_micros, to_millis, to_nanos};
3940

4041
// ── Re-exports from new modules ──
42+
pub use ast_utils::AstUtils;
4143
pub use connector_options::ConnectorOptions;
4244
pub use formats::{BadData, Format, Framing, JsonCompression, JsonFormat};
4345
pub use fs_schema::{FsSchema, FsSchemaRef};

src/coordinator/src/plan/ddl_compiler.rs renamed to src/streaming_planner/src/schema/introspection/ddl_compiler.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,21 +22,21 @@ use datafusion::sql::TableReference;
2222
use datafusion::sql::planner::{PlannerContext, SqlToRel};
2323
use datafusion::sql::sqlparser::ast;
2424
use datafusion::sql::sqlparser::ast::CreateTable as SqlCreateTable;
25+
use datafusion::sql::sqlparser::ast::Statement as DfStatement;
2526
use datafusion_expr::ExprSchemable;
2627
use tracing::warn;
2728

28-
use super::ast_utils::AstUtils;
29-
use crate::coordinator::tool::ConnectorOptions;
30-
use crate::sql::analysis::StreamSchemaProvider;
31-
use crate::sql::common::constants::{connection_table_role, connector_type, sql_field};
32-
use crate::sql::common::with_option_keys as opt;
33-
use crate::sql::common::{BadData, Format, Framing, JsonCompression, JsonFormat};
34-
use crate::sql::connector::registry::REGISTRY;
35-
use crate::sql::schema::ColumnDescriptor;
36-
use crate::sql::schema::catalog::{ExternalTable, LookupTable, SourceTable};
37-
use crate::sql::schema::data_encoding_format::DataEncodingFormat;
38-
use crate::sql::schema::table_role::{apply_adapter_specific_rules, validate_adapter_availability};
39-
use crate::sql::schema::temporal_pipeline_config::TemporalPipelineConfig;
29+
use crate::common::ast_utils::AstUtils;
30+
use crate::common::constants::{connection_table_role, connector_type, sql_field};
31+
use crate::common::with_option_keys as opt;
32+
use crate::common::{BadData, ConnectorOptions, Format, Framing, JsonCompression, JsonFormat};
33+
use crate::connector::registry::REGISTRY;
34+
use crate::schema::ColumnDescriptor;
35+
use crate::schema::catalog::{ExternalTable, LookupTable, SourceTable};
36+
use crate::schema::data_encoding_format::DataEncodingFormat;
37+
use crate::schema::schema_provider::StreamSchemaProvider;
38+
use crate::schema::table_role::{apply_adapter_specific_rules, validate_adapter_availability};
39+
use crate::schema::temporal_pipeline_config::TemporalPipelineConfig;
4040

4141
pub struct DdlCompiler<'a> {
4242
schema_provider: &'a StreamSchemaProvider,
@@ -293,6 +293,30 @@ impl<'a> DdlCompiler<'a> {
293293
}
294294
}
295295

296+
/// If `stmt` is `CREATE TABLE ... WITH (connector = ...)`, compile it to [`ExternalTable`].
297+
pub fn try_compile_connector_create_table(
298+
schema_provider: &StreamSchemaProvider,
299+
stmt: &DfStatement,
300+
) -> Option<Result<(ExternalTable, bool)>> {
301+
let DfStatement::CreateTable(ast_node) = stmt else {
302+
return None;
303+
};
304+
if ast_node.query.is_some() {
305+
return None;
306+
}
307+
if !AstUtils::contains_connector_property(&ast_node.with_options) {
308+
return None;
309+
}
310+
let declared_role = AstUtils::peek_table_role(&ast_node.with_options);
311+
let if_not_exists = ast_node.if_not_exists;
312+
let compiler = DdlCompiler::new(schema_provider);
313+
Some(
314+
compiler
315+
.compile(ast_node, declared_role.as_deref())
316+
.map(|table| (table, if_not_exists)),
317+
)
318+
}
319+
296320
fn resolve_source_watermark(
297321
table_identifier: &str,
298322
columns: &mut Vec<ColumnDescriptor>,

src/streaming_planner/src/schema/introspection/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@
1010
// See the License for the specific language governing permissions and
1111
// limitations under the License.
1212

13+
pub mod ddl_compiler;
1314
pub mod ddl_formatter;
1415
pub mod show_formatter;
1516
pub mod stream_formatter;
1617

18+
pub use ddl_compiler::{DdlCompiler, try_compile_connector_create_table};
1719
#[allow(unused_imports)]
1820
pub use ddl_formatter::{DdlBuilder, format_data_type, schema_columns_one_line};
1921
pub use show_formatter::{catalog_table_row_detail, show_create_catalog_table};

src/streaming_planner/src/schema/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ pub mod utils;
2424
pub use catalog::{ExternalTable, LookupTable, SinkTable, SourceTable};
2525
pub use column_descriptor::ColumnDescriptor;
2626
pub use introspection::{
27-
catalog_table_row_detail, schema_columns_one_line, show_create_catalog_table,
27+
catalog_table_row_detail, schema_columns_one_line, show_create_catalog_table, DdlCompiler,
28+
try_compile_connector_create_table,
2829
};
2930
pub use schema_provider::{ObjectName, StreamPlanningContext, StreamSchemaProvider, StreamTable};
3031
pub use table::CatalogEntity;

0 commit comments

Comments
 (0)