@@ -48,7 +48,6 @@ use databend_common_sql::Visibility;
4848use databend_common_sql:: binder:: ConstraintExprBinder ;
4949use databend_common_sql:: executor:: physical_plans:: FragmentKind ;
5050use databend_common_sql:: executor:: physical_plans:: MutationKind ;
51- use databend_common_sql:: executor:: physical_plans:: SortDesc ;
5251use databend_common_sql:: plans:: Insert ;
5352use databend_common_sql:: plans:: InsertInputSource ;
5453use databend_common_sql:: plans:: InsertValue ;
@@ -74,14 +73,12 @@ use crate::physical_plans::EvalScalar;
7473use crate :: physical_plans:: Exchange ;
7574use crate :: physical_plans:: IPhysicalPlan ;
7675use crate :: physical_plans:: PAIMON_ROUTE_KEY_NAME ;
77- use crate :: physical_plans:: PaimonWritePrepare ;
7876use crate :: physical_plans:: PaimonWriteRoute ;
7977use crate :: physical_plans:: PhysicalPlan ;
8078use crate :: physical_plans:: PhysicalPlanBuilder ;
8179use crate :: physical_plans:: PhysicalPlanCast ;
8280use crate :: physical_plans:: PhysicalPlanMeta ;
83- use crate :: physical_plans:: Sort ;
84- use crate :: physical_plans:: SortStep ;
81+ use crate :: physical_plans:: TableWritePrepare ;
8582use crate :: pipelines:: PipelineBuildResult ;
8683use crate :: pipelines:: PipelineBuilder ;
8784use crate :: pipelines:: RawValueSource ;
@@ -131,6 +128,25 @@ fn wrap_paimon_write_distribution(
131128 } ) )
132129}
133130
131+ fn prepare_table_write_input (
132+ input : PhysicalPlan ,
133+ table : & Arc < dyn Table > ,
134+ select_schema : DataSchemaRef ,
135+ select_column_bindings : Vec < ColumnBinding > ,
136+ insert_schema : DataSchemaRef ,
137+ cast_needed : bool ,
138+ ) -> PhysicalPlan {
139+ PhysicalPlan :: new ( TableWritePrepare {
140+ meta : PhysicalPlanMeta :: new ( "TableWritePrepare" ) ,
141+ input,
142+ table_info : table. get_table_info ( ) . clone ( ) ,
143+ insert_schema,
144+ select_schema,
145+ select_column_bindings,
146+ cast_needed,
147+ } )
148+ }
149+
134150/// Build the INSERT SELECT physical plan (including Paimon route/exchange when needed).
135151pub fn build_insert_select_physical_plan (
136152 select_plan : PhysicalPlan ,
@@ -139,24 +155,25 @@ pub fn build_insert_select_physical_plan(
139155 insert_schema : DataSchemaRef ,
140156 table : Arc < dyn Table > ,
141157 cast_needed : bool ,
158+ input_prepared : bool ,
142159 table_meta_timestamps : TableMetaTimestamps ,
143160 distributed : bool ,
144161) -> Result < PhysicalPlan > {
145162 let table_info = table. get_table_info ( ) . clone ( ) ;
146163 let needs_pk_route = is_fixed_bucket_primary_key ( & table) ?;
147164
148165 let prepare_and_route = |input : PhysicalPlan | -> Result < PhysicalPlan > {
149- let prepared = PhysicalPlan :: new ( PaimonWritePrepare {
150- meta : PhysicalPlanMeta :: new ( "PaimonWritePrepare" ) ,
166+ let prepared = prepare_table_write_input (
151167 input,
152- table_info : table_info . clone ( ) ,
153- insert_schema : insert_schema . clone ( ) ,
154- select_schema : select_schema . clone ( ) ,
155- select_column_bindings : select_column_bindings . clone ( ) ,
168+ & table ,
169+ select_schema . clone ( ) ,
170+ select_column_bindings . clone ( ) ,
171+ insert_schema . clone ( ) ,
156172 cast_needed,
157- } ) ;
173+ ) ;
158174 wrap_paimon_write_distribution ( prepared, table. clone ( ) )
159175 } ;
176+ let input_prepared = input_prepared || needs_pk_route;
160177
161178 if table. support_distributed_insert ( )
162179 && let Some ( exchange) = Exchange :: from_physical_plan ( & select_plan)
@@ -173,7 +190,7 @@ pub fn build_insert_select_physical_plan(
173190 select_column_bindings,
174191 insert_schema,
175192 cast_needed,
176- input_prepared : needs_pk_route ,
193+ input_prepared,
177194 table_meta_timestamps,
178195 meta : PhysicalPlanMeta :: new ( "DistributedInsertSelect" ) ,
179196 } ) ;
@@ -198,12 +215,12 @@ pub fn build_insert_select_physical_plan(
198215 select_column_bindings,
199216 insert_schema,
200217 cast_needed,
201- input_prepared : needs_pk_route ,
218+ input_prepared,
202219 table_meta_timestamps,
203220 meta : PhysicalPlanMeta :: new ( "DistributedInsertSelect" ) ,
204221 } ) ;
205- // VALUES / local select has no top Merge; synthesize one for PK so commit metas gather.
206- if needs_pk_route && distributed {
222+ // VALUES / local select has no top Merge; synthesize one so commit metas gather.
223+ if input_prepared && distributed {
207224 Ok ( PhysicalPlan :: new ( Exchange {
208225 input : insert,
209226 kind : FragmentKind :: Merge ,
@@ -289,45 +306,40 @@ impl InsertInterpreter {
289306 & self ,
290307 input : PhysicalPlan ,
291308 table : & Arc < dyn Table > ,
309+ select_schema : & DataSchemaRef ,
292310 insert_schema : & DataSchemaRef ,
293311 select_column_bindings : & [ ColumnBinding ] ,
294312 metadata : & MetadataRef ,
295313 cast_needed : bool ,
296- ) -> Result < PhysicalPlan > {
314+ ) -> Result < ( PhysicalPlan , bool ) > {
297315 let Ok ( fuse_table) = FuseTable :: try_from_table ( table. as_ref ( ) ) else {
298- return Ok ( input) ;
316+ return Ok ( ( input, false ) ) ;
299317 } ;
300- if cast_needed || !fuse_table. use_hash_write_distribution ( ) {
301- return Ok ( input) ;
318+ if !fuse_table. use_hash_write_distribution ( ) {
319+ return Ok ( ( input, false ) ) ;
302320 }
303321
304322 let Some ( partition_info) = fuse_table. partition_pruning_info ( self . ctx . clone ( ) ) else {
305- return Ok ( input) ;
323+ return Ok ( ( input, false ) ) ;
306324 } ;
325+ let input = prepare_table_write_input (
326+ input,
327+ table,
328+ select_schema. clone ( ) ,
329+ select_column_bindings. to_vec ( ) ,
330+ insert_schema. clone ( ) ,
331+ cast_needed,
332+ ) ;
307333 let input_schema = input. output_schema ( ) ?;
308334 let mut partition_exprs = Vec :: with_capacity ( partition_info. partition_keys . len ( ) ) ;
309335 for partition_key in partition_info. partition_keys {
310336 let expr = partition_key. as_expr ( & BUILTIN_FUNCTIONS ) ;
311- if expr
312- . column_refs ( )
313- . keys ( )
314- . any ( |name| insert_schema. index_of ( name) . is_err ( ) )
315- {
316- return Ok ( input) ;
317- }
318- partition_exprs. push ( expr. project_column_ref ( |name| {
319- let position = insert_schema. index_of ( name) ?;
320- let binding = select_column_bindings. get ( position) . ok_or_else ( || {
321- ErrorCode :: Internal ( "INSERT SELECT column binding is missing" )
322- } ) ?;
323- input_schema. index_of ( & binding. index . to_string ( ) )
324- } ) ?) ;
337+ partition_exprs. push ( expr. project_column_ref ( |name| input_schema. index_of ( name) ) ?) ;
325338 }
326339
327340 let input_columns = input_schema. num_fields ( ) ;
328341 let mut eval_exprs = Vec :: with_capacity ( partition_exprs. len ( ) ) ;
329342 let mut hash_keys = Vec :: with_capacity ( partition_exprs. len ( ) ) ;
330- let mut order_by = Vec :: with_capacity ( partition_exprs. len ( ) ) ;
331343 for ( index, expr) in partition_exprs. into_iter ( ) . enumerate ( ) {
332344 let data_type = expr. data_type ( ) . clone ( ) ;
333345 let display_name = format ! ( "partition_key_{index}" ) ;
@@ -341,12 +353,6 @@ impl InsertInterpreter {
341353 data_type,
342354 display_name : display_name. clone ( ) ,
343355 } ) ;
344- order_by. push ( SortDesc {
345- asc : true ,
346- nulls_first : false ,
347- order_by : symbol,
348- display_name,
349- } ) ;
350356 }
351357
352358 let projections: BTreeSet < _ > = ( 0 ..input_columns + eval_exprs. len ( ) ) . collect ( ) ;
@@ -359,17 +365,7 @@ impl InsertInterpreter {
359365 ignore_exchange : false ,
360366 allow_adjust_parallelism : true ,
361367 } ) ;
362- Ok ( PhysicalPlan :: new ( Sort {
363- meta : PhysicalPlanMeta :: new ( "Sort" ) ,
364- input : exchange,
365- order_by,
366- limit : None ,
367- step : SortStep :: Single ,
368- pre_projection : None ,
369- broadcast_id : None ,
370- enable_fixed_rows : self . ctx . get_settings ( ) . get_enable_fixed_rows_sort ( ) ?,
371- stat_info : None ,
372- } ) )
368+ Ok ( ( exchange, true ) )
373369 }
374370}
375371
@@ -455,6 +451,7 @@ impl Interpreter for InsertInterpreter {
455451 insert_schema,
456452 table. clone ( ) ,
457453 false ,
454+ false ,
458455 table_meta_timestamps,
459456 self . ctx . get_cluster ( ) . get_nodes ( ) . len ( ) > 1 ,
460457 ) ?;
@@ -547,39 +544,48 @@ impl Interpreter for InsertInterpreter {
547544
548545 let update_stream_meta = dml_build_update_stream_req ( self . ctx . clone ( ) ) . await ?;
549546
547+ let select_schema = plan. schema ( ) ;
550548 let insert_schema = self . plan . dest_schema ( ) ;
551549 let cast_needed = self . check_schema_cast ( plan) ?;
552- let select_plan = if table1. support_distributed_insert ( )
553- && let Some ( exchange) = Exchange :: from_physical_plan ( & select_plan)
554- {
555- let input = self . build_hash_distributed_input (
556- exchange. input . clone ( ) ,
557- & table1,
558- & insert_schema,
559- & select_column_bindings,
560- metadata,
561- cast_needed,
562- ) ?;
563- exchange. derive ( vec ! [ input] )
550+ let distributed = self . ctx . get_cluster ( ) . get_nodes ( ) . len ( ) > 1 ;
551+ let ( select_plan, input_prepared) = if distributed {
552+ if table1. support_distributed_insert ( )
553+ && let Some ( exchange) = Exchange :: from_physical_plan ( & select_plan)
554+ {
555+ let ( input, input_prepared) = self . build_hash_distributed_input (
556+ exchange. input . clone ( ) ,
557+ & table1,
558+ & select_schema,
559+ & insert_schema,
560+ & select_column_bindings,
561+ metadata,
562+ cast_needed,
563+ ) ?;
564+ ( exchange. derive ( vec ! [ input] ) , input_prepared)
565+ } else {
566+ self . build_hash_distributed_input (
567+ select_plan,
568+ & table1,
569+ & select_schema,
570+ & insert_schema,
571+ & select_column_bindings,
572+ metadata,
573+ cast_needed,
574+ ) ?
575+ }
564576 } else {
565- self . build_hash_distributed_input (
566- select_plan,
567- & table1,
568- & insert_schema,
569- & select_column_bindings,
570- metadata,
571- cast_needed,
572- ) ?
577+ ( select_plan, false )
573578 } ;
574579 let mut insert_select_plan = build_insert_select_physical_plan (
575580 select_plan,
576- plan . schema ( ) ,
581+ select_schema ,
577582 select_column_bindings,
578583 insert_schema,
579584 table1,
580585 cast_needed,
586+ input_prepared,
581587 table_meta_timestamps,
582- self . ctx . get_cluster ( ) . get_nodes ( ) . len ( ) > 1 ,
588+ distributed ,
583589 ) ?;
584590
585591 insert_select_plan. adjust_plan_id ( & mut 0 ) ;
0 commit comments