duckdb 0.7.2-dev2366.0 → 0.7.2-dev2410.0
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.
- package/package.json +1 -1
- package/src/duckdb/src/common/enums/physical_operator_type.cpp +2 -0
- package/src/duckdb/src/common/file_buffer.cpp +8 -0
- package/src/duckdb/src/common/radix_partitioning.cpp +34 -0
- package/src/duckdb/src/common/sort/partition_state.cpp +44 -124
- package/src/duckdb/src/common/sort/sorted_block.cpp +1 -1
- package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +144 -31
- package/src/duckdb/src/execution/operator/join/physical_asof_join.cpp +698 -0
- package/src/duckdb/src/execution/physical_plan/plan_asof_join.cpp +7 -1
- package/src/duckdb/src/function/scalar/list/list_sort.cpp +30 -56
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/enums/debug_initialize.hpp +17 -0
- package/src/duckdb/src/include/duckdb/common/enums/order_type.hpp +8 -0
- package/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +1 -0
- package/src/duckdb/src/include/duckdb/common/file_buffer.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/radix_partitioning.hpp +3 -0
- package/src/duckdb/src/include/duckdb/common/sort/partition_state.hpp +11 -60
- package/src/duckdb/src/include/duckdb/execution/operator/join/outer_join_marker.hpp +6 -1
- package/src/duckdb/src/include/duckdb/execution/operator/join/physical_asof_join.hpp +93 -0
- package/src/duckdb/src/include/duckdb/execution/physical_operator.hpp +1 -1
- package/src/duckdb/src/include/duckdb/main/client_config.hpp +2 -0
- package/src/duckdb/src/include/duckdb/main/config.hpp +7 -2
- package/src/duckdb/src/include/duckdb/main/settings.hpp +13 -3
- package/src/duckdb/src/include/duckdb/parser/expression/window_expression.hpp +4 -2
- package/src/duckdb/src/include/duckdb/storage/block_manager.hpp +1 -0
- package/src/duckdb/src/include/duckdb/storage/in_memory_block_manager.hpp +3 -0
- package/src/duckdb/src/include/duckdb/storage/partial_block_manager.hpp +2 -1
- package/src/duckdb/src/include/duckdb/storage/single_file_block_manager.hpp +11 -5
- package/src/duckdb/src/main/config.cpp +26 -0
- package/src/duckdb/src/main/settings/settings.cpp +31 -8
- package/src/duckdb/src/planner/binder/expression/bind_aggregate_expression.cpp +2 -5
- package/src/duckdb/src/planner/binder/expression/bind_window_expression.cpp +6 -14
- package/src/duckdb/src/planner/binder/query_node/bind_select_node.cpp +2 -5
- package/src/duckdb/src/storage/buffer/block_manager.cpp +1 -2
- package/src/duckdb/src/storage/meta_block_writer.cpp +4 -0
- package/src/duckdb/src/storage/partial_block_manager.cpp +11 -4
- package/src/duckdb/src/storage/single_file_block_manager.cpp +16 -9
- package/src/duckdb/src/storage/standard_buffer_manager.cpp +5 -2
- package/src/duckdb/src/storage/storage_manager.cpp +7 -2
- package/src/duckdb/src/storage/table/column_checkpoint_state.cpp +21 -1
- package/src/duckdb/ub_src_execution_operator_join.cpp +2 -0
@@ -142,7 +142,7 @@ Value DebugForceNoCrossProduct::GetSetting(ClientContext &context) {
|
|
142
142
|
}
|
143
143
|
|
144
144
|
//===--------------------------------------------------------------------===//
|
145
|
-
//
|
145
|
+
// Ordered Aggregate Threshold
|
146
146
|
//===--------------------------------------------------------------------===//
|
147
147
|
|
148
148
|
void OrderedAggregateThreshold::ResetLocal(ClientContext &context) {
|
@@ -185,6 +185,21 @@ Value DebugWindowMode::GetSetting(ClientContext &context) {
|
|
185
185
|
return Value();
|
186
186
|
}
|
187
187
|
|
188
|
+
//===--------------------------------------------------------------------===//
|
189
|
+
// Debug AsOf Join
|
190
|
+
//===--------------------------------------------------------------------===//
|
191
|
+
void DebugAsOfIEJoin::ResetLocal(ClientContext &context) {
|
192
|
+
ClientConfig::GetConfig(context).force_no_cross_product = ClientConfig().force_asof_iejoin;
|
193
|
+
}
|
194
|
+
|
195
|
+
void DebugAsOfIEJoin::SetLocal(ClientContext &context, const Value &input) {
|
196
|
+
ClientConfig::GetConfig(context).force_asof_iejoin = input.GetValue<bool>();
|
197
|
+
}
|
198
|
+
|
199
|
+
Value DebugAsOfIEJoin::GetSetting(ClientContext &context) {
|
200
|
+
return Value::BOOLEAN(ClientConfig::GetConfig(context).force_asof_iejoin);
|
201
|
+
}
|
202
|
+
|
188
203
|
//===--------------------------------------------------------------------===//
|
189
204
|
// Default Collation
|
190
205
|
//===--------------------------------------------------------------------===//
|
@@ -253,14 +268,18 @@ void DefaultNullOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config,
|
|
253
268
|
auto parameter = StringUtil::Lower(input.ToString());
|
254
269
|
|
255
270
|
if (parameter == "nulls_first" || parameter == "nulls first" || parameter == "null first" || parameter == "first") {
|
256
|
-
config.options.default_null_order =
|
271
|
+
config.options.default_null_order = DefaultOrderByNullType::NULLS_FIRST;
|
257
272
|
} else if (parameter == "nulls_last" || parameter == "nulls last" || parameter == "null last" ||
|
258
273
|
parameter == "last") {
|
259
|
-
config.options.default_null_order =
|
274
|
+
config.options.default_null_order = DefaultOrderByNullType::NULLS_LAST;
|
275
|
+
} else if (parameter == "nulls_first_on_asc_last_on_desc" || parameter == "sqlite" || parameter == "mysql") {
|
276
|
+
config.options.default_null_order = DefaultOrderByNullType::NULLS_FIRST_ON_ASC_LAST_ON_DESC;
|
277
|
+
} else if (parameter == "nulls_last_on_asc_first_on_desc" || parameter == "postgres") {
|
278
|
+
config.options.default_null_order = DefaultOrderByNullType::NULLS_LAST_ON_ASC_FIRST_ON_DESC;
|
260
279
|
} else {
|
261
|
-
throw ParserException(
|
262
|
-
|
263
|
-
|
280
|
+
throw ParserException("Unrecognized parameter for option NULL_ORDER \"%s\", expected either NULLS FIRST, NULLS "
|
281
|
+
"LAST, SQLite, MySQL or Postgres",
|
282
|
+
parameter);
|
264
283
|
}
|
265
284
|
}
|
266
285
|
|
@@ -271,10 +290,14 @@ void DefaultNullOrderSetting::ResetGlobal(DatabaseInstance *db, DBConfig &config
|
|
271
290
|
Value DefaultNullOrderSetting::GetSetting(ClientContext &context) {
|
272
291
|
auto &config = DBConfig::GetConfig(context);
|
273
292
|
switch (config.options.default_null_order) {
|
274
|
-
case
|
293
|
+
case DefaultOrderByNullType::NULLS_FIRST:
|
275
294
|
return "nulls_first";
|
276
|
-
case
|
295
|
+
case DefaultOrderByNullType::NULLS_LAST:
|
277
296
|
return "nulls_last";
|
297
|
+
case DefaultOrderByNullType::NULLS_FIRST_ON_ASC_LAST_ON_DESC:
|
298
|
+
return "nulls_first_on_asc_last_on_desc";
|
299
|
+
case DefaultOrderByNullType::NULLS_LAST_ON_ASC_FIRST_ON_DESC:
|
300
|
+
return "nulls_last_on_asc_first_on_desc";
|
278
301
|
default:
|
279
302
|
throw InternalException("Unknown null order setting");
|
280
303
|
}
|
@@ -215,11 +215,8 @@ BindResult BaseSelectBinder::BindAggregate(FunctionExpression &aggr, optional_pt
|
|
215
215
|
auto &config = DBConfig::GetConfig(context);
|
216
216
|
for (auto &order : aggr.order_bys->orders) {
|
217
217
|
auto &order_expr = (BoundExpression &)*order.expression;
|
218
|
-
const auto sense =
|
219
|
-
|
220
|
-
const auto null_order = (order.null_order == OrderByNullType::ORDER_DEFAULT)
|
221
|
-
? config.options.default_null_order
|
222
|
-
: order.null_order;
|
218
|
+
const auto sense = config.ResolveOrder(order.type);
|
219
|
+
const auto null_order = config.ResolveNullOrder(sense, order.null_order);
|
223
220
|
order_bys->orders.emplace_back(sense, null_order, std::move(order_expr.expr));
|
224
221
|
}
|
225
222
|
}
|
@@ -64,14 +64,6 @@ static LogicalType ResolveWindowExpressionType(ExpressionType window_type, const
|
|
64
64
|
}
|
65
65
|
}
|
66
66
|
|
67
|
-
static inline OrderType ResolveOrderType(const DBConfig &config, OrderType type) {
|
68
|
-
return (type == OrderType::ORDER_DEFAULT) ? config.options.default_order_type : type;
|
69
|
-
}
|
70
|
-
|
71
|
-
static inline OrderByNullType ResolveNullOrder(const DBConfig &config, OrderByNullType null_order) {
|
72
|
-
return (null_order == OrderByNullType::ORDER_DEFAULT) ? config.options.default_null_order : null_order;
|
73
|
-
}
|
74
|
-
|
75
67
|
static unique_ptr<Expression> GetExpression(unique_ptr<ParsedExpression> &expr) {
|
76
68
|
if (!expr) {
|
77
69
|
return nullptr;
|
@@ -231,12 +223,12 @@ BindResult BaseSelectBinder::BindWindow(WindowExpression &window, idx_t depth) {
|
|
231
223
|
LogicalType start_type = LogicalType::BIGINT;
|
232
224
|
if (window.start == WindowBoundary::EXPR_PRECEDING_RANGE) {
|
233
225
|
D_ASSERT(window.orders.size() == 1);
|
234
|
-
range_sense =
|
226
|
+
range_sense = config.ResolveOrder(window.orders[0].type);
|
235
227
|
const auto name = (range_sense == OrderType::ASCENDING) ? "-" : "+";
|
236
228
|
start_type = BindRangeExpression(context, name, window.start_expr, window.orders[0].expression);
|
237
229
|
} else if (window.start == WindowBoundary::EXPR_FOLLOWING_RANGE) {
|
238
230
|
D_ASSERT(window.orders.size() == 1);
|
239
|
-
range_sense =
|
231
|
+
range_sense = config.ResolveOrder(window.orders[0].type);
|
240
232
|
const auto name = (range_sense == OrderType::ASCENDING) ? "+" : "-";
|
241
233
|
start_type = BindRangeExpression(context, name, window.start_expr, window.orders[0].expression);
|
242
234
|
}
|
@@ -244,12 +236,12 @@ BindResult BaseSelectBinder::BindWindow(WindowExpression &window, idx_t depth) {
|
|
244
236
|
LogicalType end_type = LogicalType::BIGINT;
|
245
237
|
if (window.end == WindowBoundary::EXPR_PRECEDING_RANGE) {
|
246
238
|
D_ASSERT(window.orders.size() == 1);
|
247
|
-
range_sense =
|
239
|
+
range_sense = config.ResolveOrder(window.orders[0].type);
|
248
240
|
const auto name = (range_sense == OrderType::ASCENDING) ? "-" : "+";
|
249
241
|
end_type = BindRangeExpression(context, name, window.end_expr, window.orders[0].expression);
|
250
242
|
} else if (window.end == WindowBoundary::EXPR_FOLLOWING_RANGE) {
|
251
243
|
D_ASSERT(window.orders.size() == 1);
|
252
|
-
range_sense =
|
244
|
+
range_sense = config.ResolveOrder(window.orders[0].type);
|
253
245
|
const auto name = (range_sense == OrderType::ASCENDING) ? "+" : "-";
|
254
246
|
end_type = BindRangeExpression(context, name, window.end_expr, window.orders[0].expression);
|
255
247
|
}
|
@@ -276,8 +268,8 @@ BindResult BaseSelectBinder::BindWindow(WindowExpression &window, idx_t depth) {
|
|
276
268
|
}
|
277
269
|
|
278
270
|
for (auto &order : window.orders) {
|
279
|
-
auto type =
|
280
|
-
auto null_order = ResolveNullOrder(
|
271
|
+
auto type = config.ResolveOrder(order.type);
|
272
|
+
auto null_order = config.ResolveNullOrder(type, order.null_order);
|
281
273
|
auto expression = GetExpression(order.expression);
|
282
274
|
result->orders.emplace_back(type, null_order, std::move(expression));
|
283
275
|
}
|
@@ -158,11 +158,8 @@ void Binder::BindModifiers(OrderBinder &order_binder, QueryNode &statement, Boun
|
|
158
158
|
vector<unique_ptr<ParsedExpression>> order_list;
|
159
159
|
order_binders[0]->ExpandStarExpression(std::move(order_node.expression), order_list);
|
160
160
|
|
161
|
-
auto type =
|
162
|
-
|
163
|
-
auto null_order = order_node.null_order == OrderByNullType::ORDER_DEFAULT
|
164
|
-
? config.options.default_null_order
|
165
|
-
: order_node.null_order;
|
161
|
+
auto type = config.ResolveOrder(order_node.type);
|
162
|
+
auto null_order = config.ResolveNullOrder(type, order_node.null_order);
|
166
163
|
for (auto &order_expr : order_list) {
|
167
164
|
auto bound_expr = BindOrderExpression(order_binder, std::move(order_expr));
|
168
165
|
if (!bound_expr) {
|
@@ -33,7 +33,6 @@ void BlockManager::ClearMetaBlockHandles() {
|
|
33
33
|
}
|
34
34
|
|
35
35
|
shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(block_id_t block_id, shared_ptr<BlockHandle> old_block) {
|
36
|
-
|
37
36
|
// pin the old block to ensure we have it loaded in memory
|
38
37
|
auto old_handle = buffer_manager.Pin(old_block);
|
39
38
|
D_ASSERT(old_block->state == BlockState::BLOCK_LOADED);
|
@@ -50,7 +49,7 @@ shared_ptr<BlockHandle> BlockManager::ConvertToPersistent(block_id_t block_id, s
|
|
50
49
|
|
51
50
|
// move the data from the old block into data for the new block
|
52
51
|
new_block->state = BlockState::BLOCK_LOADED;
|
53
|
-
new_block->buffer =
|
52
|
+
new_block->buffer = ConvertBlock(block_id, *old_block->buffer);
|
54
53
|
new_block->memory_usage = old_block->memory_usage;
|
55
54
|
new_block->memory_charge = std::move(old_block->memory_charge);
|
56
55
|
|
@@ -35,6 +35,10 @@ BlockPointer MetaBlockWriter::GetBlockPointer() {
|
|
35
35
|
}
|
36
36
|
|
37
37
|
void MetaBlockWriter::Flush() {
|
38
|
+
if (offset < block->size) {
|
39
|
+
// clear remaining bytes of block (if any)
|
40
|
+
memset(block->buffer + offset, 0, block->size - offset);
|
41
|
+
}
|
38
42
|
AdvanceBlock();
|
39
43
|
block = nullptr;
|
40
44
|
}
|
@@ -54,9 +54,14 @@ bool PartialBlockManager::GetPartialBlock(idx_t segment_size, unique_ptr<Partial
|
|
54
54
|
}
|
55
55
|
|
56
56
|
void PartialBlockManager::RegisterPartialBlock(PartialBlockAllocation &&allocation) {
|
57
|
-
auto &state
|
57
|
+
auto &state = allocation.partial_block->state;
|
58
58
|
if (state.block_use_count < max_use_count) {
|
59
|
-
auto
|
59
|
+
auto unaligned_size = allocation.allocation_size + state.offset_in_block;
|
60
|
+
auto new_size = AlignValue(unaligned_size);
|
61
|
+
if (new_size != unaligned_size) {
|
62
|
+
// register the uninitialized region so we can correctly initialize it before writing to disk
|
63
|
+
allocation.partial_block->AddUninitializedRegion(unaligned_size, new_size);
|
64
|
+
}
|
60
65
|
state.offset_in_block = new_size;
|
61
66
|
auto new_space_left = state.block_size - new_size;
|
62
67
|
// check if the block is STILL partially filled after adding the segment_size
|
@@ -65,22 +70,24 @@ void PartialBlockManager::RegisterPartialBlock(PartialBlockAllocation &&allocati
|
|
65
70
|
partially_filled_blocks.insert(make_pair(new_space_left, std::move(allocation.partial_block)));
|
66
71
|
}
|
67
72
|
}
|
73
|
+
idx_t free_space = state.block_size - state.offset_in_block;
|
68
74
|
auto block_to_free = std::move(allocation.partial_block);
|
69
75
|
if (!block_to_free && partially_filled_blocks.size() > MAX_BLOCK_MAP_SIZE) {
|
70
76
|
// Free the page with the least space free.
|
71
77
|
auto itr = partially_filled_blocks.begin();
|
72
78
|
block_to_free = std::move(itr->second);
|
79
|
+
free_space = state.block_size - itr->first;
|
73
80
|
partially_filled_blocks.erase(itr);
|
74
81
|
}
|
75
82
|
// Flush any block that we're not going to reuse.
|
76
83
|
if (block_to_free) {
|
77
|
-
block_to_free->Flush();
|
84
|
+
block_to_free->Flush(free_space);
|
78
85
|
}
|
79
86
|
}
|
80
87
|
|
81
88
|
void PartialBlockManager::FlushPartialBlocks() {
|
82
89
|
for (auto &e : partially_filled_blocks) {
|
83
|
-
e.second->Flush();
|
90
|
+
e.second->Flush(e.first);
|
84
91
|
}
|
85
92
|
partially_filled_blocks.clear();
|
86
93
|
}
|
@@ -107,15 +107,15 @@ T DeserializeHeaderStructure(data_ptr_t ptr) {
|
|
107
107
|
return T::Deserialize(source);
|
108
108
|
}
|
109
109
|
|
110
|
-
SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path_p,
|
110
|
+
SingleFileBlockManager::SingleFileBlockManager(AttachedDatabase &db, string path_p, StorageManagerOptions options)
|
111
111
|
: BlockManager(BufferManager::GetBufferManager(db)), db(db), path(std::move(path_p)),
|
112
112
|
header_buffer(Allocator::Get(db), FileBufferType::MANAGED_BUFFER,
|
113
113
|
Storage::FILE_HEADER_SIZE - Storage::BLOCK_HEADER_SIZE),
|
114
|
-
iteration_count(0),
|
114
|
+
iteration_count(0), options(options) {
|
115
115
|
}
|
116
116
|
|
117
117
|
void SingleFileBlockManager::GetFileFlags(uint8_t &flags, FileLockType &lock, bool create_new) {
|
118
|
-
if (read_only) {
|
118
|
+
if (options.read_only) {
|
119
119
|
D_ASSERT(!create_new);
|
120
120
|
flags = FileFlags::FILE_FLAGS_READ;
|
121
121
|
lock = FileLockType::READ_LOCK;
|
@@ -126,7 +126,7 @@ void SingleFileBlockManager::GetFileFlags(uint8_t &flags, FileLockType &lock, bo
|
|
126
126
|
flags |= FileFlags::FILE_FLAGS_FILE_CREATE;
|
127
127
|
}
|
128
128
|
}
|
129
|
-
if (use_direct_io) {
|
129
|
+
if (options.use_direct_io) {
|
130
130
|
flags |= FileFlags::FILE_FLAGS_DIRECT_IO;
|
131
131
|
}
|
132
132
|
}
|
@@ -241,7 +241,7 @@ void SingleFileBlockManager::Initialize(DatabaseHeader &header) {
|
|
241
241
|
}
|
242
242
|
|
243
243
|
void SingleFileBlockManager::LoadFreeList() {
|
244
|
-
if (read_only) {
|
244
|
+
if (options.read_only) {
|
245
245
|
// no need to load free list for read only db
|
246
246
|
return;
|
247
247
|
}
|
@@ -343,13 +343,20 @@ idx_t SingleFileBlockManager::FreeBlocks() {
|
|
343
343
|
return free_list.size();
|
344
344
|
}
|
345
345
|
|
346
|
+
unique_ptr<Block> SingleFileBlockManager::ConvertBlock(block_id_t block_id, FileBuffer &source_buffer) {
|
347
|
+
D_ASSERT(source_buffer.AllocSize() == Storage::BLOCK_ALLOC_SIZE);
|
348
|
+
return make_uniq<Block>(source_buffer, block_id);
|
349
|
+
}
|
350
|
+
|
346
351
|
unique_ptr<Block> SingleFileBlockManager::CreateBlock(block_id_t block_id, FileBuffer *source_buffer) {
|
352
|
+
unique_ptr<Block> result;
|
347
353
|
if (source_buffer) {
|
348
|
-
|
349
|
-
return make_uniq<Block>(*source_buffer, block_id);
|
354
|
+
result = ConvertBlock(block_id, *source_buffer);
|
350
355
|
} else {
|
351
|
-
|
356
|
+
result = make_uniq<Block>(Allocator::Get(db), block_id);
|
352
357
|
}
|
358
|
+
result->Initialize(options.debug_initialize);
|
359
|
+
return result;
|
353
360
|
}
|
354
361
|
|
355
362
|
void SingleFileBlockManager::Read(Block &block) {
|
@@ -459,7 +466,7 @@ void SingleFileBlockManager::WriteHeader(DatabaseHeader header) {
|
|
459
466
|
throw FatalException("Checkpoint aborted after free list write because of PRAGMA checkpoint_abort flag");
|
460
467
|
}
|
461
468
|
|
462
|
-
if (!use_direct_io) {
|
469
|
+
if (!options.use_direct_io) {
|
463
470
|
// if we are not using Direct IO we need to fsync BEFORE we write the header to ensure that all the previous
|
464
471
|
// blocks are written as well
|
465
472
|
handle->Sync();
|
@@ -20,14 +20,17 @@ struct BufferAllocatorData : PrivateAllocatorData {
|
|
20
20
|
|
21
21
|
unique_ptr<FileBuffer> StandardBufferManager::ConstructManagedBuffer(idx_t size, unique_ptr<FileBuffer> &&source,
|
22
22
|
FileBufferType type) {
|
23
|
+
unique_ptr<FileBuffer> result;
|
23
24
|
if (source) {
|
24
25
|
auto tmp = std::move(source);
|
25
26
|
D_ASSERT(tmp->AllocSize() == BufferManager::GetAllocSize(size));
|
26
|
-
|
27
|
+
result = make_uniq<FileBuffer>(*tmp, type);
|
27
28
|
} else {
|
28
29
|
// no re-usable buffer: allocate a new buffer
|
29
|
-
|
30
|
+
result = make_uniq<FileBuffer>(Allocator::Get(db), type, size);
|
30
31
|
}
|
32
|
+
result->Initialize(DBConfig::GetConfig(db).options.debug_initialize);
|
33
|
+
return result;
|
31
34
|
}
|
32
35
|
|
33
36
|
class TemporaryFileManager;
|
@@ -95,6 +95,11 @@ void SingleFileStorageManager::LoadDatabase() {
|
|
95
95
|
auto &fs = FileSystem::Get(db);
|
96
96
|
auto &config = DBConfig::Get(db);
|
97
97
|
bool truncate_wal = false;
|
98
|
+
|
99
|
+
StorageManagerOptions options;
|
100
|
+
options.read_only = read_only;
|
101
|
+
options.use_direct_io = config.options.use_direct_io;
|
102
|
+
options.debug_initialize = config.options.debug_initialize;
|
98
103
|
// first check if the database exists
|
99
104
|
if (!fs.FileExists(path)) {
|
100
105
|
if (read_only) {
|
@@ -107,13 +112,13 @@ void SingleFileStorageManager::LoadDatabase() {
|
|
107
112
|
fs.RemoveFile(wal_path);
|
108
113
|
}
|
109
114
|
// initialize the block manager while creating a new db file
|
110
|
-
auto sf_block_manager = make_uniq<SingleFileBlockManager>(db, path,
|
115
|
+
auto sf_block_manager = make_uniq<SingleFileBlockManager>(db, path, options);
|
111
116
|
sf_block_manager->CreateNewDatabase();
|
112
117
|
block_manager = std::move(sf_block_manager);
|
113
118
|
table_io_manager = make_uniq<SingleFileTableIOManager>(*block_manager);
|
114
119
|
} else {
|
115
120
|
// initialize the block manager while loading the current db file
|
116
|
-
auto sf_block_manager = make_uniq<SingleFileBlockManager>(db, path,
|
121
|
+
auto sf_block_manager = make_uniq<SingleFileBlockManager>(db, path, options);
|
117
122
|
sf_block_manager->LoadExistingDatabase();
|
118
123
|
block_manager = std::move(sf_block_manager);
|
119
124
|
table_io_manager = make_uniq<SingleFileTableIOManager>(*block_manager);
|
@@ -50,16 +50,36 @@ public:
|
|
50
50
|
BlockManager &block_manager;
|
51
51
|
vector<PartialColumnSegment> tail_segments;
|
52
52
|
|
53
|
+
private:
|
54
|
+
struct UninitializedRegion {
|
55
|
+
idx_t start;
|
56
|
+
idx_t end;
|
57
|
+
};
|
58
|
+
vector<UninitializedRegion> uninitialized_regions;
|
59
|
+
|
53
60
|
public:
|
54
61
|
bool IsFlushed() {
|
55
62
|
// first_segment is zeroed on Flush
|
56
63
|
return !first_segment;
|
57
64
|
}
|
58
65
|
|
59
|
-
void
|
66
|
+
void AddUninitializedRegion(idx_t start, idx_t end) override {
|
67
|
+
uninitialized_regions.push_back({start, end});
|
68
|
+
}
|
69
|
+
|
70
|
+
void Flush(idx_t free_space_left) override {
|
60
71
|
// At this point, we've already copied all data from tail_segments
|
61
72
|
// into the page owned by first_segment. We flush all segment data to
|
62
73
|
// disk with the following call.
|
74
|
+
if (free_space_left > 0 || !uninitialized_regions.empty()) {
|
75
|
+
auto handle = block_manager.buffer_manager.Pin(first_segment->block);
|
76
|
+
// memset any uninitialized regions
|
77
|
+
for (auto &uninitialized : uninitialized_regions) {
|
78
|
+
memset(handle.Ptr() + uninitialized.start, 0, uninitialized.end - uninitialized.start);
|
79
|
+
}
|
80
|
+
// memset any free space at the end of the block to 0 prior to writing to disk
|
81
|
+
memset(handle.Ptr() + Storage::BLOCK_SIZE - free_space_left, 0, free_space_left);
|
82
|
+
}
|
63
83
|
first_data->IncrementVersion();
|
64
84
|
first_segment->ConvertToPersistent(&block_manager, state.block_id);
|
65
85
|
// Now that the page is persistent, update tail_segments to point to the
|
@@ -1,5 +1,7 @@
|
|
1
1
|
#include "src/execution/operator/join/outer_join_marker.cpp"
|
2
2
|
|
3
|
+
#include "src/execution/operator/join/physical_asof_join.cpp"
|
4
|
+
|
3
5
|
#include "src/execution/operator/join/physical_blockwise_nl_join.cpp"
|
4
6
|
|
5
7
|
#include "src/execution/operator/join/physical_comparison_join.cpp"
|