duckdb 0.5.2-dev764.0 → 0.5.2-dev802.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.cpp +463 -143
- package/src/duckdb.hpp +8914 -8880
- package/src/parquet-amalgamation.cpp +37518 -37518
package/src/duckdb.cpp
CHANGED
|
@@ -63958,8 +63958,9 @@ OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, D
|
|
|
63958
63958
|
if (wexpr.children.empty()) {
|
|
63959
63959
|
D_ASSERT(GetTypeIdSize(result.GetType().InternalType()) == sizeof(int64_t));
|
|
63960
63960
|
auto data = FlatVector::GetData<int64_t>(result);
|
|
63961
|
+
int64_t start_row = gstate.row_number;
|
|
63961
63962
|
for (idx_t i = 0; i < input.size(); ++i) {
|
|
63962
|
-
data[i] =
|
|
63963
|
+
data[i] = start_row + i;
|
|
63963
63964
|
}
|
|
63964
63965
|
break;
|
|
63965
63966
|
}
|
|
@@ -64006,9 +64007,10 @@ OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, D
|
|
|
64006
64007
|
}
|
|
64007
64008
|
case ExpressionType::WINDOW_ROW_NUMBER: {
|
|
64008
64009
|
// Set row numbers
|
|
64010
|
+
int64_t start_row = gstate.row_number;
|
|
64009
64011
|
auto rdata = FlatVector::GetData<int64_t>(chunk.data[col_idx]);
|
|
64010
64012
|
for (idx_t i = 0; i < count; i++) {
|
|
64011
|
-
rdata[i] =
|
|
64013
|
+
rdata[i] = start_row + i;
|
|
64012
64014
|
}
|
|
64013
64015
|
break;
|
|
64014
64016
|
}
|
|
@@ -64114,6 +64116,7 @@ private:
|
|
|
64114
64116
|
|
|
64115
64117
|
|
|
64116
64118
|
|
|
64119
|
+
|
|
64117
64120
|
#include <functional>
|
|
64118
64121
|
|
|
64119
64122
|
|
|
@@ -64580,6 +64583,10 @@ public:
|
|
|
64580
64583
|
void Schedule() override {
|
|
64581
64584
|
auto &distinct_data = *gstate.distinct_data;
|
|
64582
64585
|
|
|
64586
|
+
//! Now that all tables are combined, it's time to do the distinct aggregations
|
|
64587
|
+
auto new_event = make_shared<DistinctAggregateFinalizeEvent>(op, gstate, *pipeline, client);
|
|
64588
|
+
this->InsertEvent(move(new_event));
|
|
64589
|
+
|
|
64583
64590
|
vector<unique_ptr<Task>> tasks;
|
|
64584
64591
|
for (idx_t table_idx = 0; table_idx < distinct_data.radix_tables.size(); table_idx++) {
|
|
64585
64592
|
distinct_data.radix_tables[table_idx]->ScheduleTasks(pipeline->executor, shared_from_this(),
|
|
@@ -64587,10 +64594,6 @@ public:
|
|
|
64587
64594
|
}
|
|
64588
64595
|
D_ASSERT(!tasks.empty());
|
|
64589
64596
|
SetTasks(move(tasks));
|
|
64590
|
-
|
|
64591
|
-
//! Now that all tables are combined, it's time to do the distinct aggregations
|
|
64592
|
-
auto new_event = make_shared<DistinctAggregateFinalizeEvent>(op, gstate, *pipeline, client);
|
|
64593
|
-
this->InsertEvent(move(new_event));
|
|
64594
64597
|
}
|
|
64595
64598
|
};
|
|
64596
64599
|
|
|
@@ -71671,6 +71674,7 @@ private:
|
|
|
71671
71674
|
|
|
71672
71675
|
|
|
71673
71676
|
|
|
71677
|
+
|
|
71674
71678
|
#include <thread>
|
|
71675
71679
|
|
|
71676
71680
|
namespace duckdb {
|
|
@@ -82285,7 +82289,8 @@ static bool CanPlanIndexJoin(Transaction &transaction, TableScanBindData *bind_d
|
|
|
82285
82289
|
return false;
|
|
82286
82290
|
}
|
|
82287
82291
|
auto table = bind_data->table;
|
|
82288
|
-
|
|
82292
|
+
auto &local_storage = LocalStorage::Get(transaction);
|
|
82293
|
+
if (local_storage.Find(table->storage.get())) {
|
|
82289
82294
|
// transaction local appends: skip index join
|
|
82290
82295
|
return false;
|
|
82291
82296
|
}
|
|
@@ -105300,6 +105305,7 @@ void ListFlattenFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
105300
105305
|
|
|
105301
105306
|
|
|
105302
105307
|
|
|
105308
|
+
|
|
105303
105309
|
namespace duckdb {
|
|
105304
105310
|
|
|
105305
105311
|
// FIXME: use a local state for each thread to increase performance?
|
|
@@ -116691,6 +116697,8 @@ void StructPackFun::RegisterFunction(BuiltinFunctions &set) {
|
|
|
116691
116697
|
|
|
116692
116698
|
|
|
116693
116699
|
|
|
116700
|
+
|
|
116701
|
+
|
|
116694
116702
|
namespace duckdb {
|
|
116695
116703
|
|
|
116696
116704
|
// aggregate state export
|
|
@@ -124159,8 +124167,8 @@ unique_ptr<GlobalTableFunctionState> TableScanInitGlobal(ClientContext &context,
|
|
|
124159
124167
|
static unique_ptr<BaseStatistics> TableScanStatistics(ClientContext &context, const FunctionData *bind_data_p,
|
|
124160
124168
|
column_t column_id) {
|
|
124161
124169
|
auto &bind_data = (const TableScanBindData &)*bind_data_p;
|
|
124162
|
-
auto &
|
|
124163
|
-
if (
|
|
124170
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
124171
|
+
if (local_storage.Find(bind_data.table->storage.get())) {
|
|
124164
124172
|
// we don't emit any statistics for tables that have outstanding transaction-local data
|
|
124165
124173
|
return nullptr;
|
|
124166
124174
|
}
|
|
@@ -124238,9 +124246,9 @@ void TableScanDependency(unordered_set<CatalogEntry *> &entries, const FunctionD
|
|
|
124238
124246
|
|
|
124239
124247
|
unique_ptr<NodeStatistics> TableScanCardinality(ClientContext &context, const FunctionData *bind_data_p) {
|
|
124240
124248
|
auto &bind_data = (const TableScanBindData &)*bind_data_p;
|
|
124241
|
-
auto &
|
|
124249
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
124242
124250
|
idx_t estimated_cardinality =
|
|
124243
|
-
bind_data.table->storage->info->cardinality +
|
|
124251
|
+
bind_data.table->storage->info->cardinality + local_storage.AddedRows(bind_data.table->storage.get());
|
|
124244
124252
|
return make_unique<NodeStatistics>(bind_data.table->storage->info->cardinality, estimated_cardinality);
|
|
124245
124253
|
}
|
|
124246
124254
|
|
|
@@ -124265,11 +124273,11 @@ static unique_ptr<GlobalTableFunctionState> IndexScanInitGlobal(ClientContext &c
|
|
|
124265
124273
|
row_id_data = (data_ptr_t)&bind_data.result_ids[0];
|
|
124266
124274
|
}
|
|
124267
124275
|
auto result = make_unique<IndexScanGlobalState>(row_id_data);
|
|
124268
|
-
auto &
|
|
124276
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
124269
124277
|
result->column_ids = input.column_ids;
|
|
124270
124278
|
result->local_storage_state.Initialize(input.column_ids, input.filters);
|
|
124271
|
-
|
|
124272
|
-
|
|
124279
|
+
local_storage.InitializeScan(bind_data.table->storage.get(), result->local_storage_state.local_state,
|
|
124280
|
+
input.filters);
|
|
124273
124281
|
|
|
124274
124282
|
result->finished = false;
|
|
124275
124283
|
return move(result);
|
|
@@ -124279,13 +124287,15 @@ static void IndexScanFunction(ClientContext &context, TableFunctionInput &data_p
|
|
|
124279
124287
|
auto &bind_data = (const TableScanBindData &)*data_p.bind_data;
|
|
124280
124288
|
auto &state = (IndexScanGlobalState &)*data_p.global_state;
|
|
124281
124289
|
auto &transaction = Transaction::GetTransaction(context);
|
|
124290
|
+
auto &local_storage = LocalStorage::Get(transaction);
|
|
124291
|
+
|
|
124282
124292
|
if (!state.finished) {
|
|
124283
124293
|
bind_data.table->storage->Fetch(transaction, output, state.column_ids, state.row_ids,
|
|
124284
124294
|
bind_data.result_ids.size(), state.fetch_state);
|
|
124285
124295
|
state.finished = true;
|
|
124286
124296
|
}
|
|
124287
124297
|
if (output.size() == 0) {
|
|
124288
|
-
|
|
124298
|
+
local_storage.Scan(state.local_storage_state.local_state, state.column_ids, output);
|
|
124289
124299
|
}
|
|
124290
124300
|
}
|
|
124291
124301
|
|
|
@@ -178018,6 +178028,7 @@ void BindContext::AddContext(BindContext other) {
|
|
|
178018
178028
|
|
|
178019
178029
|
|
|
178020
178030
|
|
|
178031
|
+
|
|
178021
178032
|
//===----------------------------------------------------------------------===//
|
|
178022
178033
|
// DuckDB
|
|
178023
178034
|
//
|
|
@@ -178215,6 +178226,7 @@ public:
|
|
|
178215
178226
|
|
|
178216
178227
|
|
|
178217
178228
|
|
|
178229
|
+
|
|
178218
178230
|
namespace duckdb {
|
|
178219
178231
|
|
|
178220
178232
|
static void InvertPercentileFractions(unique_ptr<ParsedExpression> &fractions) {
|
|
@@ -179094,6 +179106,7 @@ BindResult ExpressionBinder::BindExpression(ConstantExpression &expr, idx_t dept
|
|
|
179094
179106
|
|
|
179095
179107
|
|
|
179096
179108
|
|
|
179109
|
+
|
|
179097
179110
|
namespace duckdb {
|
|
179098
179111
|
|
|
179099
179112
|
BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t depth,
|
|
@@ -186562,6 +186575,7 @@ BoundLimitPercentModifier::BoundLimitPercentModifier()
|
|
|
186562
186575
|
|
|
186563
186576
|
|
|
186564
186577
|
|
|
186578
|
+
|
|
186565
186579
|
namespace duckdb {
|
|
186566
186580
|
|
|
186567
186581
|
class FunctionSerializer {
|
|
@@ -194519,6 +194533,8 @@ struct PartialBlock {
|
|
|
194519
194533
|
|
|
194520
194534
|
public:
|
|
194521
194535
|
virtual void Flush() = 0;
|
|
194536
|
+
virtual void Clear() {
|
|
194537
|
+
}
|
|
194522
194538
|
};
|
|
194523
194539
|
|
|
194524
194540
|
struct PartialBlockAllocation {
|
|
@@ -194547,9 +194563,8 @@ public:
|
|
|
194547
194563
|
|
|
194548
194564
|
public:
|
|
194549
194565
|
PartialBlockManager(BlockManager &block_manager, uint32_t max_partial_block_size = DEFAULT_MAX_PARTIAL_BLOCK_SIZE,
|
|
194550
|
-
uint32_t max_use_count = DEFAULT_MAX_USE_COUNT)
|
|
194551
|
-
|
|
194552
|
-
}
|
|
194566
|
+
uint32_t max_use_count = DEFAULT_MAX_USE_COUNT);
|
|
194567
|
+
virtual ~PartialBlockManager();
|
|
194553
194568
|
|
|
194554
194569
|
public:
|
|
194555
194570
|
//! Flush any remaining partial blocks to disk
|
|
@@ -194562,6 +194577,9 @@ public:
|
|
|
194562
194577
|
//! Register a partially filled block that is filled with "segment_size" entries
|
|
194563
194578
|
void RegisterPartialBlock(PartialBlockAllocation &&allocation);
|
|
194564
194579
|
|
|
194580
|
+
//! Clears all blocks
|
|
194581
|
+
void Clear();
|
|
194582
|
+
|
|
194565
194583
|
protected:
|
|
194566
194584
|
BlockManager &block_manager;
|
|
194567
194585
|
//! A map of (available space -> PartialBlock) for partially filled blocks
|
|
@@ -194711,6 +194729,10 @@ public:
|
|
|
194711
194729
|
void RegisterPartialBlock(PartialBlockAllocation &&allocation);
|
|
194712
194730
|
PartialBlockAllocation GetBlockAllocation(uint32_t segment_size);
|
|
194713
194731
|
|
|
194732
|
+
PartialBlockManager &GetPartialBlockManager() {
|
|
194733
|
+
return partial_block_manager;
|
|
194734
|
+
}
|
|
194735
|
+
|
|
194714
194736
|
protected:
|
|
194715
194737
|
TableCatalogEntry &table;
|
|
194716
194738
|
PartialBlockManager &partial_block_manager;
|
|
@@ -194806,28 +194828,33 @@ private:
|
|
|
194806
194828
|
|
|
194807
194829
|
|
|
194808
194830
|
|
|
194831
|
+
|
|
194809
194832
|
namespace duckdb {
|
|
194810
194833
|
class ColumnData;
|
|
194811
194834
|
class DatabaseInstance;
|
|
194812
194835
|
class RowGroup;
|
|
194836
|
+
class PartialBlockManager;
|
|
194813
194837
|
class TableDataWriter;
|
|
194814
194838
|
|
|
194815
194839
|
struct ColumnCheckpointState {
|
|
194816
|
-
ColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
194840
|
+
ColumnCheckpointState(RowGroup &row_group, ColumnData &column_data, PartialBlockManager &partial_block_manager);
|
|
194817
194841
|
virtual ~ColumnCheckpointState();
|
|
194818
194842
|
|
|
194819
194843
|
RowGroup &row_group;
|
|
194820
194844
|
ColumnData &column_data;
|
|
194821
|
-
RowGroupWriter &writer;
|
|
194822
194845
|
SegmentTree new_tree;
|
|
194823
194846
|
vector<DataPointer> data_pointers;
|
|
194824
194847
|
unique_ptr<BaseStatistics> global_stats;
|
|
194825
194848
|
|
|
194849
|
+
protected:
|
|
194850
|
+
PartialBlockManager &partial_block_manager;
|
|
194851
|
+
|
|
194826
194852
|
public:
|
|
194827
194853
|
virtual unique_ptr<BaseStatistics> GetStatistics();
|
|
194828
194854
|
|
|
194829
194855
|
virtual void FlushSegment(unique_ptr<ColumnSegment> segment, idx_t segment_size);
|
|
194830
|
-
virtual void WriteDataPointers();
|
|
194856
|
+
virtual void WriteDataPointers(RowGroupWriter &writer);
|
|
194857
|
+
virtual void GetBlockIds(unordered_set<block_id_t> &result);
|
|
194831
194858
|
};
|
|
194832
194859
|
|
|
194833
194860
|
} // namespace duckdb
|
|
@@ -197104,6 +197131,8 @@ public:
|
|
|
197104
197131
|
DataTableInfo &GetTableInfo() const;
|
|
197105
197132
|
virtual idx_t GetMaxEntry();
|
|
197106
197133
|
|
|
197134
|
+
void IncrementVersion();
|
|
197135
|
+
|
|
197107
197136
|
//! The root type of the column
|
|
197108
197137
|
const LogicalType &RootType() const;
|
|
197109
197138
|
|
|
@@ -197149,9 +197178,10 @@ public:
|
|
|
197149
197178
|
|
|
197150
197179
|
virtual void CommitDropColumn();
|
|
197151
197180
|
|
|
197152
|
-
virtual unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
197153
|
-
|
|
197154
|
-
|
|
197181
|
+
virtual unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
197182
|
+
PartialBlockManager &partial_block_manager);
|
|
197183
|
+
virtual unique_ptr<ColumnCheckpointState>
|
|
197184
|
+
Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager, ColumnCheckpointInfo &checkpoint_info);
|
|
197155
197185
|
|
|
197156
197186
|
virtual void CheckpointScan(ColumnSegment *segment, ColumnScanState &state, idx_t row_group_start, idx_t count,
|
|
197157
197187
|
Vector &scan_vector);
|
|
@@ -197190,6 +197220,8 @@ protected:
|
|
|
197190
197220
|
mutex update_lock;
|
|
197191
197221
|
//! The updates for this column segment
|
|
197192
197222
|
unique_ptr<UpdateSegment> updates;
|
|
197223
|
+
//! The internal version of the column data
|
|
197224
|
+
idx_t version;
|
|
197193
197225
|
};
|
|
197194
197226
|
|
|
197195
197227
|
} // namespace duckdb
|
|
@@ -200657,12 +200689,14 @@ idx_t ValidityFinalAnalyze(AnalyzeState &state_p) {
|
|
|
200657
200689
|
//===--------------------------------------------------------------------===//
|
|
200658
200690
|
struct ValidityScanState : public SegmentScanState {
|
|
200659
200691
|
BufferHandle handle;
|
|
200692
|
+
block_id_t block_id;
|
|
200660
200693
|
};
|
|
200661
200694
|
|
|
200662
200695
|
unique_ptr<SegmentScanState> ValidityInitScan(ColumnSegment &segment) {
|
|
200663
200696
|
auto result = make_unique<ValidityScanState>();
|
|
200664
200697
|
auto &buffer_manager = BufferManager::GetBufferManager(segment.db);
|
|
200665
200698
|
result->handle = buffer_manager.Pin(segment.block);
|
|
200699
|
+
result->block_id = segment.block->BlockId();
|
|
200666
200700
|
return move(result);
|
|
200667
200701
|
}
|
|
200668
200702
|
|
|
@@ -200678,6 +200712,7 @@ void ValidityScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t s
|
|
|
200678
200712
|
|
|
200679
200713
|
auto &result_mask = FlatVector::Validity(result);
|
|
200680
200714
|
auto buffer_ptr = scan_state.handle.Ptr() + segment.GetBlockOffset();
|
|
200715
|
+
D_ASSERT(scan_state.block_id == segment.block->BlockId());
|
|
200681
200716
|
auto input_data = (validity_t *)buffer_ptr;
|
|
200682
200717
|
|
|
200683
200718
|
#ifdef DEBUG
|
|
@@ -200803,6 +200838,7 @@ void ValidityScan(ColumnSegment &segment, ColumnScanState &state, idx_t scan_cou
|
|
|
200803
200838
|
// it is not required for correctness
|
|
200804
200839
|
auto &result_mask = FlatVector::Validity(result);
|
|
200805
200840
|
auto buffer_ptr = scan_state.handle.Ptr() + segment.GetBlockOffset();
|
|
200841
|
+
D_ASSERT(scan_state.block_id == segment.block->BlockId());
|
|
200806
200842
|
auto input_data = (validity_t *)buffer_ptr;
|
|
200807
200843
|
auto result_data = (validity_t *)result_mask.GetData();
|
|
200808
200844
|
idx_t start_offset = start / ValidityMask::BITS_PER_VALUE;
|
|
@@ -201019,8 +201055,9 @@ public:
|
|
|
201019
201055
|
|
|
201020
201056
|
void CommitDropColumn() override;
|
|
201021
201057
|
|
|
201022
|
-
unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
201023
|
-
|
|
201058
|
+
unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
201059
|
+
PartialBlockManager &partial_block_manager) override;
|
|
201060
|
+
unique_ptr<ColumnCheckpointState> Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager,
|
|
201024
201061
|
ColumnCheckpointInfo &checkpoint_info) override;
|
|
201025
201062
|
void CheckpointScan(ColumnSegment *segment, ColumnScanState &state, idx_t row_group_start, idx_t count,
|
|
201026
201063
|
Vector &scan_vector) override;
|
|
@@ -201080,11 +201117,11 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, ColumnDefinition
|
|
|
201080
201117
|
// add the column definitions from this DataTable
|
|
201081
201118
|
column_definitions.emplace_back(new_column.Copy());
|
|
201082
201119
|
|
|
201083
|
-
auto &transaction = Transaction::GetTransaction(context);
|
|
201084
201120
|
this->row_groups = parent.row_groups->AddColumn(new_column, default_value, stats.GetStats(new_column_idx));
|
|
201085
201121
|
|
|
201086
201122
|
// also add this column to client local storage
|
|
201087
|
-
|
|
201123
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201124
|
+
local_storage.AddColumn(&parent, this, new_column, default_value);
|
|
201088
201125
|
|
|
201089
201126
|
// this table replaces the previous table, hence the parent is no longer the root DataTable
|
|
201090
201127
|
parent.is_root = false;
|
|
@@ -201131,8 +201168,8 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t removed_co
|
|
|
201131
201168
|
this->row_groups = parent.row_groups->RemoveColumn(removed_column);
|
|
201132
201169
|
|
|
201133
201170
|
// scan the original table, and fill the new column with the transformed value
|
|
201134
|
-
auto &
|
|
201135
|
-
|
|
201171
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201172
|
+
local_storage.DropColumn(&parent, this, removed_column);
|
|
201136
201173
|
|
|
201137
201174
|
// this table replaces the previous table, hence the parent is no longer the root DataTable
|
|
201138
201175
|
parent.is_root = false;
|
|
@@ -201152,8 +201189,8 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, unique_ptr<Bound
|
|
|
201152
201189
|
VerifyNewConstraint(context, parent, constraint.get());
|
|
201153
201190
|
|
|
201154
201191
|
// Get the local data ownership from old dt
|
|
201155
|
-
auto &
|
|
201156
|
-
|
|
201192
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201193
|
+
local_storage.MoveStorage(&parent, this);
|
|
201157
201194
|
// this table replaces the previous table, hence the parent is no longer the root DataTable
|
|
201158
201195
|
parent.is_root = false;
|
|
201159
201196
|
}
|
|
@@ -201186,8 +201223,8 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t changed_id
|
|
|
201186
201223
|
parent.row_groups->AlterType(changed_idx, target_type, bound_columns, cast_expr, stats.GetStats(changed_idx));
|
|
201187
201224
|
|
|
201188
201225
|
// scan the original table, and fill the new column with the transformed value
|
|
201189
|
-
auto &
|
|
201190
|
-
|
|
201226
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201227
|
+
local_storage.ChangeType(&parent, this, changed_idx, target_type, bound_columns, cast_expr);
|
|
201191
201228
|
|
|
201192
201229
|
// this table replaces the previous table, hence the parent is no longer the root DataTable
|
|
201193
201230
|
parent.is_root = false;
|
|
@@ -201217,7 +201254,8 @@ void DataTable::InitializeScan(TableScanState &state, const vector<column_t> &co
|
|
|
201217
201254
|
void DataTable::InitializeScan(Transaction &transaction, TableScanState &state, const vector<column_t> &column_ids,
|
|
201218
201255
|
TableFilterSet *table_filters) {
|
|
201219
201256
|
InitializeScan(state, column_ids, table_filters);
|
|
201220
|
-
|
|
201257
|
+
auto &local_storage = LocalStorage::Get(transaction);
|
|
201258
|
+
local_storage.InitializeScan(this, state.local_state, table_filters);
|
|
201221
201259
|
}
|
|
201222
201260
|
|
|
201223
201261
|
void DataTable::InitializeScanWithOffset(TableScanState &state, const vector<column_t> &column_ids, idx_t start_row,
|
|
@@ -201237,16 +201275,17 @@ idx_t DataTable::MaxThreads(ClientContext &context) {
|
|
|
201237
201275
|
|
|
201238
201276
|
void DataTable::InitializeParallelScan(ClientContext &context, ParallelTableScanState &state) {
|
|
201239
201277
|
row_groups->InitializeParallelScan(state.scan_state);
|
|
201240
|
-
|
|
201241
|
-
|
|
201278
|
+
|
|
201279
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201280
|
+
local_storage.InitializeParallelScan(this, state.local_state);
|
|
201242
201281
|
}
|
|
201243
201282
|
|
|
201244
201283
|
bool DataTable::NextParallelScan(ClientContext &context, ParallelTableScanState &state, TableScanState &scan_state) {
|
|
201245
201284
|
if (row_groups->NextParallelScan(context, state.scan_state, scan_state.table_state)) {
|
|
201246
201285
|
return true;
|
|
201247
201286
|
}
|
|
201248
|
-
auto &
|
|
201249
|
-
if (
|
|
201287
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201288
|
+
if (local_storage.NextParallelScan(context, this, state.local_state, scan_state.local_state)) {
|
|
201250
201289
|
return true;
|
|
201251
201290
|
} else {
|
|
201252
201291
|
// finished all scans: no more scans remaining
|
|
@@ -201262,7 +201301,8 @@ void DataTable::Scan(Transaction &transaction, DataChunk &result, TableScanState
|
|
|
201262
201301
|
}
|
|
201263
201302
|
|
|
201264
201303
|
// scan the transaction-local segments
|
|
201265
|
-
|
|
201304
|
+
auto &local_storage = LocalStorage::Get(transaction);
|
|
201305
|
+
local_storage.Scan(state.local_state, state.GetColumnIds(), result);
|
|
201266
201306
|
}
|
|
201267
201307
|
|
|
201268
201308
|
bool DataTable::CreateIndexScan(TableScanState &state, DataChunk &result, TableScanType type) {
|
|
@@ -201384,10 +201424,10 @@ static void VerifyForeignKeyConstraint(const BoundForeignKeyConstraint &bfk, Cli
|
|
|
201384
201424
|
|
|
201385
201425
|
data_table->info->indexes.VerifyForeignKey(*dst_keys_ptr, is_append, dst_chunk, err_msgs);
|
|
201386
201426
|
// check whether or not the chunk can be inserted or deleted into the referenced table' transaction local storage
|
|
201387
|
-
auto &
|
|
201388
|
-
bool transaction_check =
|
|
201427
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201428
|
+
bool transaction_check = local_storage.Find(data_table);
|
|
201389
201429
|
if (transaction_check) {
|
|
201390
|
-
auto &transact_index =
|
|
201430
|
+
auto &transact_index = local_storage.GetIndexes(data_table);
|
|
201391
201431
|
transact_index.VerifyForeignKey(*dst_keys_ptr, is_append, dst_chunk, tran_err_msgs);
|
|
201392
201432
|
}
|
|
201393
201433
|
|
|
@@ -201439,8 +201479,8 @@ void DataTable::VerifyNewConstraint(ClientContext &context, DataTable &parent, c
|
|
|
201439
201479
|
}
|
|
201440
201480
|
|
|
201441
201481
|
parent.row_groups->VerifyNewConstraint(parent, *constraint);
|
|
201442
|
-
auto &
|
|
201443
|
-
|
|
201482
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201483
|
+
local_storage.VerifyNewConstraint(parent, *constraint);
|
|
201444
201484
|
}
|
|
201445
201485
|
|
|
201446
201486
|
void DataTable::VerifyAppendConstraints(TableCatalogEntry &table, ClientContext &context, DataChunk &chunk) {
|
|
@@ -201500,8 +201540,8 @@ void DataTable::InitializeLocalAppend(LocalAppendState &state, ClientContext &co
|
|
|
201500
201540
|
if (!is_root) {
|
|
201501
201541
|
throw TransactionException("Transaction conflict: adding entries to a table that has been altered!");
|
|
201502
201542
|
}
|
|
201503
|
-
auto &
|
|
201504
|
-
|
|
201543
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201544
|
+
local_storage.InitializeAppend(state, this);
|
|
201505
201545
|
}
|
|
201506
201546
|
|
|
201507
201547
|
void DataTable::LocalAppend(LocalAppendState &state, TableCatalogEntry &table, ClientContext &context,
|
|
@@ -201761,6 +201801,7 @@ idx_t DataTable::Delete(TableCatalogEntry &table, ClientContext &context, Vector
|
|
|
201761
201801
|
}
|
|
201762
201802
|
|
|
201763
201803
|
auto &transaction = Transaction::GetTransaction(context);
|
|
201804
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201764
201805
|
|
|
201765
201806
|
row_identifiers.Flatten(count);
|
|
201766
201807
|
auto ids = FlatVector::GetData<row_t>(row_identifiers);
|
|
@@ -201771,7 +201812,7 @@ idx_t DataTable::Delete(TableCatalogEntry &table, ClientContext &context, Vector
|
|
|
201771
201812
|
// and we only need to fetch columns that are part of this constraint
|
|
201772
201813
|
DataChunk verify_chunk;
|
|
201773
201814
|
if (first_id >= MAX_ROW_ID) {
|
|
201774
|
-
|
|
201815
|
+
local_storage.FetchChunk(this, row_identifiers, count, verify_chunk);
|
|
201775
201816
|
} else {
|
|
201776
201817
|
ColumnFetchState fetch_state;
|
|
201777
201818
|
vector<column_t> col_ids;
|
|
@@ -201787,7 +201828,7 @@ idx_t DataTable::Delete(TableCatalogEntry &table, ClientContext &context, Vector
|
|
|
201787
201828
|
|
|
201788
201829
|
if (first_id >= MAX_ROW_ID) {
|
|
201789
201830
|
// deletion is in transaction-local storage: push delete into local chunk collection
|
|
201790
|
-
return
|
|
201831
|
+
return local_storage.Delete(this, row_identifiers, count);
|
|
201791
201832
|
} else {
|
|
201792
201833
|
return row_groups->Delete(transaction, this, ids, count);
|
|
201793
201834
|
}
|
|
@@ -201902,7 +201943,8 @@ void DataTable::Update(TableCatalogEntry &table, ClientContext &context, Vector
|
|
|
201902
201943
|
auto first_id = FlatVector::GetValue<row_t>(row_ids, 0);
|
|
201903
201944
|
if (first_id >= MAX_ROW_ID) {
|
|
201904
201945
|
// update is in transaction-local storage: push update into local storage
|
|
201905
|
-
|
|
201946
|
+
auto &local_storage = LocalStorage::Get(context);
|
|
201947
|
+
local_storage.Update(this, row_ids, column_ids, updates);
|
|
201906
201948
|
return;
|
|
201907
201949
|
}
|
|
201908
201950
|
|
|
@@ -202099,8 +202141,13 @@ BlockPointer Index::Serialize(duckdb::MetaBlockWriter &writer) {
|
|
|
202099
202141
|
|
|
202100
202142
|
|
|
202101
202143
|
|
|
202144
|
+
|
|
202145
|
+
|
|
202102
202146
|
namespace duckdb {
|
|
202103
202147
|
|
|
202148
|
+
//===--------------------------------------------------------------------===//
|
|
202149
|
+
// Local Table Storage
|
|
202150
|
+
//===--------------------------------------------------------------------===//
|
|
202104
202151
|
LocalTableStorage::LocalTableStorage(DataTable &table)
|
|
202105
202152
|
: table(table), allocator(Allocator::Get(table.db)), deleted_rows(0) {
|
|
202106
202153
|
auto types = table.GetTypes();
|
|
@@ -202127,7 +202174,11 @@ LocalTableStorage::LocalTableStorage(DataTable &table)
|
|
|
202127
202174
|
LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &parent, idx_t changed_idx,
|
|
202128
202175
|
const LogicalType &target_type, const vector<column_t> &bound_columns,
|
|
202129
202176
|
Expression &cast_expr)
|
|
202130
|
-
: table(new_dt), allocator(Allocator::Get(table.db)), deleted_rows(parent.deleted_rows)
|
|
202177
|
+
: table(new_dt), allocator(Allocator::Get(table.db)), deleted_rows(parent.deleted_rows),
|
|
202178
|
+
partial_manager(move(parent.partial_manager)), written_blocks(move(parent.written_blocks)) {
|
|
202179
|
+
if (partial_manager) {
|
|
202180
|
+
partial_manager->FlushPartialBlocks();
|
|
202181
|
+
}
|
|
202131
202182
|
stats.InitializeAlterType(parent.stats, changed_idx, target_type);
|
|
202132
202183
|
row_groups =
|
|
202133
202184
|
parent.row_groups->AlterType(changed_idx, target_type, bound_columns, cast_expr, stats.GetStats(changed_idx));
|
|
@@ -202136,7 +202187,11 @@ LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &paren
|
|
|
202136
202187
|
}
|
|
202137
202188
|
|
|
202138
202189
|
LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &parent, idx_t drop_idx)
|
|
202139
|
-
: table(new_dt), allocator(Allocator::Get(table.db)), deleted_rows(parent.deleted_rows)
|
|
202190
|
+
: table(new_dt), allocator(Allocator::Get(table.db)), deleted_rows(parent.deleted_rows),
|
|
202191
|
+
partial_manager(move(parent.partial_manager)), written_blocks(move(parent.written_blocks)) {
|
|
202192
|
+
if (partial_manager) {
|
|
202193
|
+
partial_manager->FlushPartialBlocks();
|
|
202194
|
+
}
|
|
202140
202195
|
stats.InitializeRemoveColumn(parent.stats, drop_idx);
|
|
202141
202196
|
row_groups = parent.row_groups->RemoveColumn(drop_idx);
|
|
202142
202197
|
parent.row_groups.reset();
|
|
@@ -202145,7 +202200,8 @@ LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &paren
|
|
|
202145
202200
|
|
|
202146
202201
|
LocalTableStorage::LocalTableStorage(DataTable &new_dt, LocalTableStorage &parent, ColumnDefinition &new_column,
|
|
202147
202202
|
Expression *default_value)
|
|
202148
|
-
: table(new_dt), allocator(Allocator::Get(table.db)), deleted_rows(parent.deleted_rows)
|
|
202203
|
+
: table(new_dt), allocator(Allocator::Get(table.db)), deleted_rows(parent.deleted_rows),
|
|
202204
|
+
partial_manager(move(parent.partial_manager)), written_blocks(move(parent.written_blocks)) {
|
|
202149
202205
|
idx_t new_column_idx = parent.table.column_definitions.size();
|
|
202150
202206
|
stats.InitializeAddColumn(parent.stats, new_column.GetType());
|
|
202151
202207
|
row_groups = parent.row_groups->AddColumn(new_column, default_value, stats.GetStats(new_column_idx));
|
|
@@ -202177,6 +202233,20 @@ idx_t LocalTableStorage::EstimatedSize() {
|
|
|
202177
202233
|
return appended_rows * row_size;
|
|
202178
202234
|
}
|
|
202179
202235
|
|
|
202236
|
+
//===--------------------------------------------------------------------===//
|
|
202237
|
+
// LocalStorage
|
|
202238
|
+
//===--------------------------------------------------------------------===//
|
|
202239
|
+
LocalStorage::LocalStorage(Transaction &transaction) : transaction(transaction) {
|
|
202240
|
+
}
|
|
202241
|
+
|
|
202242
|
+
LocalStorage &LocalStorage::Get(Transaction &transaction) {
|
|
202243
|
+
return transaction.GetLocalStorage();
|
|
202244
|
+
}
|
|
202245
|
+
|
|
202246
|
+
LocalStorage &LocalStorage::Get(ClientContext &context) {
|
|
202247
|
+
return Transaction::GetTransaction(context).GetLocalStorage();
|
|
202248
|
+
}
|
|
202249
|
+
|
|
202180
202250
|
void LocalStorage::InitializeScan(DataTable *table, CollectionScanState &state, TableFilterSet *table_filters) {
|
|
202181
202251
|
auto entry = table_storage.find(table);
|
|
202182
202252
|
if (entry == table_storage.end()) {
|
|
@@ -202230,8 +202300,68 @@ void LocalStorage::Append(LocalAppendState &state, DataChunk &chunk) {
|
|
|
202230
202300
|
throw ConstraintException("PRIMARY KEY or UNIQUE constraint violated: duplicated key");
|
|
202231
202301
|
}
|
|
202232
202302
|
|
|
202233
|
-
//! Append to the
|
|
202234
|
-
storage->row_groups->Append(chunk, state.append_state, storage->stats);
|
|
202303
|
+
//! Append the chunk to the local storage
|
|
202304
|
+
auto new_row_group = storage->row_groups->Append(chunk, state.append_state, storage->stats);
|
|
202305
|
+
|
|
202306
|
+
//! Check if we should pre-emptively flush blocks to disk
|
|
202307
|
+
if (new_row_group) {
|
|
202308
|
+
storage->CheckFlushToDisk();
|
|
202309
|
+
}
|
|
202310
|
+
}
|
|
202311
|
+
|
|
202312
|
+
void LocalTableStorage::CheckFlushToDisk() {
|
|
202313
|
+
// we finished writing a complete row group
|
|
202314
|
+
// check if we should pre-emptively write it to disk
|
|
202315
|
+
if (table.info->IsTemporary() || StorageManager::GetStorageManager(table.db).InMemory()) {
|
|
202316
|
+
return;
|
|
202317
|
+
}
|
|
202318
|
+
if (!table.info->indexes.Empty()) {
|
|
202319
|
+
// we have indexes - we cannot merge
|
|
202320
|
+
return;
|
|
202321
|
+
}
|
|
202322
|
+
if (deleted_rows != 0) {
|
|
202323
|
+
// we have deletes - we cannot merge
|
|
202324
|
+
return;
|
|
202325
|
+
}
|
|
202326
|
+
// we should! write the second-to-last row group to disk
|
|
202327
|
+
// allocate the partial block-manager if none is allocated yet
|
|
202328
|
+
if (!partial_manager) {
|
|
202329
|
+
auto &block_manager = table.info->table_io_manager->GetBlockManagerForRowData();
|
|
202330
|
+
partial_manager = make_unique<PartialBlockManager>(block_manager);
|
|
202331
|
+
}
|
|
202332
|
+
// flush second-to-last row group
|
|
202333
|
+
auto row_group = row_groups->GetRowGroup(-2);
|
|
202334
|
+
FlushToDisk(row_group);
|
|
202335
|
+
}
|
|
202336
|
+
|
|
202337
|
+
void LocalTableStorage::FlushToDisk(RowGroup *row_group) {
|
|
202338
|
+
// flush the specified row group
|
|
202339
|
+
D_ASSERT(row_group);
|
|
202340
|
+
D_ASSERT(deleted_rows == 0);
|
|
202341
|
+
D_ASSERT(table.info->indexes.Empty());
|
|
202342
|
+
D_ASSERT(partial_manager);
|
|
202343
|
+
//! The set of column compression types (if any)
|
|
202344
|
+
vector<CompressionType> compression_types;
|
|
202345
|
+
D_ASSERT(compression_types.empty());
|
|
202346
|
+
for (auto &column : table.column_definitions) {
|
|
202347
|
+
compression_types.push_back(column.CompressionType());
|
|
202348
|
+
}
|
|
202349
|
+
auto row_group_pointer = row_group->WriteToDisk(*partial_manager, compression_types);
|
|
202350
|
+
for (idx_t col_idx = 0; col_idx < row_group_pointer.statistics.size(); col_idx++) {
|
|
202351
|
+
row_group_pointer.states[col_idx]->GetBlockIds(written_blocks);
|
|
202352
|
+
stats.MergeStats(col_idx, *row_group_pointer.statistics[col_idx]);
|
|
202353
|
+
}
|
|
202354
|
+
}
|
|
202355
|
+
void LocalTableStorage::FlushToDisk() {
|
|
202356
|
+
// no partial manager - nothing to flush
|
|
202357
|
+
if (!partial_manager) {
|
|
202358
|
+
return;
|
|
202359
|
+
}
|
|
202360
|
+
// flush the last row group
|
|
202361
|
+
FlushToDisk(row_groups->GetRowGroup(-1));
|
|
202362
|
+
// then flush the partial manager
|
|
202363
|
+
partial_manager->FlushPartialBlocks();
|
|
202364
|
+
partial_manager.reset();
|
|
202235
202365
|
}
|
|
202236
202366
|
|
|
202237
202367
|
void LocalStorage::FinalizeAppend(LocalAppendState &state) {
|
|
@@ -202252,6 +202382,10 @@ idx_t LocalStorage::EstimatedSize() {
|
|
|
202252
202382
|
return estimated_size;
|
|
202253
202383
|
}
|
|
202254
202384
|
|
|
202385
|
+
bool LocalTableStorage::HasWrittenBlocks() {
|
|
202386
|
+
return partial_manager || !written_blocks.empty();
|
|
202387
|
+
}
|
|
202388
|
+
|
|
202255
202389
|
idx_t LocalStorage::Delete(DataTable *table, Vector &row_ids, idx_t count) {
|
|
202256
202390
|
auto storage = GetStorage(table);
|
|
202257
202391
|
D_ASSERT(storage);
|
|
@@ -202319,10 +202453,16 @@ void LocalStorage::Flush(DataTable &table, LocalTableStorage &storage) {
|
|
|
202319
202453
|
table.AppendLock(append_state);
|
|
202320
202454
|
if ((append_state.row_start == 0 || storage.row_groups->GetTotalRows() >= MERGE_THRESHOLD) &&
|
|
202321
202455
|
storage.table.info->indexes.Empty() && storage.deleted_rows == 0) {
|
|
202322
|
-
// table is currently empty OR we are bulk appending
|
|
202323
|
-
//
|
|
202456
|
+
// table is currently empty OR we are bulk appending: move over the storage directly
|
|
202457
|
+
// first flush any out-standing storage nodes
|
|
202458
|
+
storage.FlushToDisk();
|
|
202324
202459
|
table.MergeStorage(*storage.row_groups, storage.indexes, storage.stats);
|
|
202325
202460
|
} else {
|
|
202461
|
+
if (storage.partial_manager || !storage.written_blocks.empty()) {
|
|
202462
|
+
// we have written data but cannot merge to disk after all
|
|
202463
|
+
// revert the data we have already written
|
|
202464
|
+
storage.Rollback();
|
|
202465
|
+
}
|
|
202326
202466
|
bool constraint_violated = false;
|
|
202327
202467
|
table.InitializeAppend(transaction, append_state, append_count);
|
|
202328
202468
|
ScanTableStorage(table, storage, [&](DataChunk &chunk) -> bool {
|
|
@@ -202368,6 +202508,27 @@ void LocalStorage::Commit(LocalStorage::CommitState &commit_state, Transaction &
|
|
|
202368
202508
|
table_storage.clear();
|
|
202369
202509
|
}
|
|
202370
202510
|
|
|
202511
|
+
void LocalStorage::Rollback() {
|
|
202512
|
+
for (auto &entry : table_storage) {
|
|
202513
|
+
auto storage = entry.second.get();
|
|
202514
|
+
if (!storage) {
|
|
202515
|
+
continue;
|
|
202516
|
+
}
|
|
202517
|
+
storage->Rollback();
|
|
202518
|
+
}
|
|
202519
|
+
}
|
|
202520
|
+
|
|
202521
|
+
void LocalTableStorage::Rollback() {
|
|
202522
|
+
if (partial_manager) {
|
|
202523
|
+
partial_manager->Clear();
|
|
202524
|
+
partial_manager.reset();
|
|
202525
|
+
}
|
|
202526
|
+
auto &block_manager = table.info->table_io_manager->GetBlockManagerForRowData();
|
|
202527
|
+
for (auto block_id : written_blocks) {
|
|
202528
|
+
block_manager.MarkBlockAsModified(block_id);
|
|
202529
|
+
}
|
|
202530
|
+
}
|
|
202531
|
+
|
|
202371
202532
|
idx_t LocalStorage::AddedRows(DataTable *table) {
|
|
202372
202533
|
auto entry = table_storage.find(table);
|
|
202373
202534
|
if (entry == table_storage.end()) {
|
|
@@ -202593,6 +202754,12 @@ void MetaBlockWriter::WriteData(const_data_ptr_t buffer, idx_t write_size) {
|
|
|
202593
202754
|
|
|
202594
202755
|
namespace duckdb {
|
|
202595
202756
|
|
|
202757
|
+
PartialBlockManager::PartialBlockManager(BlockManager &block_manager, uint32_t max_partial_block_size,
|
|
202758
|
+
uint32_t max_use_count)
|
|
202759
|
+
: block_manager(block_manager), max_partial_block_size(max_partial_block_size), max_use_count(max_use_count) {
|
|
202760
|
+
}
|
|
202761
|
+
PartialBlockManager::~PartialBlockManager() {
|
|
202762
|
+
}
|
|
202596
202763
|
//===--------------------------------------------------------------------===//
|
|
202597
202764
|
// Partial Blocks
|
|
202598
202765
|
//===--------------------------------------------------------------------===//
|
|
@@ -202667,6 +202834,14 @@ void PartialBlockManager::FlushPartialBlocks() {
|
|
|
202667
202834
|
for (auto &e : partially_filled_blocks) {
|
|
202668
202835
|
e.second->Flush();
|
|
202669
202836
|
}
|
|
202837
|
+
partially_filled_blocks.clear();
|
|
202838
|
+
}
|
|
202839
|
+
|
|
202840
|
+
void PartialBlockManager::Clear() {
|
|
202841
|
+
for (auto &e : partially_filled_blocks) {
|
|
202842
|
+
e.second->Clear();
|
|
202843
|
+
}
|
|
202844
|
+
partially_filled_blocks.clear();
|
|
202670
202845
|
}
|
|
202671
202846
|
|
|
202672
202847
|
} // namespace duckdb
|
|
@@ -202719,13 +202894,9 @@ public:
|
|
|
202719
202894
|
void WriteHeader(DatabaseHeader header) override;
|
|
202720
202895
|
|
|
202721
202896
|
//! Returns the number of total blocks
|
|
202722
|
-
idx_t TotalBlocks() override
|
|
202723
|
-
return max_block;
|
|
202724
|
-
}
|
|
202897
|
+
idx_t TotalBlocks() override;
|
|
202725
202898
|
//! Returns the number of free blocks
|
|
202726
|
-
idx_t FreeBlocks() override
|
|
202727
|
-
return free_list.size();
|
|
202728
|
-
}
|
|
202899
|
+
idx_t FreeBlocks() override;
|
|
202729
202900
|
|
|
202730
202901
|
private:
|
|
202731
202902
|
//! Load the free list from the file
|
|
@@ -202766,6 +202937,8 @@ private:
|
|
|
202766
202937
|
bool read_only;
|
|
202767
202938
|
//! Whether or not to use Direct IO to read the blocks
|
|
202768
202939
|
bool use_direct_io;
|
|
202940
|
+
//! Lock for performing various operations in the single file block manager
|
|
202941
|
+
mutex block_lock;
|
|
202769
202942
|
};
|
|
202770
202943
|
} // namespace duckdb
|
|
202771
202944
|
|
|
@@ -202990,6 +203163,7 @@ bool SingleFileBlockManager::IsRootBlock(block_id_t root) {
|
|
|
202990
203163
|
}
|
|
202991
203164
|
|
|
202992
203165
|
block_id_t SingleFileBlockManager::GetFreeBlockId() {
|
|
203166
|
+
lock_guard<mutex> lock(block_lock);
|
|
202993
203167
|
block_id_t block;
|
|
202994
203168
|
if (!free_list.empty()) {
|
|
202995
203169
|
// free list is non empty
|
|
@@ -203004,6 +203178,7 @@ block_id_t SingleFileBlockManager::GetFreeBlockId() {
|
|
|
203004
203178
|
}
|
|
203005
203179
|
|
|
203006
203180
|
void SingleFileBlockManager::MarkBlockAsModified(block_id_t block_id) {
|
|
203181
|
+
lock_guard<mutex> lock(block_lock);
|
|
203007
203182
|
D_ASSERT(block_id >= 0);
|
|
203008
203183
|
|
|
203009
203184
|
// check if the block is a multi-use block
|
|
@@ -203026,6 +203201,7 @@ void SingleFileBlockManager::MarkBlockAsModified(block_id_t block_id) {
|
|
|
203026
203201
|
}
|
|
203027
203202
|
|
|
203028
203203
|
void SingleFileBlockManager::IncreaseBlockReferenceCount(block_id_t block_id) {
|
|
203204
|
+
lock_guard<mutex> lock(block_lock);
|
|
203029
203205
|
D_ASSERT(free_list.find(block_id) == free_list.end());
|
|
203030
203206
|
auto entry = multi_use_blocks.find(block_id);
|
|
203031
203207
|
if (entry != multi_use_blocks.end()) {
|
|
@@ -203039,6 +203215,16 @@ block_id_t SingleFileBlockManager::GetMetaBlock() {
|
|
|
203039
203215
|
return meta_block;
|
|
203040
203216
|
}
|
|
203041
203217
|
|
|
203218
|
+
idx_t SingleFileBlockManager::TotalBlocks() {
|
|
203219
|
+
lock_guard<mutex> lock(block_lock);
|
|
203220
|
+
return max_block;
|
|
203221
|
+
}
|
|
203222
|
+
|
|
203223
|
+
idx_t SingleFileBlockManager::FreeBlocks() {
|
|
203224
|
+
lock_guard<mutex> lock(block_lock);
|
|
203225
|
+
return free_list.size();
|
|
203226
|
+
}
|
|
203227
|
+
|
|
203042
203228
|
unique_ptr<Block> SingleFileBlockManager::CreateBlock(block_id_t block_id, FileBuffer *source_buffer) {
|
|
203043
203229
|
if (source_buffer) {
|
|
203044
203230
|
D_ASSERT(source_buffer->AllocSize() == Storage::BLOCK_ALLOC_SIZE);
|
|
@@ -204894,8 +205080,9 @@ public:
|
|
|
204894
205080
|
|
|
204895
205081
|
void CommitDropColumn() override;
|
|
204896
205082
|
|
|
204897
|
-
unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
204898
|
-
|
|
205083
|
+
unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
205084
|
+
PartialBlockManager &partial_block_manager) override;
|
|
205085
|
+
unique_ptr<ColumnCheckpointState> Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager,
|
|
204899
205086
|
ColumnCheckpointInfo &checkpoint_info) override;
|
|
204900
205087
|
|
|
204901
205088
|
void DeserializeColumn(Deserializer &source) override;
|
|
@@ -204916,8 +205103,9 @@ private:
|
|
|
204916
205103
|
|
|
204917
205104
|
namespace duckdb {
|
|
204918
205105
|
|
|
204919
|
-
ColumnCheckpointState::ColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
204920
|
-
|
|
205106
|
+
ColumnCheckpointState::ColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
205107
|
+
PartialBlockManager &partial_block_manager)
|
|
205108
|
+
: row_group(row_group), column_data(column_data), partial_block_manager(partial_block_manager) {
|
|
204921
205109
|
}
|
|
204922
205110
|
|
|
204923
205111
|
ColumnCheckpointState::~ColumnCheckpointState() {
|
|
@@ -204930,13 +205118,15 @@ unique_ptr<BaseStatistics> ColumnCheckpointState::GetStatistics() {
|
|
|
204930
205118
|
|
|
204931
205119
|
struct PartialBlockForCheckpoint : PartialBlock {
|
|
204932
205120
|
struct PartialColumnSegment {
|
|
205121
|
+
ColumnData *data;
|
|
204933
205122
|
ColumnSegment *segment;
|
|
204934
205123
|
uint32_t offset_in_block;
|
|
204935
205124
|
};
|
|
204936
205125
|
|
|
204937
205126
|
public:
|
|
204938
|
-
PartialBlockForCheckpoint(ColumnSegment *first_segment, BlockManager &block_manager,
|
|
204939
|
-
|
|
205127
|
+
PartialBlockForCheckpoint(ColumnData *first_data, ColumnSegment *first_segment, BlockManager &block_manager,
|
|
205128
|
+
PartialBlockState state)
|
|
205129
|
+
: PartialBlock(state), first_data(first_data), first_segment(first_segment), block_manager(block_manager) {
|
|
204940
205130
|
}
|
|
204941
205131
|
|
|
204942
205132
|
~PartialBlockForCheckpoint() override {
|
|
@@ -204949,6 +205139,7 @@ public:
|
|
|
204949
205139
|
// the block to get written to storage (via BlockManger::ConvertToPersistent),
|
|
204950
205140
|
// and all segments to have their references updated
|
|
204951
205141
|
// (via ColumnSegment::ConvertToPersistent)
|
|
205142
|
+
ColumnData *first_data;
|
|
204952
205143
|
ColumnSegment *first_segment;
|
|
204953
205144
|
BlockManager &block_manager;
|
|
204954
205145
|
vector<PartialColumnSegment> tail_segments;
|
|
@@ -204963,18 +205154,26 @@ public:
|
|
|
204963
205154
|
// At this point, we've already copied all data from tail_segments
|
|
204964
205155
|
// into the page owned by first_segment. We flush all segment data to
|
|
204965
205156
|
// disk with the following call.
|
|
205157
|
+
first_data->IncrementVersion();
|
|
204966
205158
|
first_segment->ConvertToPersistent(&block_manager, state.block_id);
|
|
204967
205159
|
// Now that the page is persistent, update tail_segments to point to the
|
|
204968
205160
|
// newly persistent block.
|
|
204969
205161
|
for (auto e : tail_segments) {
|
|
205162
|
+
e.data->IncrementVersion();
|
|
204970
205163
|
e.segment->MarkAsPersistent(first_segment->block, e.offset_in_block);
|
|
204971
205164
|
}
|
|
204972
205165
|
first_segment = nullptr;
|
|
204973
205166
|
tail_segments.clear();
|
|
204974
205167
|
}
|
|
204975
205168
|
|
|
204976
|
-
void
|
|
204977
|
-
|
|
205169
|
+
void Clear() override {
|
|
205170
|
+
first_data = nullptr;
|
|
205171
|
+
first_segment = nullptr;
|
|
205172
|
+
tail_segments.clear();
|
|
205173
|
+
}
|
|
205174
|
+
|
|
205175
|
+
void AddSegmentToTail(ColumnData *data, ColumnSegment *segment, uint32_t offset_in_block) {
|
|
205176
|
+
tail_segments.push_back({data, segment, offset_in_block});
|
|
204978
205177
|
}
|
|
204979
205178
|
};
|
|
204980
205179
|
|
|
@@ -204996,7 +205195,7 @@ void ColumnCheckpointState::FlushSegment(unique_ptr<ColumnSegment> segment, idx_
|
|
|
204996
205195
|
|
|
204997
205196
|
if (!segment->stats.statistics->IsConstant()) {
|
|
204998
205197
|
// non-constant block
|
|
204999
|
-
PartialBlockAllocation allocation =
|
|
205198
|
+
PartialBlockAllocation allocation = partial_block_manager.GetBlockAllocation(segment_size);
|
|
205000
205199
|
block_id = allocation.state.block_id;
|
|
205001
205200
|
offset_in_block = allocation.state.offset_in_block;
|
|
205002
205201
|
|
|
@@ -205010,15 +205209,15 @@ void ColumnCheckpointState::FlushSegment(unique_ptr<ColumnSegment> segment, idx_
|
|
|
205010
205209
|
auto new_handle = buffer_manager.Pin(pstate->first_segment->block);
|
|
205011
205210
|
// memcpy the contents of the old block to the new block
|
|
205012
205211
|
memcpy(new_handle.Ptr() + offset_in_block, old_handle.Ptr(), segment_size);
|
|
205013
|
-
pstate->AddSegmentToTail(segment.get(), offset_in_block);
|
|
205212
|
+
pstate->AddSegmentToTail(&column_data, segment.get(), offset_in_block);
|
|
205014
205213
|
} else {
|
|
205015
205214
|
// Create a new block for future reuse.
|
|
205016
205215
|
D_ASSERT(offset_in_block == 0);
|
|
205017
|
-
allocation.partial_block =
|
|
205018
|
-
|
|
205216
|
+
allocation.partial_block = make_unique<PartialBlockForCheckpoint>(
|
|
205217
|
+
&column_data, segment.get(), *allocation.block_manager, allocation.state);
|
|
205019
205218
|
}
|
|
205020
205219
|
// Writer will decide whether to reuse this block.
|
|
205021
|
-
|
|
205220
|
+
partial_block_manager.RegisterPartialBlock(move(allocation));
|
|
205022
205221
|
} else {
|
|
205023
205222
|
// constant block: no need to write anything to disk besides the stats
|
|
205024
205223
|
// set up the compression function to constant
|
|
@@ -205046,10 +205245,19 @@ void ColumnCheckpointState::FlushSegment(unique_ptr<ColumnSegment> segment, idx_
|
|
|
205046
205245
|
data_pointers.push_back(move(data_pointer));
|
|
205047
205246
|
}
|
|
205048
205247
|
|
|
205049
|
-
void ColumnCheckpointState::WriteDataPointers() {
|
|
205248
|
+
void ColumnCheckpointState::WriteDataPointers(RowGroupWriter &writer) {
|
|
205050
205249
|
writer.WriteColumnDataPointers(*this);
|
|
205051
205250
|
}
|
|
205052
205251
|
|
|
205252
|
+
void ColumnCheckpointState::GetBlockIds(unordered_set<block_id_t> &result) {
|
|
205253
|
+
for (auto &pointer : data_pointers) {
|
|
205254
|
+
if (pointer.block_pointer.block_id == INVALID_BLOCK) {
|
|
205255
|
+
continue;
|
|
205256
|
+
}
|
|
205257
|
+
result.insert(pointer.block_pointer.block_id);
|
|
205258
|
+
}
|
|
205259
|
+
}
|
|
205260
|
+
|
|
205053
205261
|
} // namespace duckdb
|
|
205054
205262
|
|
|
205055
205263
|
|
|
@@ -205119,8 +205327,9 @@ public:
|
|
|
205119
205327
|
|
|
205120
205328
|
void CommitDropColumn() override;
|
|
205121
205329
|
|
|
205122
|
-
unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
205123
|
-
|
|
205330
|
+
unique_ptr<ColumnCheckpointState> CreateCheckpointState(RowGroup &row_group,
|
|
205331
|
+
PartialBlockManager &partial_block_manager) override;
|
|
205332
|
+
unique_ptr<ColumnCheckpointState> Checkpoint(RowGroup &row_group, PartialBlockManager &partial_block_manager,
|
|
205124
205333
|
ColumnCheckpointInfo &checkpoint_info) override;
|
|
205125
205334
|
|
|
205126
205335
|
void DeserializeColumn(Deserializer &source) override;
|
|
@@ -205247,12 +205456,12 @@ namespace duckdb {
|
|
|
205247
205456
|
ColumnData::ColumnData(BlockManager &block_manager, DataTableInfo &info, idx_t column_index, idx_t start_row,
|
|
205248
205457
|
LogicalType type, ColumnData *parent)
|
|
205249
205458
|
: block_manager(block_manager), info(info), column_index(column_index), start(start_row), type(move(type)),
|
|
205250
|
-
parent(parent) {
|
|
205459
|
+
parent(parent), version(0) {
|
|
205251
205460
|
}
|
|
205252
205461
|
|
|
205253
205462
|
ColumnData::ColumnData(ColumnData &other, idx_t start, ColumnData *parent)
|
|
205254
205463
|
: block_manager(other.block_manager), info(other.info), column_index(other.column_index), start(start),
|
|
205255
|
-
type(move(other.type)), parent(parent), updates(move(other.updates)) {
|
|
205464
|
+
type(move(other.type)), parent(parent), updates(move(other.updates)), version(parent ? parent->version + 1 : 0) {
|
|
205256
205465
|
idx_t offset = 0;
|
|
205257
205466
|
for (auto segment = other.data.GetRootSegment(); segment; segment = segment->next.get()) {
|
|
205258
205467
|
auto &other = (ColumnSegment &)*segment;
|
|
@@ -205279,6 +205488,10 @@ const LogicalType &ColumnData::RootType() const {
|
|
|
205279
205488
|
return type;
|
|
205280
205489
|
}
|
|
205281
205490
|
|
|
205491
|
+
void ColumnData::IncrementVersion() {
|
|
205492
|
+
version++;
|
|
205493
|
+
}
|
|
205494
|
+
|
|
205282
205495
|
idx_t ColumnData::GetMaxEntry() {
|
|
205283
205496
|
auto first_segment = data.GetRootSegment();
|
|
205284
205497
|
auto last_segment = data.GetLastSegment();
|
|
@@ -205296,6 +205509,8 @@ void ColumnData::InitializeScan(ColumnScanState &state) {
|
|
|
205296
205509
|
state.row_index = state.current ? state.current->start : 0;
|
|
205297
205510
|
state.internal_index = state.row_index;
|
|
205298
205511
|
state.initialized = false;
|
|
205512
|
+
state.version = version;
|
|
205513
|
+
state.scan_state.reset();
|
|
205299
205514
|
}
|
|
205300
205515
|
|
|
205301
205516
|
void ColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx) {
|
|
@@ -205303,15 +205518,23 @@ void ColumnData::InitializeScanWithOffset(ColumnScanState &state, idx_t row_idx)
|
|
|
205303
205518
|
state.row_index = row_idx;
|
|
205304
205519
|
state.internal_index = state.current->start;
|
|
205305
205520
|
state.initialized = false;
|
|
205521
|
+
state.version = version;
|
|
205522
|
+
state.scan_state.reset();
|
|
205306
205523
|
}
|
|
205307
205524
|
|
|
205308
205525
|
idx_t ColumnData::ScanVector(ColumnScanState &state, Vector &result, idx_t remaining) {
|
|
205309
|
-
if (
|
|
205526
|
+
if (state.version != version) {
|
|
205527
|
+
InitializeScanWithOffset(state, state.row_index);
|
|
205528
|
+
state.current->InitializeScan(state);
|
|
205529
|
+
state.initialized = true;
|
|
205530
|
+
} else if (!state.initialized) {
|
|
205310
205531
|
D_ASSERT(state.current);
|
|
205311
205532
|
state.current->InitializeScan(state);
|
|
205312
205533
|
state.internal_index = state.current->start;
|
|
205313
205534
|
state.initialized = true;
|
|
205314
205535
|
}
|
|
205536
|
+
D_ASSERT(data.HasSegment(state.current));
|
|
205537
|
+
D_ASSERT(state.version == version);
|
|
205315
205538
|
D_ASSERT(state.internal_index <= state.row_index);
|
|
205316
205539
|
if (state.internal_index < state.row_index) {
|
|
205317
205540
|
state.current->Skip(state);
|
|
@@ -205563,8 +205786,9 @@ void ColumnData::CommitDropColumn() {
|
|
|
205563
205786
|
}
|
|
205564
205787
|
}
|
|
205565
205788
|
|
|
205566
|
-
unique_ptr<ColumnCheckpointState> ColumnData::CreateCheckpointState(RowGroup &row_group,
|
|
205567
|
-
|
|
205789
|
+
unique_ptr<ColumnCheckpointState> ColumnData::CreateCheckpointState(RowGroup &row_group,
|
|
205790
|
+
PartialBlockManager &partial_block_manager) {
|
|
205791
|
+
return make_unique<ColumnCheckpointState>(row_group, *this, partial_block_manager);
|
|
205568
205792
|
}
|
|
205569
205793
|
|
|
205570
205794
|
void ColumnData::CheckpointScan(ColumnSegment *segment, ColumnScanState &state, idx_t row_group_start, idx_t count,
|
|
@@ -205576,11 +205800,12 @@ void ColumnData::CheckpointScan(ColumnSegment *segment, ColumnScanState &state,
|
|
|
205576
205800
|
}
|
|
205577
205801
|
}
|
|
205578
205802
|
|
|
205579
|
-
unique_ptr<ColumnCheckpointState> ColumnData::Checkpoint(RowGroup &row_group,
|
|
205803
|
+
unique_ptr<ColumnCheckpointState> ColumnData::Checkpoint(RowGroup &row_group,
|
|
205804
|
+
PartialBlockManager &partial_block_manager,
|
|
205580
205805
|
ColumnCheckpointInfo &checkpoint_info) {
|
|
205581
205806
|
// scan the segments of the column data
|
|
205582
205807
|
// set up the checkpoint state
|
|
205583
|
-
auto checkpoint_state = CreateCheckpointState(row_group,
|
|
205808
|
+
auto checkpoint_state = CreateCheckpointState(row_group, partial_block_manager);
|
|
205584
205809
|
checkpoint_state->global_stats = BaseStatistics::CreateEmpty(type, StatisticsType::LOCAL_STATS);
|
|
205585
205810
|
|
|
205586
205811
|
if (!data.root_node) {
|
|
@@ -205594,6 +205819,7 @@ unique_ptr<ColumnCheckpointState> ColumnData::Checkpoint(RowGroup &row_group, Ro
|
|
|
205594
205819
|
|
|
205595
205820
|
// replace the old tree with the new one
|
|
205596
205821
|
data.Replace(checkpoint_state->new_tree);
|
|
205822
|
+
version++;
|
|
205597
205823
|
|
|
205598
205824
|
return checkpoint_state;
|
|
205599
205825
|
}
|
|
@@ -206166,6 +206392,7 @@ void ColumnSegment::ConvertToPersistent(BlockManager *block_manager, block_id_t
|
|
|
206166
206392
|
block_id = block_id_p;
|
|
206167
206393
|
offset = 0;
|
|
206168
206394
|
|
|
206395
|
+
D_ASSERT(stats.statistics);
|
|
206169
206396
|
if (block_id == INVALID_BLOCK) {
|
|
206170
206397
|
// constant block: reset the block buffer
|
|
206171
206398
|
D_ASSERT(stats.statistics->IsConstant());
|
|
@@ -206797,8 +207024,8 @@ void ListColumnData::CommitDropColumn() {
|
|
|
206797
207024
|
}
|
|
206798
207025
|
|
|
206799
207026
|
struct ListColumnCheckpointState : public ColumnCheckpointState {
|
|
206800
|
-
ListColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
206801
|
-
: ColumnCheckpointState(row_group, column_data,
|
|
207027
|
+
ListColumnCheckpointState(RowGroup &row_group, ColumnData &column_data, PartialBlockManager &partial_block_manager)
|
|
207028
|
+
: ColumnCheckpointState(row_group, column_data, partial_block_manager) {
|
|
206802
207029
|
global_stats = make_unique<ListStatistics>(column_data.type);
|
|
206803
207030
|
}
|
|
206804
207031
|
|
|
@@ -206814,22 +207041,29 @@ public:
|
|
|
206814
207041
|
return stats;
|
|
206815
207042
|
}
|
|
206816
207043
|
|
|
206817
|
-
void WriteDataPointers() override {
|
|
206818
|
-
ColumnCheckpointState::WriteDataPointers();
|
|
206819
|
-
validity_state->WriteDataPointers();
|
|
206820
|
-
child_state->WriteDataPointers();
|
|
207044
|
+
void WriteDataPointers(RowGroupWriter &writer) override {
|
|
207045
|
+
ColumnCheckpointState::WriteDataPointers(writer);
|
|
207046
|
+
validity_state->WriteDataPointers(writer);
|
|
207047
|
+
child_state->WriteDataPointers(writer);
|
|
207048
|
+
}
|
|
207049
|
+
void GetBlockIds(unordered_set<block_id_t> &result) override {
|
|
207050
|
+
ColumnCheckpointState::GetBlockIds(result);
|
|
207051
|
+
validity_state->GetBlockIds(result);
|
|
207052
|
+
child_state->GetBlockIds(result);
|
|
206821
207053
|
}
|
|
206822
207054
|
};
|
|
206823
207055
|
|
|
206824
|
-
unique_ptr<ColumnCheckpointState> ListColumnData::CreateCheckpointState(RowGroup &row_group,
|
|
206825
|
-
|
|
207056
|
+
unique_ptr<ColumnCheckpointState> ListColumnData::CreateCheckpointState(RowGroup &row_group,
|
|
207057
|
+
PartialBlockManager &partial_block_manager) {
|
|
207058
|
+
return make_unique<ListColumnCheckpointState>(row_group, *this, partial_block_manager);
|
|
206826
207059
|
}
|
|
206827
207060
|
|
|
206828
|
-
unique_ptr<ColumnCheckpointState> ListColumnData::Checkpoint(RowGroup &row_group,
|
|
207061
|
+
unique_ptr<ColumnCheckpointState> ListColumnData::Checkpoint(RowGroup &row_group,
|
|
207062
|
+
PartialBlockManager &partial_block_manager,
|
|
206829
207063
|
ColumnCheckpointInfo &checkpoint_info) {
|
|
206830
|
-
auto validity_state = validity.Checkpoint(row_group,
|
|
206831
|
-
auto base_state = ColumnData::Checkpoint(row_group,
|
|
206832
|
-
auto child_state = child_column->Checkpoint(row_group,
|
|
207064
|
+
auto validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info);
|
|
207065
|
+
auto base_state = ColumnData::Checkpoint(row_group, partial_block_manager, checkpoint_info);
|
|
207066
|
+
auto child_state = child_column->Checkpoint(row_group, partial_block_manager, checkpoint_info);
|
|
206833
207067
|
|
|
206834
207068
|
auto &checkpoint_state = (ListColumnCheckpointState &)*base_state;
|
|
206835
207069
|
checkpoint_state.validity_state = move(validity_state);
|
|
@@ -207545,10 +207779,11 @@ void RowGroup::MergeIntoStatistics(idx_t column_idx, BaseStatistics &other) {
|
|
|
207545
207779
|
other.Merge(*stats[column_idx]->statistics);
|
|
207546
207780
|
}
|
|
207547
207781
|
|
|
207548
|
-
|
|
207549
|
-
|
|
207550
|
-
|
|
207551
|
-
states.reserve(columns.size());
|
|
207782
|
+
RowGroupWriteData RowGroup::WriteToDisk(PartialBlockManager &manager,
|
|
207783
|
+
const vector<CompressionType> &compression_types) {
|
|
207784
|
+
RowGroupWriteData result;
|
|
207785
|
+
result.states.reserve(columns.size());
|
|
207786
|
+
result.statistics.reserve(columns.size());
|
|
207552
207787
|
|
|
207553
207788
|
// Checkpoint the individual columns of the row group
|
|
207554
207789
|
// Here we're iterating over columns. Each column can have multiple segments.
|
|
@@ -207560,23 +207795,39 @@ RowGroupPointer RowGroup::Checkpoint(RowGroupWriter &writer, vector<unique_ptr<B
|
|
|
207560
207795
|
// pointers all end up densely packed, and thus more cache-friendly.
|
|
207561
207796
|
for (idx_t column_idx = 0; column_idx < columns.size(); column_idx++) {
|
|
207562
207797
|
auto &column = columns[column_idx];
|
|
207563
|
-
ColumnCheckpointInfo checkpoint_info {
|
|
207564
|
-
auto checkpoint_state = column->Checkpoint(*this,
|
|
207798
|
+
ColumnCheckpointInfo checkpoint_info {compression_types[column_idx]};
|
|
207799
|
+
auto checkpoint_state = column->Checkpoint(*this, manager, checkpoint_info);
|
|
207565
207800
|
D_ASSERT(checkpoint_state);
|
|
207566
207801
|
|
|
207567
207802
|
auto stats = checkpoint_state->GetStatistics();
|
|
207568
207803
|
D_ASSERT(stats);
|
|
207569
207804
|
|
|
207570
|
-
|
|
207571
|
-
|
|
207572
|
-
states.push_back(move(checkpoint_state));
|
|
207805
|
+
result.statistics.push_back(move(stats));
|
|
207806
|
+
result.states.push_back(move(checkpoint_state));
|
|
207573
207807
|
}
|
|
207808
|
+
D_ASSERT(result.states.size() == result.statistics.size());
|
|
207809
|
+
return result;
|
|
207810
|
+
}
|
|
207811
|
+
|
|
207812
|
+
RowGroupPointer RowGroup::Checkpoint(RowGroupWriter &writer, vector<unique_ptr<BaseStatistics>> &global_stats) {
|
|
207813
|
+
RowGroupPointer row_group_pointer;
|
|
207814
|
+
|
|
207815
|
+
vector<CompressionType> compression_types;
|
|
207816
|
+
compression_types.reserve(columns.size());
|
|
207817
|
+
for (idx_t column_idx = 0; column_idx < columns.size(); column_idx++) {
|
|
207818
|
+
compression_types.push_back(writer.GetColumnCompressionType(column_idx));
|
|
207819
|
+
}
|
|
207820
|
+
auto result = WriteToDisk(writer.GetPartialBlockManager(), compression_types);
|
|
207821
|
+
for (idx_t column_idx = 0; column_idx < columns.size(); column_idx++) {
|
|
207822
|
+
global_stats[column_idx]->Merge(*result.statistics[column_idx]);
|
|
207823
|
+
}
|
|
207824
|
+
row_group_pointer.statistics = move(result.statistics);
|
|
207574
207825
|
|
|
207575
207826
|
// construct the row group pointer and write the column meta data to disk
|
|
207576
|
-
D_ASSERT(states.size() == columns.size());
|
|
207827
|
+
D_ASSERT(result.states.size() == columns.size());
|
|
207577
207828
|
row_group_pointer.row_start = start;
|
|
207578
207829
|
row_group_pointer.tuple_count = count;
|
|
207579
|
-
for (auto &state : states) {
|
|
207830
|
+
for (auto &state : result.states) {
|
|
207580
207831
|
// get the current position of the table data writer
|
|
207581
207832
|
auto &data_writer = writer.GetPayloadWriter();
|
|
207582
207833
|
auto pointer = data_writer.GetBlockPointer();
|
|
@@ -207588,7 +207839,7 @@ RowGroupPointer RowGroup::Checkpoint(RowGroupWriter &writer, vector<unique_ptr<B
|
|
|
207588
207839
|
//
|
|
207589
207840
|
// Just as above, the state can refer to many other states, so this
|
|
207590
207841
|
// can cascade recursively into more pointer writes.
|
|
207591
|
-
state->WriteDataPointers();
|
|
207842
|
+
state->WriteDataPointers(writer);
|
|
207592
207843
|
}
|
|
207593
207844
|
row_group_pointer.versions = version_info;
|
|
207594
207845
|
Verify();
|
|
@@ -207849,6 +208100,10 @@ void RowGroupCollection::AppendRowGroup(idx_t start_row) {
|
|
|
207849
208100
|
row_groups->AppendSegment(move(new_row_group));
|
|
207850
208101
|
}
|
|
207851
208102
|
|
|
208103
|
+
RowGroup *RowGroupCollection::GetRowGroup(int64_t index) {
|
|
208104
|
+
return (RowGroup *)row_groups->GetSegmentByIndex(index);
|
|
208105
|
+
}
|
|
208106
|
+
|
|
207852
208107
|
void RowGroupCollection::Verify() {
|
|
207853
208108
|
#ifdef DEBUG
|
|
207854
208109
|
idx_t current_total_rows = 0;
|
|
@@ -207999,10 +208254,11 @@ void RowGroupCollection::InitializeAppend(TableAppendState &state) {
|
|
|
207999
208254
|
InitializeAppend(tdata, state, 0);
|
|
208000
208255
|
}
|
|
208001
208256
|
|
|
208002
|
-
|
|
208257
|
+
bool RowGroupCollection::Append(DataChunk &chunk, TableAppendState &state, TableStatistics &stats) {
|
|
208003
208258
|
D_ASSERT(chunk.ColumnCount() == types.size());
|
|
208004
208259
|
chunk.Verify();
|
|
208005
208260
|
|
|
208261
|
+
bool new_row_group = false;
|
|
208006
208262
|
idx_t append_count = chunk.size();
|
|
208007
208263
|
idx_t remaining = chunk.size();
|
|
208008
208264
|
state.total_append_count += append_count;
|
|
@@ -208036,6 +208292,7 @@ void RowGroupCollection::Append(DataChunk &chunk, TableAppendState &state, Table
|
|
|
208036
208292
|
chunk.Slice(sel, remaining);
|
|
208037
208293
|
}
|
|
208038
208294
|
// append a new row_group
|
|
208295
|
+
new_row_group = true;
|
|
208039
208296
|
auto next_start = current_row_group->start + state.row_group_append_state.offset_in_row_group;
|
|
208040
208297
|
AppendRowGroup(next_start);
|
|
208041
208298
|
// set up the append state for this row_group
|
|
@@ -208059,6 +208316,7 @@ void RowGroupCollection::Append(DataChunk &chunk, TableAppendState &state, Table
|
|
|
208059
208316
|
}
|
|
208060
208317
|
stats.GetStats(col_idx).stats->UpdateDistinctStatistics(chunk.data[col_idx], chunk.size());
|
|
208061
208318
|
}
|
|
208319
|
+
return new_row_group;
|
|
208062
208320
|
}
|
|
208063
208321
|
|
|
208064
208322
|
void RowGroupCollection::FinalizeAppend(TransactionData transaction, TableAppendState &state) {
|
|
@@ -208099,12 +208357,7 @@ void RowGroupCollection::CommitAppend(transaction_t commit_id, idx_t row_start,
|
|
|
208099
208357
|
|
|
208100
208358
|
void RowGroupCollection::RevertAppendInternal(idx_t start_row, idx_t count) {
|
|
208101
208359
|
if (total_rows != start_row + count) {
|
|
208102
|
-
|
|
208103
|
-
// in this case the rows will stay as "inserted by transaction X", but will never be committed
|
|
208104
|
-
// they will never be used by any other transaction and will essentially leave a gap
|
|
208105
|
-
// this situation is rare, and as such we don't care about optimizing it (yet?)
|
|
208106
|
-
// it only happens if C1 appends a lot of data -> C2 appends a lot of data -> C1 rolls back
|
|
208107
|
-
return;
|
|
208360
|
+
throw InternalException("Interleaved appends: this should no longer happen");
|
|
208108
208361
|
}
|
|
208109
208362
|
total_rows = start_row;
|
|
208110
208363
|
|
|
@@ -208559,6 +208812,21 @@ SegmentBase *SegmentTree::GetRootSegment() {
|
|
|
208559
208812
|
return root_node.get();
|
|
208560
208813
|
}
|
|
208561
208814
|
|
|
208815
|
+
SegmentBase *SegmentTree::GetSegmentByIndex(int64_t index) {
|
|
208816
|
+
if (index < 0) {
|
|
208817
|
+
index = nodes.size() + index;
|
|
208818
|
+
if (index < 0) {
|
|
208819
|
+
return nullptr;
|
|
208820
|
+
}
|
|
208821
|
+
return nodes[index].node;
|
|
208822
|
+
} else {
|
|
208823
|
+
if (idx_t(index) >= nodes.size()) {
|
|
208824
|
+
return nullptr;
|
|
208825
|
+
}
|
|
208826
|
+
return nodes[index].node;
|
|
208827
|
+
}
|
|
208828
|
+
}
|
|
208829
|
+
|
|
208562
208830
|
SegmentBase *SegmentTree::GetLastSegment() {
|
|
208563
208831
|
return nodes.empty() ? nullptr : nodes.back().node;
|
|
208564
208832
|
}
|
|
@@ -208591,6 +208859,16 @@ idx_t SegmentTree::GetSegmentIndex(idx_t row_number) {
|
|
|
208591
208859
|
throw InternalException("Could not find node in column segment tree!");
|
|
208592
208860
|
}
|
|
208593
208861
|
|
|
208862
|
+
bool SegmentTree::HasSegment(SegmentBase *segment) {
|
|
208863
|
+
lock_guard<mutex> tree_lock(node_lock);
|
|
208864
|
+
for (auto &node : nodes) {
|
|
208865
|
+
if (node.node == segment) {
|
|
208866
|
+
return true;
|
|
208867
|
+
}
|
|
208868
|
+
}
|
|
208869
|
+
return false;
|
|
208870
|
+
}
|
|
208871
|
+
|
|
208594
208872
|
void SegmentTree::AppendSegment(unique_ptr<SegmentBase> segment) {
|
|
208595
208873
|
D_ASSERT(segment);
|
|
208596
208874
|
// add the node to the list of nodes
|
|
@@ -208775,8 +209053,9 @@ void StandardColumnData::CommitDropColumn() {
|
|
|
208775
209053
|
}
|
|
208776
209054
|
|
|
208777
209055
|
struct StandardColumnCheckpointState : public ColumnCheckpointState {
|
|
208778
|
-
StandardColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
208779
|
-
|
|
209056
|
+
StandardColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
209057
|
+
PartialBlockManager &partial_block_manager)
|
|
209058
|
+
: ColumnCheckpointState(row_group, column_data, partial_block_manager) {
|
|
208780
209059
|
}
|
|
208781
209060
|
|
|
208782
209061
|
unique_ptr<ColumnCheckpointState> validity_state;
|
|
@@ -208788,21 +209067,27 @@ public:
|
|
|
208788
209067
|
return move(global_stats);
|
|
208789
209068
|
}
|
|
208790
209069
|
|
|
208791
|
-
void WriteDataPointers() override {
|
|
208792
|
-
ColumnCheckpointState::WriteDataPointers();
|
|
208793
|
-
validity_state->WriteDataPointers();
|
|
209070
|
+
void WriteDataPointers(RowGroupWriter &writer) override {
|
|
209071
|
+
ColumnCheckpointState::WriteDataPointers(writer);
|
|
209072
|
+
validity_state->WriteDataPointers(writer);
|
|
209073
|
+
}
|
|
209074
|
+
|
|
209075
|
+
void GetBlockIds(unordered_set<block_id_t> &result) override {
|
|
209076
|
+
ColumnCheckpointState::GetBlockIds(result);
|
|
209077
|
+
validity_state->GetBlockIds(result);
|
|
208794
209078
|
}
|
|
208795
209079
|
};
|
|
208796
209080
|
|
|
208797
|
-
unique_ptr<ColumnCheckpointState>
|
|
208798
|
-
|
|
208799
|
-
return make_unique<StandardColumnCheckpointState>(row_group, *this,
|
|
209081
|
+
unique_ptr<ColumnCheckpointState>
|
|
209082
|
+
StandardColumnData::CreateCheckpointState(RowGroup &row_group, PartialBlockManager &partial_block_manager) {
|
|
209083
|
+
return make_unique<StandardColumnCheckpointState>(row_group, *this, partial_block_manager);
|
|
208800
209084
|
}
|
|
208801
209085
|
|
|
208802
|
-
unique_ptr<ColumnCheckpointState> StandardColumnData::Checkpoint(RowGroup &row_group,
|
|
209086
|
+
unique_ptr<ColumnCheckpointState> StandardColumnData::Checkpoint(RowGroup &row_group,
|
|
209087
|
+
PartialBlockManager &partial_block_manager,
|
|
208803
209088
|
ColumnCheckpointInfo &checkpoint_info) {
|
|
208804
|
-
auto validity_state = validity.Checkpoint(row_group,
|
|
208805
|
-
auto base_state = ColumnData::Checkpoint(row_group,
|
|
209089
|
+
auto validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info);
|
|
209090
|
+
auto base_state = ColumnData::Checkpoint(row_group, partial_block_manager, checkpoint_info);
|
|
208806
209091
|
auto &checkpoint_state = (StandardColumnCheckpointState &)*base_state;
|
|
208807
209092
|
checkpoint_state.validity_state = move(validity_state);
|
|
208808
209093
|
return base_state;
|
|
@@ -209074,8 +209359,9 @@ void StructColumnData::CommitDropColumn() {
|
|
|
209074
209359
|
}
|
|
209075
209360
|
|
|
209076
209361
|
struct StructColumnCheckpointState : public ColumnCheckpointState {
|
|
209077
|
-
StructColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
209078
|
-
|
|
209362
|
+
StructColumnCheckpointState(RowGroup &row_group, ColumnData &column_data,
|
|
209363
|
+
PartialBlockManager &partial_block_manager)
|
|
209364
|
+
: ColumnCheckpointState(row_group, column_data, partial_block_manager) {
|
|
209079
209365
|
global_stats = make_unique<StructStatistics>(column_data.type);
|
|
209080
209366
|
}
|
|
209081
209367
|
|
|
@@ -209094,24 +209380,33 @@ public:
|
|
|
209094
209380
|
return move(stats);
|
|
209095
209381
|
}
|
|
209096
209382
|
|
|
209097
|
-
void WriteDataPointers() override {
|
|
209098
|
-
validity_state->WriteDataPointers();
|
|
209383
|
+
void WriteDataPointers(RowGroupWriter &writer) override {
|
|
209384
|
+
validity_state->WriteDataPointers(writer);
|
|
209385
|
+
for (auto &state : child_states) {
|
|
209386
|
+
state->WriteDataPointers(writer);
|
|
209387
|
+
}
|
|
209388
|
+
}
|
|
209389
|
+
void GetBlockIds(unordered_set<block_id_t> &result) override {
|
|
209390
|
+
validity_state->GetBlockIds(result);
|
|
209099
209391
|
for (auto &state : child_states) {
|
|
209100
|
-
state->
|
|
209392
|
+
state->GetBlockIds(result);
|
|
209101
209393
|
}
|
|
209102
209394
|
}
|
|
209103
209395
|
};
|
|
209104
209396
|
|
|
209105
|
-
unique_ptr<ColumnCheckpointState> StructColumnData::CreateCheckpointState(RowGroup &row_group,
|
|
209106
|
-
|
|
209397
|
+
unique_ptr<ColumnCheckpointState> StructColumnData::CreateCheckpointState(RowGroup &row_group,
|
|
209398
|
+
PartialBlockManager &partial_block_manager) {
|
|
209399
|
+
return make_unique<StructColumnCheckpointState>(row_group, *this, partial_block_manager);
|
|
209107
209400
|
}
|
|
209108
209401
|
|
|
209109
|
-
unique_ptr<ColumnCheckpointState> StructColumnData::Checkpoint(RowGroup &row_group,
|
|
209402
|
+
unique_ptr<ColumnCheckpointState> StructColumnData::Checkpoint(RowGroup &row_group,
|
|
209403
|
+
PartialBlockManager &partial_block_manager,
|
|
209110
209404
|
ColumnCheckpointInfo &checkpoint_info) {
|
|
209111
|
-
auto checkpoint_state = make_unique<StructColumnCheckpointState>(row_group, *this,
|
|
209112
|
-
checkpoint_state->validity_state = validity.Checkpoint(row_group,
|
|
209405
|
+
auto checkpoint_state = make_unique<StructColumnCheckpointState>(row_group, *this, partial_block_manager);
|
|
209406
|
+
checkpoint_state->validity_state = validity.Checkpoint(row_group, partial_block_manager, checkpoint_info);
|
|
209113
209407
|
for (auto &sub_column : sub_columns) {
|
|
209114
|
-
checkpoint_state->child_states.push_back(
|
|
209408
|
+
checkpoint_state->child_states.push_back(
|
|
209409
|
+
sub_column->Checkpoint(row_group, partial_block_manager, checkpoint_info));
|
|
209115
209410
|
}
|
|
209116
209411
|
return move(checkpoint_state);
|
|
209117
209412
|
}
|
|
@@ -212062,6 +212357,7 @@ void RollbackState::RollbackEntry(UndoFlags type, data_ptr_t data) {
|
|
|
212062
212357
|
|
|
212063
212358
|
|
|
212064
212359
|
|
|
212360
|
+
|
|
212065
212361
|
#include <cstring>
|
|
212066
212362
|
|
|
212067
212363
|
namespace duckdb {
|
|
@@ -212077,13 +212373,21 @@ Transaction::Transaction(weak_ptr<ClientContext> context_p, transaction_t start_
|
|
|
212077
212373
|
timestamp_t start_timestamp, idx_t catalog_version)
|
|
212078
212374
|
: context(move(context_p)), start_time(start_time), transaction_id(transaction_id), commit_id(0),
|
|
212079
212375
|
highest_active_query(0), active_query(MAXIMUM_QUERY_ID), start_timestamp(start_timestamp),
|
|
212080
|
-
catalog_version(catalog_version),
|
|
212376
|
+
catalog_version(catalog_version), is_invalidated(false), undo_buffer(context.lock()),
|
|
212377
|
+
storage(make_unique<LocalStorage>(*this)) {
|
|
212378
|
+
}
|
|
212379
|
+
|
|
212380
|
+
Transaction::~Transaction() {
|
|
212081
212381
|
}
|
|
212082
212382
|
|
|
212083
212383
|
Transaction &Transaction::GetTransaction(ClientContext &context) {
|
|
212084
212384
|
return context.ActiveTransaction();
|
|
212085
212385
|
}
|
|
212086
212386
|
|
|
212387
|
+
LocalStorage &Transaction::GetLocalStorage() {
|
|
212388
|
+
return *storage;
|
|
212389
|
+
}
|
|
212390
|
+
|
|
212087
212391
|
void Transaction::PushCatalogEntry(CatalogEntry *entry, data_ptr_t extra_data, idx_t extra_data_size) {
|
|
212088
212392
|
idx_t alloc_size = sizeof(CatalogEntry *);
|
|
212089
212393
|
if (extra_data_size > 0) {
|
|
@@ -212131,12 +212435,12 @@ UpdateInfo *Transaction::CreateUpdateInfo(idx_t type_size, idx_t entries) {
|
|
|
212131
212435
|
}
|
|
212132
212436
|
|
|
212133
212437
|
bool Transaction::ChangesMade() {
|
|
212134
|
-
return undo_buffer.ChangesMade() || storage
|
|
212438
|
+
return undo_buffer.ChangesMade() || storage->ChangesMade();
|
|
212135
212439
|
}
|
|
212136
212440
|
|
|
212137
212441
|
bool Transaction::AutomaticCheckpoint(DatabaseInstance &db) {
|
|
212138
212442
|
auto &storage_manager = StorageManager::GetStorageManager(db);
|
|
212139
|
-
return storage_manager.AutomaticCheckpoint(storage
|
|
212443
|
+
return storage_manager.AutomaticCheckpoint(storage->EstimatedSize() + undo_buffer.EstimatedSize());
|
|
212140
212444
|
}
|
|
212141
212445
|
|
|
212142
212446
|
string Transaction::Commit(DatabaseInstance &db, transaction_t commit_id, bool checkpoint) noexcept {
|
|
@@ -212152,7 +212456,7 @@ string Transaction::Commit(DatabaseInstance &db, transaction_t commit_id, bool c
|
|
|
212152
212456
|
LocalStorage::CommitState commit_state;
|
|
212153
212457
|
auto storage_commit_state = storage_manager.GenStorageCommitState(*this, checkpoint);
|
|
212154
212458
|
try {
|
|
212155
|
-
storage
|
|
212459
|
+
storage->Commit(commit_state, *this);
|
|
212156
212460
|
undo_buffer.Commit(iterator_state, log, commit_id);
|
|
212157
212461
|
if (log) {
|
|
212158
212462
|
// commit any sequences that were used to the WAL
|
|
@@ -212168,6 +212472,22 @@ string Transaction::Commit(DatabaseInstance &db, transaction_t commit_id, bool c
|
|
|
212168
212472
|
}
|
|
212169
212473
|
}
|
|
212170
212474
|
|
|
212475
|
+
void Transaction::Rollback() noexcept {
|
|
212476
|
+
storage->Rollback();
|
|
212477
|
+
undo_buffer.Rollback();
|
|
212478
|
+
}
|
|
212479
|
+
|
|
212480
|
+
void Transaction::Cleanup() {
|
|
212481
|
+
undo_buffer.Cleanup();
|
|
212482
|
+
}
|
|
212483
|
+
|
|
212484
|
+
void Transaction::Invalidate() {
|
|
212485
|
+
is_invalidated = true;
|
|
212486
|
+
}
|
|
212487
|
+
bool Transaction::IsInvalidated() {
|
|
212488
|
+
return is_invalidated;
|
|
212489
|
+
}
|
|
212490
|
+
|
|
212171
212491
|
} // namespace duckdb
|
|
212172
212492
|
|
|
212173
212493
|
|