@@ -80,15 +80,17 @@ InsertGlobalState::InsertGlobalState(ClientContext &context, const vector<Logica
8080 : table(table), insert_count(0 ), initialized(false ), return_collection(context, return_types) {
8181}
8282
83- InsertLocalState::InsertLocalState (ClientContext &context, const vector<LogicalType> &types ,
83+ InsertLocalState::InsertLocalState (ClientContext &context, const vector<LogicalType> &types_p ,
8484 const vector<unique_ptr<Expression>> &bound_defaults,
8585 const vector<unique_ptr<BoundConstraint>> &bound_constraints)
8686 : default_executor(context, bound_defaults), bound_constraints(bound_constraints) {
8787
8888 auto &allocator = Allocator::Get (context);
89- insert_chunk.Initialize (allocator, types);
90- update_chunk.Initialize (allocator, types);
91- append_chunk.Initialize (allocator, types);
89+
90+ types = types_p;
91+ auto initialize = vector<bool >(types.size (), false );
92+ update_chunk.Initialize (allocator, types, initialize);
93+ append_chunk.Initialize (allocator, types, initialize);
9294}
9395
9496ConstraintState &InsertLocalState::GetConstraintState (DataTable &table, TableCatalogEntry &table_ref) {
@@ -185,8 +187,10 @@ static void CombineExistingAndInsertTuples(DataChunk &result, DataChunk &scan_ch
185187 auto &insert_types = op.insert_types ;
186188
187189 if (types_to_fetch.empty ()) {
188- // We have not scanned the initial table, so we can just duplicate the initial chunk
189- result.Initialize (client, input_chunk.GetTypes ());
190+ // We have not scanned the initial table, so we duplicate the initial chunk.
191+ const auto &types = input_chunk.GetTypes ();
192+ auto initialize = vector<bool >(types.size (), false );
193+ result.Initialize (client, types, initialize, input_chunk.size ());
190194 result.Reference (input_chunk);
191195 result.SetCardinality (input_chunk);
192196 return ;
@@ -196,7 +200,7 @@ static void CombineExistingAndInsertTuples(DataChunk &result, DataChunk &scan_ch
196200 combined_types.insert (combined_types.end (), insert_types.begin (), insert_types.end ());
197201 combined_types.insert (combined_types.end (), types_to_fetch.begin (), types_to_fetch.end ());
198202
199- result.Initialize (client, combined_types);
203+ result.Initialize (client, combined_types, input_chunk. size () );
200204 result.Reset ();
201205 // Add the VALUES list
202206 for (idx_t i = 0 ; i < insert_types.size (); i++) {
@@ -223,12 +227,13 @@ static void CombineExistingAndInsertTuples(DataChunk &result, DataChunk &scan_ch
223227 result.SetCardinality (input_chunk.size ());
224228}
225229
226- static void CreateUpdateChunk (ExecutionContext &context, DataChunk &chunk, TableCatalogEntry &table, Vector &row_ids ,
227- DataChunk &update_chunk, const PhysicalInsert &op) {
230+ static void CreateUpdateChunk (ExecutionContext &context, DataChunk &chunk, Vector &row_ids, DataChunk &update_chunk ,
231+ const PhysicalInsert &op) {
228232
229233 auto &do_update_condition = op.do_update_condition ;
230234 auto &set_types = op.set_types ;
231235 auto &set_expressions = op.set_expressions ;
236+
232237 // Check the optional condition for the DO UPDATE clause, to filter which rows will be updated
233238 if (do_update_condition) {
234239 DataChunk do_update_filter_result;
@@ -255,8 +260,15 @@ static void CreateUpdateChunk(ExecutionContext &context, DataChunk &chunk, Table
255260 }
256261 }
257262
258- // Execute the SET expressions
259- update_chunk.Initialize (context.client , set_types);
263+ if (chunk.size () == 0 ) {
264+ auto initialize = vector<bool >(set_types.size (), false );
265+ update_chunk.Initialize (context.client , set_types, initialize, chunk.size ());
266+ update_chunk.SetCardinality (chunk);
267+ return ;
268+ }
269+
270+ // Execute the SET expressions.
271+ update_chunk.Initialize (context.client , set_types, chunk.size ());
260272 ExpressionExecutor executor (context.client , set_expressions);
261273 executor.Execute (chunk, update_chunk);
262274 update_chunk.SetCardinality (chunk);
@@ -272,7 +284,7 @@ static idx_t PerformOnConflictAction(InsertLocalState &lstate, ExecutionContext
272284
273285 auto &set_columns = op.set_columns ;
274286 DataChunk update_chunk;
275- CreateUpdateChunk (context, chunk, table, row_ids, update_chunk, op);
287+ CreateUpdateChunk (context, chunk, row_ids, update_chunk, op);
276288 auto &data_table = table.GetStorage ();
277289
278290 // Perform the UPDATE on the (global) storage.
@@ -476,7 +488,9 @@ static idx_t HandleInsertConflicts(TableCatalogEntry &table, ExecutionContext &c
476488 DataChunk combined_chunk; // contains conflict_chunk + scan_chunk (wide)
477489
478490 // Filter out everything but the conflicting rows
479- conflict_chunk.Initialize (context.client , tuples.GetTypes ());
491+ const auto &types = tuples.GetTypes ();
492+ auto initialize = vector<bool >(types.size (), false );
493+ conflict_chunk.Initialize (context.client , types, initialize, tuples.size ());
480494 conflict_chunk.Reference (tuples);
481495 conflict_chunk.Slice (conflicts.Selection (), conflicts.Count ());
482496 conflict_chunk.SetCardinality (conflicts.Count ());
@@ -487,7 +501,7 @@ static idx_t HandleInsertConflicts(TableCatalogEntry &table, ExecutionContext &c
487501 D_ASSERT (scan_chunk.size () == 0 );
488502 // When these values are required for the conditions or the SET expressions,
489503 // then we scan the existing table for the conflicting tuples, using the rowids
490- scan_chunk.Initialize (context.client , types_to_fetch);
504+ scan_chunk.Initialize (context.client , types_to_fetch, conflicts. Count () );
491505 fetch_state = make_uniq<ColumnFetchState>();
492506 if (GLOBAL) {
493507 auto &transaction = DuckTransaction::Get (context.client , table.catalog );
@@ -520,7 +534,7 @@ static idx_t HandleInsertConflicts(TableCatalogEntry &table, ExecutionContext &c
520534 return affected_tuples;
521535}
522536
523- idx_t PhysicalInsert::OnConflictHandling (TableCatalogEntry &table, ExecutionContext &context, InsertGlobalState &gstate,
537+ idx_t PhysicalInsert::OnConflictHandling (TableCatalogEntry &table, ExecutionContext &context,
524538 InsertLocalState &lstate) const {
525539 auto &data_table = table.GetStorage ();
526540 auto &local_storage = LocalStorage::Get (context.client , data_table.db );
@@ -620,6 +634,21 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, DataChunk &chunk,
620634
621635 auto &table = gstate.table ;
622636 auto &storage = table.GetStorage ();
637+ if (lstate.init_insert_chunk ) {
638+ auto initialize = vector<bool >(lstate.types .size (), false );
639+ if (!column_index_map.empty ()) {
640+ for (auto &col : table.GetColumns ().Physical ()) {
641+ auto storage_idx = col.StorageOid ();
642+ auto mapped_index = column_index_map[col.Physical ()];
643+ if (mapped_index == DConstants::INVALID_INDEX) {
644+ initialize[storage_idx] = true ;
645+ }
646+ }
647+ }
648+ auto &allocator = Allocator::Get (context.client );
649+ lstate.insert_chunk .Initialize (allocator, lstate.types , initialize, chunk.size ());
650+ lstate.init_insert_chunk = false ;
651+ }
623652 PhysicalInsert::ResolveDefaults (table, chunk, column_index_map, lstate.default_executor , lstate.insert_chunk );
624653
625654 if (!parallel) {
@@ -634,7 +663,7 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, DataChunk &chunk,
634663 // so it should not be added to the RETURNING chunk
635664 gstate.return_collection .Append (lstate.insert_chunk );
636665 }
637- idx_t updated_tuples = OnConflictHandling (table, context, gstate, lstate);
666+ idx_t updated_tuples = OnConflictHandling (table, context, lstate);
638667 if (action_type == OnConflictAction::NOTHING && return_chunk) {
639668 // Because we didn't add to the RETURNING chunk yet
640669 // we add the tuples that did not get filtered out now
@@ -665,7 +694,7 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, DataChunk &chunk,
665694 lstate.local_collection ->InitializeAppend (lstate.local_append_state );
666695 lstate.writer = &gstate.table .GetStorage ().CreateOptimisticWriter (context.client );
667696 }
668- OnConflictHandling (table, context, gstate, lstate);
697+ OnConflictHandling (table, context, lstate);
669698 D_ASSERT (action_type != OnConflictAction::UPDATE);
670699
671700 auto new_row_group = lstate.local_collection ->Append (lstate.insert_chunk , lstate.local_append_state );
0 commit comments