duckdb 1.4.2 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/extension/core_functions/aggregate/holistic/approximate_quantile.cpp +1 -1
  3. package/src/duckdb/extension/icu/icu_extension.cpp +14 -5
  4. package/src/duckdb/extension/parquet/column_writer.cpp +4 -4
  5. package/src/duckdb/extension/parquet/include/writer/templated_column_writer.hpp +12 -4
  6. package/src/duckdb/src/common/encryption_key_manager.cpp +4 -0
  7. package/src/duckdb/src/common/local_file_system.cpp +23 -0
  8. package/src/duckdb/src/common/types/column/column_data_collection.cpp +6 -0
  9. package/src/duckdb/src/common/types/conflict_manager.cpp +1 -1
  10. package/src/duckdb/src/execution/index/art/base_node.cpp +3 -1
  11. package/src/duckdb/src/execution/index/art/prefix.cpp +5 -8
  12. package/src/duckdb/src/execution/index/bound_index.cpp +68 -25
  13. package/src/duckdb/src/execution/index/unbound_index.cpp +21 -10
  14. package/src/duckdb/src/execution/operator/csv_scanner/scanner/base_scanner.cpp +4 -0
  15. package/src/duckdb/src/execution/operator/csv_scanner/scanner/string_value_scanner.cpp +36 -28
  16. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/csv_sniffer.cpp +3 -2
  17. package/src/duckdb/src/execution/operator/csv_scanner/sniffer/type_detection.cpp +12 -6
  18. package/src/duckdb/src/execution/operator/scan/physical_positional_scan.cpp +8 -4
  19. package/src/duckdb/src/execution/operator/scan/physical_table_scan.cpp +1 -1
  20. package/src/duckdb/src/execution/physical_plan/plan_aggregate.cpp +4 -3
  21. package/src/duckdb/src/execution/physical_plan/plan_distinct.cpp +3 -2
  22. package/src/duckdb/src/execution/physical_plan/plan_filter.cpp +0 -1
  23. package/src/duckdb/src/execution/physical_plan/plan_window.cpp +6 -8
  24. package/src/duckdb/src/function/aggregate/sorted_aggregate_function.cpp +4 -3
  25. package/src/duckdb/src/function/macro_function.cpp +20 -2
  26. package/src/duckdb/src/function/table/system/duckdb_log.cpp +3 -0
  27. package/src/duckdb/src/function/table/system/test_all_types.cpp +26 -13
  28. package/src/duckdb/src/function/table/table_scan.cpp +72 -38
  29. package/src/duckdb/src/function/table/version/pragma_version.cpp +3 -3
  30. package/src/duckdb/src/function/table_function.cpp +24 -0
  31. package/src/duckdb/src/include/duckdb/common/encryption_key_manager.hpp +1 -0
  32. package/src/duckdb/src/include/duckdb/common/limits.hpp +4 -2
  33. package/src/duckdb/src/include/duckdb/common/local_file_system.hpp +2 -0
  34. package/src/duckdb/src/include/duckdb/common/types/row/block_iterator.hpp +2 -0
  35. package/src/duckdb/src/include/duckdb/execution/index/art/art_operator.hpp +2 -0
  36. package/src/duckdb/src/include/duckdb/execution/index/art/prefix.hpp +2 -2
  37. package/src/duckdb/src/include/duckdb/execution/index/bound_index.hpp +1 -1
  38. package/src/duckdb/src/include/duckdb/execution/index/unbound_index.hpp +41 -7
  39. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/base_scanner.hpp +15 -1
  40. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/sniffer/csv_sniffer.hpp +1 -0
  41. package/src/duckdb/src/include/duckdb/execution/operator/csv_scanner/string_value_scanner.hpp +2 -1
  42. package/src/duckdb/src/include/duckdb/execution/physical_plan_generator.hpp +3 -1
  43. package/src/duckdb/src/include/duckdb/function/function_binder.hpp +2 -1
  44. package/src/duckdb/src/include/duckdb/function/table_function.hpp +2 -0
  45. package/src/duckdb/src/include/duckdb/main/db_instance_cache.hpp +5 -0
  46. package/src/duckdb/src/include/duckdb/main/extension_entries.hpp +2 -0
  47. package/src/duckdb/src/include/duckdb/optimizer/filter_combiner.hpp +1 -0
  48. package/src/duckdb/src/include/duckdb/optimizer/join_order/relation_manager.hpp +4 -4
  49. package/src/duckdb/src/include/duckdb/optimizer/rule/ordered_aggregate_optimizer.hpp +3 -1
  50. package/src/duckdb/src/include/duckdb/parser/parsed_data/sample_options.hpp +3 -0
  51. package/src/duckdb/src/include/duckdb/planner/binder.hpp +1 -1
  52. package/src/duckdb/src/include/duckdb/planner/bound_result_modifier.hpp +4 -2
  53. package/src/duckdb/src/include/duckdb/planner/expression_binder.hpp +1 -2
  54. package/src/duckdb/src/include/duckdb/planner/subquery/flatten_dependent_join.hpp +1 -1
  55. package/src/duckdb/src/include/duckdb/planner/subquery/rewrite_cte_scan.hpp +3 -1
  56. package/src/duckdb/src/include/duckdb/storage/table/chunk_info.hpp +3 -3
  57. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +2 -6
  58. package/src/duckdb/src/include/duckdb/storage/table/row_version_manager.hpp +4 -1
  59. package/src/duckdb/src/include/duckdb/storage/table/validity_column_data.hpp +2 -0
  60. package/src/duckdb/src/logging/log_storage.cpp +17 -23
  61. package/src/duckdb/src/main/capi/duckdb-c.cpp +1 -1
  62. package/src/duckdb/src/main/connection.cpp +0 -5
  63. package/src/duckdb/src/main/database_manager.cpp +12 -9
  64. package/src/duckdb/src/main/db_instance_cache.cpp +15 -1
  65. package/src/duckdb/src/main/extension/extension_alias.cpp +1 -0
  66. package/src/duckdb/src/optimizer/filter_combiner.cpp +38 -4
  67. package/src/duckdb/src/optimizer/join_order/relation_manager.cpp +15 -15
  68. package/src/duckdb/src/optimizer/late_materialization.cpp +5 -0
  69. package/src/duckdb/src/optimizer/rule/ordered_aggregate_optimizer.cpp +6 -3
  70. package/src/duckdb/src/parser/transform/helpers/transform_sample.cpp +3 -2
  71. package/src/duckdb/src/planner/binder/expression/bind_star_expression.cpp +1 -1
  72. package/src/duckdb/src/planner/binder/query_node/plan_select_node.cpp +1 -1
  73. package/src/duckdb/src/planner/binder/statement/bind_copy.cpp +4 -1
  74. package/src/duckdb/src/planner/binder/statement/bind_insert.cpp +17 -10
  75. package/src/duckdb/src/planner/binder.cpp +3 -3
  76. package/src/duckdb/src/planner/bound_result_modifier.cpp +22 -5
  77. package/src/duckdb/src/planner/expression/bound_function_expression.cpp +4 -1
  78. package/src/duckdb/src/planner/expression_binder/constant_binder.cpp +1 -1
  79. package/src/duckdb/src/planner/expression_binder.cpp +1 -2
  80. package/src/duckdb/src/planner/subquery/flatten_dependent_join.cpp +57 -24
  81. package/src/duckdb/src/planner/subquery/rewrite_cte_scan.cpp +5 -3
  82. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +9 -0
  83. package/src/duckdb/src/storage/storage_info.cpp +2 -0
  84. package/src/duckdb/src/storage/table/chunk_info.cpp +3 -3
  85. package/src/duckdb/src/storage/table/column_data.cpp +5 -1
  86. package/src/duckdb/src/storage/table/column_data_checkpointer.cpp +1 -1
  87. package/src/duckdb/src/storage/table/column_segment.cpp +3 -1
  88. package/src/duckdb/src/storage/table/row_group.cpp +6 -8
  89. package/src/duckdb/src/storage/table/row_group_collection.cpp +41 -1
  90. package/src/duckdb/src/storage/table/row_version_manager.cpp +37 -23
  91. package/src/duckdb/src/storage/table/standard_column_data.cpp +5 -5
  92. package/src/duckdb/src/storage/table/validity_column_data.cpp +17 -0
@@ -1053,7 +1053,7 @@ RowGroupPointer RowGroup::Checkpoint(RowGroupWriteData write_data, RowGroupWrite
1053
1053
  row_group_pointer.data_pointers = column_pointers;
1054
1054
  row_group_pointer.has_metadata_blocks = true;
1055
1055
  row_group_pointer.extra_metadata_blocks = write_data.existing_extra_metadata_blocks;
1056
- row_group_pointer.deletes_pointers = deletes_pointers;
1056
+ row_group_pointer.deletes_pointers = CheckpointDeletes(*metadata_manager);
1057
1057
  vector<MetaBlockPointer> extra_metadata_block_pointers;
1058
1058
  extra_metadata_block_pointers.reserve(write_data.existing_extra_metadata_blocks.size());
1059
1059
  for (auto &block_pointer : write_data.existing_extra_metadata_blocks) {
@@ -1061,7 +1061,6 @@ RowGroupPointer RowGroup::Checkpoint(RowGroupWriteData write_data, RowGroupWrite
1061
1061
  }
1062
1062
  metadata_manager->ClearModifiedBlocks(column_pointers);
1063
1063
  metadata_manager->ClearModifiedBlocks(extra_metadata_block_pointers);
1064
- metadata_manager->ClearModifiedBlocks(deletes_pointers);
1065
1064
  // remember metadata_blocks to avoid loading them on future checkpoints
1066
1065
  has_metadata_blocks = true;
1067
1066
  extra_metadata_blocks = row_group_pointer.extra_metadata_blocks;
@@ -1109,14 +1108,13 @@ RowGroupPointer RowGroup::Checkpoint(RowGroupWriteData write_data, RowGroupWrite
1109
1108
  row_group_pointer.extra_metadata_blocks.push_back(column_pointer.block_pointer);
1110
1109
  metadata_blocks.insert(column_pointer.block_pointer);
1111
1110
  }
1111
+ if (metadata_manager) {
1112
+ row_group_pointer.deletes_pointers = CheckpointDeletes(*metadata_manager);
1113
+ }
1112
1114
  // set up the pointers correctly within this row group for future operations
1113
1115
  column_pointers = row_group_pointer.data_pointers;
1114
1116
  has_metadata_blocks = true;
1115
1117
  extra_metadata_blocks = row_group_pointer.extra_metadata_blocks;
1116
-
1117
- if (metadata_manager) {
1118
- row_group_pointer.deletes_pointers = CheckpointDeletes(*metadata_manager);
1119
- }
1120
1118
  Verify();
1121
1119
  return row_group_pointer;
1122
1120
  }
@@ -1125,11 +1123,11 @@ bool RowGroup::HasChanges() const {
1125
1123
  if (has_changes) {
1126
1124
  return true;
1127
1125
  }
1128
- if (version_info.load()) {
1126
+ auto version_info_loaded = version_info.load();
1127
+ if (version_info_loaded && version_info_loaded->HasUnserializedChanges()) {
1129
1128
  // we have deletes
1130
1129
  return true;
1131
1130
  }
1132
- D_ASSERT(!deletes_is_loaded.load());
1133
1131
  // check if any of the columns have changes
1134
1132
  // avoid loading unloaded columns - unloaded columns can never have changes
1135
1133
  for (idx_t c = 0; c < columns.size(); c++) {
@@ -14,6 +14,7 @@
14
14
  #include "duckdb/storage/table/column_checkpoint_state.hpp"
15
15
  #include "duckdb/storage/table/persistent_table_data.hpp"
16
16
  #include "duckdb/storage/table/row_group_segment_tree.hpp"
17
+ #include "duckdb/storage/table/row_version_manager.hpp"
17
18
  #include "duckdb/storage/table/scan_state.hpp"
18
19
  #include "duckdb/storage/table_storage_info.hpp"
19
20
  #include "duckdb/main/settings.hpp"
@@ -505,6 +506,11 @@ void RowGroupCollection::RevertAppendInternal(idx_t start_row) {
505
506
  if (segment.start == start_row) {
506
507
  // we are truncating exactly this row group - erase it entirely
507
508
  row_groups->EraseSegments(l, segment_index);
509
+ if (segment_index > 0) {
510
+ // if we have a previous segment, we need to update the next pointer
511
+ auto previous_segment = row_groups->GetSegmentByIndex(l, UnsafeNumericCast<int64_t>(segment_index - 1));
512
+ previous_segment->next = nullptr;
513
+ }
508
514
  } else {
509
515
  // we need to truncate within a row group
510
516
  // remove any segments AFTER this segment: they should be deleted entirely
@@ -1167,7 +1173,7 @@ void RowGroupCollection::Checkpoint(TableDataWriter &writer, TableStatistics &gl
1167
1173
  extra_metadata_block_pointers.emplace_back(block_pointer, 0);
1168
1174
  }
1169
1175
  metadata_manager.ClearModifiedBlocks(extra_metadata_block_pointers);
1170
- metadata_manager.ClearModifiedBlocks(row_group.GetDeletesPointers());
1176
+ row_group.CheckpointDeletes(metadata_manager);
1171
1177
  row_groups->AppendSegment(l, std::move(entry.node));
1172
1178
  }
1173
1179
  writer.WriteUnchangedTable(metadata_pointer, total_rows.load());
@@ -1285,6 +1291,40 @@ void RowGroupCollection::Checkpoint(TableDataWriter &writer, TableStatistics &gl
1285
1291
 
1286
1292
  throw InternalException("Reloading blocks just written does not yield same blocks: " + oss.str());
1287
1293
  }
1294
+
1295
+ vector<MetaBlockPointer> read_deletes_pointers;
1296
+ if (!pointer_copy.deletes_pointers.empty()) {
1297
+ auto root_delete = pointer_copy.deletes_pointers[0];
1298
+ auto vm = RowVersionManager::Deserialize(root_delete, GetBlockManager().GetMetadataManager(),
1299
+ row_group.start);
1300
+ read_deletes_pointers = vm->GetStoragePointers();
1301
+ }
1302
+
1303
+ set<idx_t> all_written_deletes_block_ids;
1304
+ for (auto &ptr : pointer_copy.deletes_pointers) {
1305
+ all_written_deletes_block_ids.insert(ptr.block_pointer);
1306
+ }
1307
+ set<idx_t> all_read_deletes_block_ids;
1308
+ for (auto &ptr : read_deletes_pointers) {
1309
+ all_read_deletes_block_ids.insert(ptr.block_pointer);
1310
+ }
1311
+
1312
+ if (all_written_deletes_block_ids != all_read_deletes_block_ids) {
1313
+ std::stringstream oss;
1314
+ oss << "Written: ";
1315
+ for (auto &block : all_written_deletes_block_ids) {
1316
+ oss << block << ", ";
1317
+ }
1318
+ oss << "\n";
1319
+ oss << "Read: ";
1320
+ for (auto &block : all_read_deletes_block_ids) {
1321
+ oss << block << ", ";
1322
+ }
1323
+ oss << "\n";
1324
+
1325
+ throw InternalException("Reloading deletes blocks just written does not yield same blocks: " +
1326
+ oss.str());
1327
+ }
1288
1328
  }
1289
1329
  }
1290
1330
  total_rows = new_total_rows;
@@ -7,7 +7,7 @@
7
7
 
8
8
  namespace duckdb {
9
9
 
10
- RowVersionManager::RowVersionManager(idx_t start) noexcept : start(start), has_changes(false) {
10
+ RowVersionManager::RowVersionManager(idx_t start) noexcept : start(start), has_unserialized_changes(false) {
11
11
  }
12
12
 
13
13
  void RowVersionManager::SetStart(idx_t new_start) {
@@ -88,7 +88,7 @@ void RowVersionManager::FillVectorInfo(idx_t vector_idx) {
88
88
  void RowVersionManager::AppendVersionInfo(TransactionData transaction, idx_t count, idx_t row_group_start,
89
89
  idx_t row_group_end) {
90
90
  lock_guard<mutex> lock(version_lock);
91
- has_changes = true;
91
+ has_unserialized_changes = true;
92
92
  idx_t start_vector_idx = row_group_start / STANDARD_VECTOR_SIZE;
93
93
  idx_t end_vector_idx = (row_group_end - 1) / STANDARD_VECTOR_SIZE;
94
94
 
@@ -141,6 +141,7 @@ void RowVersionManager::CommitAppend(transaction_t commit_id, idx_t row_group_st
141
141
  idx_t vend =
142
142
  vector_idx == end_vector_idx ? row_group_end - end_vector_idx * STANDARD_VECTOR_SIZE : STANDARD_VECTOR_SIZE;
143
143
  auto &info = *vector_info[vector_idx];
144
+ D_ASSERT(has_unserialized_changes);
144
145
  info.CommitAppend(commit_id, vstart, vend);
145
146
  }
146
147
  }
@@ -167,10 +168,12 @@ void RowVersionManager::CleanupAppend(transaction_t lowest_active_transaction, i
167
168
  }
168
169
  auto &info = *vector_info[vector_idx];
169
170
  // if we wrote the entire chunk info try to compress it
170
- unique_ptr<ChunkInfo> new_info;
171
- auto cleanup = info.Cleanup(lowest_active_transaction, new_info);
171
+ auto cleanup = info.Cleanup(lowest_active_transaction);
172
172
  if (cleanup) {
173
- vector_info[vector_idx] = std::move(new_info);
173
+ if (info.HasDeletes()) {
174
+ has_unserialized_changes = true;
175
+ }
176
+ vector_info[vector_idx].reset();
174
177
  }
175
178
  }
176
179
  }
@@ -179,6 +182,7 @@ void RowVersionManager::RevertAppend(idx_t start_row) {
179
182
  lock_guard<mutex> lock(version_lock);
180
183
  idx_t start_vector_idx = (start_row + (STANDARD_VECTOR_SIZE - 1)) / STANDARD_VECTOR_SIZE;
181
184
  for (idx_t vector_idx = start_vector_idx; vector_idx < vector_info.size(); vector_idx++) {
185
+ D_ASSERT(has_unserialized_changes);
182
186
  vector_info[vector_idx].reset();
183
187
  }
184
188
  }
@@ -205,19 +209,19 @@ ChunkVectorInfo &RowVersionManager::GetVectorInfo(idx_t vector_idx) {
205
209
 
206
210
  idx_t RowVersionManager::DeleteRows(idx_t vector_idx, transaction_t transaction_id, row_t rows[], idx_t count) {
207
211
  lock_guard<mutex> lock(version_lock);
208
- has_changes = true;
212
+ has_unserialized_changes = true;
209
213
  return GetVectorInfo(vector_idx).Delete(transaction_id, rows, count);
210
214
  }
211
215
 
212
216
  void RowVersionManager::CommitDelete(idx_t vector_idx, transaction_t commit_id, const DeleteInfo &info) {
213
217
  lock_guard<mutex> lock(version_lock);
214
- has_changes = true;
218
+ has_unserialized_changes = true;
215
219
  GetVectorInfo(vector_idx).CommitDelete(commit_id, info);
216
220
  }
217
221
 
218
222
  vector<MetaBlockPointer> RowVersionManager::Checkpoint(MetadataManager &manager) {
219
- if (!has_changes && !storage_pointers.empty()) {
220
- // the row version manager already exists on disk and no changes were made
223
+ lock_guard<mutex> lock(version_lock);
224
+ if (!has_unserialized_changes) {
221
225
  // we can write the current pointer as-is
222
226
  // ensure the blocks we are pointing to are not marked as free
223
227
  manager.ClearModifiedBlocks(storage_pointers);
@@ -236,24 +240,23 @@ vector<MetaBlockPointer> RowVersionManager::Checkpoint(MetadataManager &manager)
236
240
  }
237
241
  to_serialize.emplace_back(vector_idx, *chunk_info);
238
242
  }
239
- if (to_serialize.empty()) {
240
- return vector<MetaBlockPointer>();
241
- }
242
243
 
243
244
  storage_pointers.clear();
244
245
 
245
- MetadataWriter writer(manager, &storage_pointers);
246
- // now serialize the actual version information
247
- writer.Write<idx_t>(to_serialize.size());
248
- for (auto &entry : to_serialize) {
249
- auto &vector_idx = entry.first;
250
- auto &chunk_info = entry.second.get();
251
- writer.Write<idx_t>(vector_idx);
252
- chunk_info.Write(writer);
246
+ if (!to_serialize.empty()) {
247
+ MetadataWriter writer(manager, &storage_pointers);
248
+ // now serialize the actual version information
249
+ writer.Write<idx_t>(to_serialize.size());
250
+ for (auto &entry : to_serialize) {
251
+ auto &vector_idx = entry.first;
252
+ auto &chunk_info = entry.second.get();
253
+ writer.Write<idx_t>(vector_idx);
254
+ chunk_info.Write(writer);
255
+ }
256
+ writer.Flush();
253
257
  }
254
- writer.Flush();
255
258
 
256
- has_changes = false;
259
+ has_unserialized_changes = false;
257
260
  return storage_pointers;
258
261
  }
259
262
 
@@ -277,8 +280,19 @@ shared_ptr<RowVersionManager> RowVersionManager::Deserialize(MetaBlockPointer de
277
280
  version_info->FillVectorInfo(vector_index);
278
281
  version_info->vector_info[vector_index] = ChunkInfo::Read(source);
279
282
  }
280
- version_info->has_changes = false;
283
+ version_info->has_unserialized_changes = false;
281
284
  return version_info;
282
285
  }
283
286
 
287
+ bool RowVersionManager::HasUnserializedChanges() {
288
+ lock_guard<mutex> lock(version_lock);
289
+ return has_unserialized_changes;
290
+ }
291
+
292
+ vector<MetaBlockPointer> RowVersionManager::GetStoragePointers() {
293
+ lock_guard<mutex> lock(version_lock);
294
+ D_ASSERT(!has_unserialized_changes);
295
+ return storage_pointers;
296
+ }
297
+
284
298
  } // namespace duckdb
@@ -170,12 +170,12 @@ void StandardColumnData::UpdateColumn(TransactionData transaction, DataTable &da
170
170
  const vector<column_t> &column_path, Vector &update_vector, row_t *row_ids,
171
171
  idx_t update_count, idx_t depth) {
172
172
  if (depth >= column_path.size()) {
173
- // update this column
173
+ // Update the column.
174
174
  ColumnData::Update(transaction, data_table, column_path[0], update_vector, row_ids, update_count);
175
- } else {
176
- // update the child column (i.e. the validity column)
177
- validity.UpdateColumn(transaction, data_table, column_path, update_vector, row_ids, update_count, depth + 1);
175
+ return;
178
176
  }
177
+ // Update the child column, which is the validity column.
178
+ validity.UpdateWithBase(transaction, data_table, column_path[0], update_vector, row_ids, update_count, *this);
179
179
  }
180
180
 
181
181
  unique_ptr<BaseStatistics> StandardColumnData::GetUpdateStatistics() {
@@ -200,8 +200,8 @@ void StandardColumnData::FetchRow(TransactionData transaction, ColumnFetchState
200
200
  auto child_state = make_uniq<ColumnFetchState>();
201
201
  state.child_states.push_back(std::move(child_state));
202
202
  }
203
- validity.FetchRow(transaction, *state.child_states[0], row_id, result, result_idx);
204
203
  ColumnData::FetchRow(transaction, state, row_id, result, result_idx);
204
+ validity.FetchRow(transaction, *state.child_states[0], row_id, result, result_idx);
205
205
  }
206
206
 
207
207
  void StandardColumnData::CommitDropColumn() {
@@ -1,6 +1,7 @@
1
1
  #include "duckdb/storage/table/validity_column_data.hpp"
2
2
  #include "duckdb/storage/table/scan_state.hpp"
3
3
  #include "duckdb/storage/table/update_segment.hpp"
4
+ #include "duckdb/storage/table/standard_column_data.hpp"
4
5
 
5
6
  namespace duckdb {
6
7
 
@@ -13,6 +14,22 @@ FilterPropagateResult ValidityColumnData::CheckZonemap(ColumnScanState &state, T
13
14
  return FilterPropagateResult::NO_PRUNING_POSSIBLE;
14
15
  }
15
16
 
17
+ void ValidityColumnData::UpdateWithBase(TransactionData transaction, DataTable &data_table, idx_t column_index,
18
+ Vector &update_vector, row_t *row_ids, idx_t update_count, ColumnData &base) {
19
+ Vector base_vector(base.type);
20
+ ColumnScanState validity_scan_state;
21
+ FetchUpdateData(validity_scan_state, row_ids, base_vector);
22
+
23
+ if (validity_scan_state.current->GetCompressionFunction().type == CompressionType::COMPRESSION_EMPTY) {
24
+ // The validity is actually covered by the data, so we read it to get the validity for UpdateInternal.
25
+ ColumnScanState data_scan_state;
26
+ auto fetch_count = base.Fetch(data_scan_state, row_ids[0], base_vector);
27
+ base_vector.Flatten(fetch_count);
28
+ }
29
+
30
+ UpdateInternal(transaction, data_table, column_index, update_vector, row_ids, update_count, base_vector);
31
+ }
32
+
16
33
  void ValidityColumnData::AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata,
17
34
  idx_t count) {
18
35
  lock_guard<mutex> l(stats_lock);