duckdb 0.8.2-dev4314.0 → 0.8.2-dev4424.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/extension/parquet/parquet_extension.cpp +1 -1
- package/src/duckdb/src/common/enum_util.cpp +5 -0
- package/src/duckdb/src/common/file_buffer.cpp +1 -1
- package/src/duckdb/src/common/types/date.cpp +1 -1
- package/src/duckdb/src/common/types/validity_mask.cpp +56 -0
- package/src/duckdb/src/execution/index/fixed_size_buffer.cpp +3 -10
- package/src/duckdb/src/execution/operator/csv_scanner/parallel_csv_reader.cpp +6 -3
- package/src/duckdb/src/execution/operator/persistent/physical_batch_insert.cpp +1 -1
- package/src/duckdb/src/execution/operator/persistent/physical_insert.cpp +1 -1
- package/src/duckdb/src/function/table/arrow_conversion.cpp +9 -1
- package/src/duckdb/src/function/table/read_csv.cpp +5 -22
- package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
- package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -15
- package/src/duckdb/src/include/duckdb/common/serializer/memory_stream.hpp +1 -1
- package/src/duckdb/src/include/duckdb/common/types/validity_mask.hpp +3 -0
- package/src/duckdb/src/include/duckdb/function/table/arrow.hpp +3 -0
- package/src/duckdb/src/include/duckdb/main/query_result.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/block.hpp +3 -3
- package/src/duckdb/src/include/duckdb/storage/compression/bitpacking.hpp +1 -8
- package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +2 -2
- package/src/duckdb/src/include/duckdb/storage/metadata/metadata_manager.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/metadata/metadata_reader.hpp +2 -0
- package/src/duckdb/src/include/duckdb/storage/metadata/metadata_writer.hpp +6 -2
- package/src/duckdb/src/include/duckdb/storage/storage_info.hpp +19 -0
- package/src/duckdb/src/include/duckdb/storage/table/chunk_info.hpp +19 -13
- package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +1 -1
- package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +15 -15
- package/src/duckdb/src/include/duckdb/storage/table/row_version_manager.hpp +59 -0
- package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +1 -1
- package/src/duckdb/src/include/duckdb/transaction/commit_state.hpp +1 -6
- package/src/duckdb/src/include/duckdb/transaction/delete_info.hpp +3 -2
- package/src/duckdb/src/include/duckdb/transaction/duck_transaction.hpp +4 -2
- package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +1 -1
- package/src/duckdb/src/include/duckdb/transaction/undo_buffer.hpp +0 -1
- package/src/duckdb/src/main/settings/settings.cpp +5 -10
- package/src/duckdb/src/optimizer/statistics/expression/propagate_cast.cpp +14 -0
- package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +0 -1
- package/src/duckdb/src/storage/checkpoint_manager.cpp +37 -36
- package/src/duckdb/src/storage/compression/bitpacking.cpp +55 -48
- package/src/duckdb/src/storage/data_table.cpp +1 -1
- package/src/duckdb/src/storage/local_storage.cpp +9 -2
- package/src/duckdb/src/storage/metadata/metadata_manager.cpp +41 -2
- package/src/duckdb/src/storage/metadata/metadata_reader.cpp +12 -3
- package/src/duckdb/src/storage/metadata/metadata_writer.cpp +8 -2
- package/src/duckdb/src/storage/single_file_block_manager.cpp +1 -2
- package/src/duckdb/src/storage/storage_info.cpp +1 -1
- package/src/duckdb/src/storage/table/chunk_info.cpp +39 -33
- package/src/duckdb/src/storage/table/column_data.cpp +14 -9
- package/src/duckdb/src/storage/table/list_column_data.cpp +2 -2
- package/src/duckdb/src/storage/table/row_group.cpp +102 -192
- package/src/duckdb/src/storage/table/row_group_collection.cpp +2 -2
- package/src/duckdb/src/storage/table/row_version_manager.cpp +228 -0
- package/src/duckdb/src/storage/table/update_segment.cpp +2 -2
- package/src/duckdb/src/transaction/cleanup_state.cpp +2 -1
- package/src/duckdb/src/transaction/commit_state.cpp +5 -4
- package/src/duckdb/src/transaction/duck_transaction.cpp +4 -2
- package/src/duckdb/src/transaction/rollback_state.cpp +2 -1
- package/src/duckdb/src/transaction/undo_buffer.cpp +3 -5
- package/src/duckdb/ub_src_storage_table.cpp +2 -0
- package/test/prepare.test.ts +10 -1
- package/test/test_all_types.test.ts +4 -4
@@ -0,0 +1,228 @@
|
|
1
|
+
#include "duckdb/storage/table/row_version_manager.hpp"
|
2
|
+
#include "duckdb/transaction/transaction_data.hpp"
|
3
|
+
#include "duckdb/storage/metadata/metadata_manager.hpp"
|
4
|
+
#include "duckdb/storage/metadata/metadata_reader.hpp"
|
5
|
+
#include "duckdb/storage/metadata/metadata_writer.hpp"
|
6
|
+
#include "duckdb/common/pair.hpp"
|
7
|
+
|
8
|
+
namespace duckdb {
|
9
|
+
|
10
|
+
RowVersionManager::RowVersionManager(idx_t start) : start(start), has_changes(false) {
|
11
|
+
}
|
12
|
+
|
13
|
+
void RowVersionManager::SetStart(idx_t new_start) {
|
14
|
+
lock_guard<mutex> l(version_lock);
|
15
|
+
this->start = new_start;
|
16
|
+
idx_t current_start = start;
|
17
|
+
for (idx_t i = 0; i < Storage::ROW_GROUP_VECTOR_COUNT; i++) {
|
18
|
+
if (vector_info[i]) {
|
19
|
+
vector_info[i]->start = current_start;
|
20
|
+
}
|
21
|
+
current_start += STANDARD_VECTOR_SIZE;
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
idx_t RowVersionManager::GetCommittedDeletedCount(idx_t count) {
|
26
|
+
lock_guard<mutex> l(version_lock);
|
27
|
+
idx_t deleted_count = 0;
|
28
|
+
for (idx_t r = 0, i = 0; r < count; r += STANDARD_VECTOR_SIZE, i++) {
|
29
|
+
if (!vector_info[i]) {
|
30
|
+
continue;
|
31
|
+
}
|
32
|
+
idx_t max_count = MinValue<idx_t>(STANDARD_VECTOR_SIZE, count - r);
|
33
|
+
if (max_count == 0) {
|
34
|
+
break;
|
35
|
+
}
|
36
|
+
deleted_count += vector_info[i]->GetCommittedDeletedCount(max_count);
|
37
|
+
}
|
38
|
+
return deleted_count;
|
39
|
+
}
|
40
|
+
|
41
|
+
optional_ptr<ChunkInfo> RowVersionManager::GetChunkInfo(idx_t vector_idx) {
|
42
|
+
return vector_info[vector_idx].get();
|
43
|
+
}
|
44
|
+
|
45
|
+
idx_t RowVersionManager::GetSelVector(TransactionData transaction, idx_t vector_idx, SelectionVector &sel_vector,
|
46
|
+
idx_t max_count) {
|
47
|
+
lock_guard<mutex> l(version_lock);
|
48
|
+
auto chunk_info = GetChunkInfo(vector_idx);
|
49
|
+
if (!chunk_info) {
|
50
|
+
return max_count;
|
51
|
+
}
|
52
|
+
return chunk_info->GetSelVector(transaction, sel_vector, max_count);
|
53
|
+
}
|
54
|
+
|
55
|
+
idx_t RowVersionManager::GetCommittedSelVector(transaction_t start_time, transaction_t transaction_id, idx_t vector_idx,
|
56
|
+
SelectionVector &sel_vector, idx_t max_count) {
|
57
|
+
lock_guard<mutex> l(version_lock);
|
58
|
+
auto info = GetChunkInfo(vector_idx);
|
59
|
+
if (!info) {
|
60
|
+
return max_count;
|
61
|
+
}
|
62
|
+
return info->GetCommittedSelVector(start_time, transaction_id, sel_vector, max_count);
|
63
|
+
}
|
64
|
+
|
65
|
+
bool RowVersionManager::Fetch(TransactionData transaction, idx_t row) {
|
66
|
+
lock_guard<mutex> lock(version_lock);
|
67
|
+
idx_t vector_index = row / STANDARD_VECTOR_SIZE;
|
68
|
+
auto info = GetChunkInfo(vector_index);
|
69
|
+
if (!info) {
|
70
|
+
return true;
|
71
|
+
}
|
72
|
+
return info->Fetch(transaction, row - vector_index * STANDARD_VECTOR_SIZE);
|
73
|
+
}
|
74
|
+
|
75
|
+
void RowVersionManager::AppendVersionInfo(TransactionData transaction, idx_t count, idx_t row_group_start,
|
76
|
+
idx_t row_group_end) {
|
77
|
+
lock_guard<mutex> lock(version_lock);
|
78
|
+
has_changes = true;
|
79
|
+
idx_t start_vector_idx = row_group_start / STANDARD_VECTOR_SIZE;
|
80
|
+
idx_t end_vector_idx = (row_group_end - 1) / STANDARD_VECTOR_SIZE;
|
81
|
+
for (idx_t vector_idx = start_vector_idx; vector_idx <= end_vector_idx; vector_idx++) {
|
82
|
+
idx_t vector_start =
|
83
|
+
vector_idx == start_vector_idx ? row_group_start - start_vector_idx * STANDARD_VECTOR_SIZE : 0;
|
84
|
+
idx_t vector_end =
|
85
|
+
vector_idx == end_vector_idx ? row_group_end - end_vector_idx * STANDARD_VECTOR_SIZE : STANDARD_VECTOR_SIZE;
|
86
|
+
if (vector_start == 0 && vector_end == STANDARD_VECTOR_SIZE) {
|
87
|
+
// entire vector is encapsulated by append: append a single constant
|
88
|
+
auto constant_info = make_uniq<ChunkConstantInfo>(start + vector_idx * STANDARD_VECTOR_SIZE);
|
89
|
+
constant_info->insert_id = transaction.transaction_id;
|
90
|
+
constant_info->delete_id = NOT_DELETED_ID;
|
91
|
+
vector_info[vector_idx] = std::move(constant_info);
|
92
|
+
} else {
|
93
|
+
// part of a vector is encapsulated: append to that part
|
94
|
+
optional_ptr<ChunkVectorInfo> new_info;
|
95
|
+
if (!vector_info[vector_idx]) {
|
96
|
+
// first time appending to this vector: create new info
|
97
|
+
auto insert_info = make_uniq<ChunkVectorInfo>(start + vector_idx * STANDARD_VECTOR_SIZE);
|
98
|
+
new_info = insert_info.get();
|
99
|
+
vector_info[vector_idx] = std::move(insert_info);
|
100
|
+
} else if (vector_info[vector_idx]->type == ChunkInfoType::VECTOR_INFO) {
|
101
|
+
// use existing vector
|
102
|
+
new_info = &vector_info[vector_idx]->Cast<ChunkVectorInfo>();
|
103
|
+
} else {
|
104
|
+
throw InternalException("Error in RowVersionManager::AppendVersionInfo - expected either a "
|
105
|
+
"ChunkVectorInfo or no version info");
|
106
|
+
}
|
107
|
+
new_info->Append(vector_start, vector_end, transaction.transaction_id);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
void RowVersionManager::CommitAppend(transaction_t commit_id, idx_t row_group_start, idx_t count) {
|
113
|
+
idx_t row_group_end = row_group_start + count;
|
114
|
+
|
115
|
+
lock_guard<mutex> lock(version_lock);
|
116
|
+
idx_t start_vector_idx = row_group_start / STANDARD_VECTOR_SIZE;
|
117
|
+
idx_t end_vector_idx = (row_group_end - 1) / STANDARD_VECTOR_SIZE;
|
118
|
+
for (idx_t vector_idx = start_vector_idx; vector_idx <= end_vector_idx; vector_idx++) {
|
119
|
+
idx_t vstart = vector_idx == start_vector_idx ? row_group_start - start_vector_idx * STANDARD_VECTOR_SIZE : 0;
|
120
|
+
idx_t vend =
|
121
|
+
vector_idx == end_vector_idx ? row_group_end - end_vector_idx * STANDARD_VECTOR_SIZE : STANDARD_VECTOR_SIZE;
|
122
|
+
|
123
|
+
auto info = vector_info[vector_idx].get();
|
124
|
+
info->CommitAppend(commit_id, vstart, vend);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
void RowVersionManager::RevertAppend(idx_t start_row) {
|
129
|
+
lock_guard<mutex> lock(version_lock);
|
130
|
+
idx_t start_vector_idx = (start_row + (STANDARD_VECTOR_SIZE - 1)) / STANDARD_VECTOR_SIZE;
|
131
|
+
for (idx_t vector_idx = start_vector_idx; vector_idx < Storage::ROW_GROUP_VECTOR_COUNT; vector_idx++) {
|
132
|
+
vector_info[vector_idx].reset();
|
133
|
+
}
|
134
|
+
}
|
135
|
+
|
136
|
+
ChunkVectorInfo &RowVersionManager::GetVectorInfo(idx_t vector_idx) {
|
137
|
+
if (!vector_info[vector_idx]) {
|
138
|
+
// no info yet: create it
|
139
|
+
vector_info[vector_idx] = make_uniq<ChunkVectorInfo>(start + vector_idx * STANDARD_VECTOR_SIZE);
|
140
|
+
} else if (vector_info[vector_idx]->type == ChunkInfoType::CONSTANT_INFO) {
|
141
|
+
auto &constant = vector_info[vector_idx]->Cast<ChunkConstantInfo>();
|
142
|
+
// info exists but it's a constant info: convert to a vector info
|
143
|
+
auto new_info = make_uniq<ChunkVectorInfo>(start + vector_idx * STANDARD_VECTOR_SIZE);
|
144
|
+
new_info->insert_id = constant.insert_id;
|
145
|
+
for (idx_t i = 0; i < STANDARD_VECTOR_SIZE; i++) {
|
146
|
+
new_info->inserted[i] = constant.insert_id;
|
147
|
+
}
|
148
|
+
vector_info[vector_idx] = std::move(new_info);
|
149
|
+
}
|
150
|
+
D_ASSERT(vector_info[vector_idx]->type == ChunkInfoType::VECTOR_INFO);
|
151
|
+
return vector_info[vector_idx]->Cast<ChunkVectorInfo>();
|
152
|
+
}
|
153
|
+
|
154
|
+
idx_t RowVersionManager::DeleteRows(idx_t vector_idx, transaction_t transaction_id, row_t rows[], idx_t count) {
|
155
|
+
lock_guard<mutex> lock(version_lock);
|
156
|
+
has_changes = true;
|
157
|
+
return GetVectorInfo(vector_idx).Delete(transaction_id, rows, count);
|
158
|
+
}
|
159
|
+
|
160
|
+
void RowVersionManager::CommitDelete(idx_t vector_idx, transaction_t commit_id, row_t rows[], idx_t count) {
|
161
|
+
lock_guard<mutex> lock(version_lock);
|
162
|
+
has_changes = true;
|
163
|
+
GetVectorInfo(vector_idx).CommitDelete(commit_id, rows, count);
|
164
|
+
}
|
165
|
+
|
166
|
+
vector<MetaBlockPointer> RowVersionManager::Checkpoint(MetadataManager &manager) {
|
167
|
+
if (!has_changes && !storage_pointers.empty()) {
|
168
|
+
// the row version manager already exists on disk and no changes were made
|
169
|
+
// we can write the current pointer as-is
|
170
|
+
// ensure the blocks we are pointing to are not marked as free
|
171
|
+
manager.ClearModifiedBlocks(storage_pointers);
|
172
|
+
// return the root pointer
|
173
|
+
return storage_pointers;
|
174
|
+
}
|
175
|
+
// first count how many ChunkInfo's we need to deserialize
|
176
|
+
vector<pair<idx_t, reference<ChunkInfo>>> to_serialize;
|
177
|
+
for (idx_t vector_idx = 0; vector_idx < Storage::ROW_GROUP_VECTOR_COUNT; vector_idx++) {
|
178
|
+
auto chunk_info = vector_info[vector_idx].get();
|
179
|
+
if (!chunk_info) {
|
180
|
+
continue;
|
181
|
+
}
|
182
|
+
if (!chunk_info->HasDeletes()) {
|
183
|
+
continue;
|
184
|
+
}
|
185
|
+
to_serialize.emplace_back(vector_idx, *chunk_info);
|
186
|
+
}
|
187
|
+
if (to_serialize.empty()) {
|
188
|
+
return vector<MetaBlockPointer>();
|
189
|
+
}
|
190
|
+
|
191
|
+
storage_pointers.clear();
|
192
|
+
|
193
|
+
MetadataWriter writer(manager, &storage_pointers);
|
194
|
+
// now serialize the actual version information
|
195
|
+
writer.Write<idx_t>(to_serialize.size());
|
196
|
+
for (auto &entry : to_serialize) {
|
197
|
+
auto &vector_idx = entry.first;
|
198
|
+
auto &chunk_info = entry.second.get();
|
199
|
+
writer.Write<idx_t>(vector_idx);
|
200
|
+
chunk_info.Write(writer);
|
201
|
+
}
|
202
|
+
writer.Flush();
|
203
|
+
|
204
|
+
has_changes = false;
|
205
|
+
return storage_pointers;
|
206
|
+
}
|
207
|
+
|
208
|
+
shared_ptr<RowVersionManager> RowVersionManager::Deserialize(MetaBlockPointer delete_pointer, MetadataManager &manager,
|
209
|
+
idx_t start) {
|
210
|
+
if (!delete_pointer.IsValid()) {
|
211
|
+
return nullptr;
|
212
|
+
}
|
213
|
+
auto version_info = make_shared<RowVersionManager>(start);
|
214
|
+
MetadataReader source(manager, delete_pointer, &version_info->storage_pointers);
|
215
|
+
auto chunk_count = source.Read<idx_t>();
|
216
|
+
D_ASSERT(chunk_count > 0);
|
217
|
+
for (idx_t i = 0; i < chunk_count; i++) {
|
218
|
+
idx_t vector_index = source.Read<idx_t>();
|
219
|
+
if (vector_index >= Storage::ROW_GROUP_VECTOR_COUNT) {
|
220
|
+
throw Exception("In DeserializeDeletes, vector_index is out of range for the row group. Corrupted file?");
|
221
|
+
}
|
222
|
+
version_info->vector_info[vector_index] = ChunkInfo::Read(source);
|
223
|
+
}
|
224
|
+
version_info->has_changes = false;
|
225
|
+
return version_info;
|
226
|
+
}
|
227
|
+
|
228
|
+
} // namespace duckdb
|
@@ -328,7 +328,7 @@ void UpdateSegment::FetchCommittedRange(idx_t start_row, idx_t count, Vector &re
|
|
328
328
|
idx_t start_vector = start_row / STANDARD_VECTOR_SIZE;
|
329
329
|
idx_t end_vector = (end_row - 1) / STANDARD_VECTOR_SIZE;
|
330
330
|
D_ASSERT(start_vector <= end_vector);
|
331
|
-
D_ASSERT(end_vector <
|
331
|
+
D_ASSERT(end_vector < Storage::ROW_GROUP_VECTOR_COUNT);
|
332
332
|
|
333
333
|
for (idx_t vector_idx = start_vector; vector_idx <= end_vector; vector_idx++) {
|
334
334
|
if (!root->info[vector_idx]) {
|
@@ -1089,7 +1089,7 @@ void UpdateSegment::Update(TransactionData transaction, idx_t column_index, Vect
|
|
1089
1089
|
idx_t vector_offset = column_data.start + vector_index * STANDARD_VECTOR_SIZE;
|
1090
1090
|
|
1091
1091
|
D_ASSERT(idx_t(first_id) >= column_data.start);
|
1092
|
-
D_ASSERT(vector_index <
|
1092
|
+
D_ASSERT(vector_index < Storage::ROW_GROUP_VECTOR_COUNT);
|
1093
1093
|
|
1094
1094
|
// first check the version chain
|
1095
1095
|
UpdateInfo *node = nullptr;
|
@@ -8,6 +8,7 @@
|
|
8
8
|
#include "duckdb/catalog/dependency_manager.hpp"
|
9
9
|
#include "duckdb/storage/table/chunk_info.hpp"
|
10
10
|
#include "duckdb/storage/table/update_segment.hpp"
|
11
|
+
#include "duckdb/storage/table/row_version_manager.hpp"
|
11
12
|
|
12
13
|
namespace duckdb {
|
13
14
|
|
@@ -69,7 +70,7 @@ void CleanupState::CleanupDelete(DeleteInfo &info) {
|
|
69
70
|
|
70
71
|
count = 0;
|
71
72
|
for (idx_t i = 0; i < info.count; i++) {
|
72
|
-
row_numbers[count++] = info.
|
73
|
+
row_numbers[count++] = info.base_row + info.rows[i];
|
73
74
|
}
|
74
75
|
Flush();
|
75
76
|
}
|
@@ -16,13 +16,14 @@
|
|
16
16
|
#include "duckdb/transaction/update_info.hpp"
|
17
17
|
#include "duckdb/catalog/catalog_entry/scalar_macro_catalog_entry.hpp"
|
18
18
|
#include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp"
|
19
|
+
#include "duckdb/storage/table/row_version_manager.hpp"
|
19
20
|
#include "duckdb/common/serializer/binary_deserializer.hpp"
|
20
21
|
#include "duckdb/common/serializer/memory_stream.hpp"
|
21
22
|
|
22
23
|
namespace duckdb {
|
23
24
|
|
24
|
-
CommitState::CommitState(
|
25
|
-
: log(log), commit_id(commit_id), current_table_info(nullptr)
|
25
|
+
CommitState::CommitState(transaction_t commit_id, optional_ptr<WriteAheadLog> log)
|
26
|
+
: log(log), commit_id(commit_id), current_table_info(nullptr) {
|
26
27
|
}
|
27
28
|
|
28
29
|
void CommitState::SwitchTable(DataTableInfo *table_info, UndoFlags new_op) {
|
@@ -280,7 +281,7 @@ void CommitState::CommitEntry(UndoFlags type, data_ptr_t data) {
|
|
280
281
|
WriteDelete(*info);
|
281
282
|
}
|
282
283
|
// mark the tuples as committed
|
283
|
-
info->
|
284
|
+
info->version_info->CommitDelete(info->vector_idx, commit_id, info->rows, info->count);
|
284
285
|
break;
|
285
286
|
}
|
286
287
|
case UndoFlags::UPDATE_TUPLE: {
|
@@ -321,7 +322,7 @@ void CommitState::RevertCommit(UndoFlags type, data_ptr_t data) {
|
|
321
322
|
auto info = reinterpret_cast<DeleteInfo *>(data);
|
322
323
|
info->table->info->cardinality += info->count;
|
323
324
|
// revert the commit by writing the (uncommitted) transaction_id back into the version info
|
324
|
-
info->
|
325
|
+
info->version_info->CommitDelete(info->vector_idx, transaction_id, info->rows, info->count);
|
325
326
|
break;
|
326
327
|
}
|
327
328
|
case UndoFlags::UPDATE_TUPLE: {
|
@@ -70,10 +70,12 @@ void DuckTransaction::PushCatalogEntry(CatalogEntry &entry, data_ptr_t extra_dat
|
|
70
70
|
}
|
71
71
|
}
|
72
72
|
|
73
|
-
void DuckTransaction::PushDelete(DataTable &table,
|
73
|
+
void DuckTransaction::PushDelete(DataTable &table, RowVersionManager &info, idx_t vector_idx, row_t rows[], idx_t count,
|
74
|
+
idx_t base_row) {
|
74
75
|
auto delete_info = reinterpret_cast<DeleteInfo *>(
|
75
76
|
undo_buffer.CreateEntry(UndoFlags::DELETE_TUPLE, sizeof(DeleteInfo) + sizeof(row_t) * count));
|
76
|
-
delete_info->
|
77
|
+
delete_info->version_info = &info;
|
78
|
+
delete_info->vector_idx = vector_idx;
|
77
79
|
delete_info->table = &table;
|
78
80
|
delete_info->count = count;
|
79
81
|
delete_info->base_row = base_row;
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#include "duckdb/catalog/catalog_set.hpp"
|
10
10
|
#include "duckdb/storage/data_table.hpp"
|
11
11
|
#include "duckdb/storage/table/update_segment.hpp"
|
12
|
+
#include "duckdb/storage/table/row_version_manager.hpp"
|
12
13
|
|
13
14
|
namespace duckdb {
|
14
15
|
|
@@ -30,7 +31,7 @@ void RollbackState::RollbackEntry(UndoFlags type, data_ptr_t data) {
|
|
30
31
|
case UndoFlags::DELETE_TUPLE: {
|
31
32
|
auto info = reinterpret_cast<DeleteInfo *>(data);
|
32
33
|
// reset the deleted flag on rollback
|
33
|
-
info->
|
34
|
+
info->version_info->CommitDelete(info->vector_idx, NOT_DELETED_ID, info->rows, info->count);
|
34
35
|
break;
|
35
36
|
}
|
36
37
|
case UndoFlags::UPDATE_TUPLE: {
|
@@ -11,12 +11,10 @@
|
|
11
11
|
#include "duckdb/transaction/rollback_state.hpp"
|
12
12
|
#include "duckdb/common/pair.hpp"
|
13
13
|
|
14
|
-
#include <unordered_map>
|
15
|
-
|
16
14
|
namespace duckdb {
|
17
15
|
constexpr uint32_t UNDO_ENTRY_HEADER_SIZE = sizeof(UndoFlags) + sizeof(uint32_t);
|
18
16
|
|
19
|
-
UndoBuffer::UndoBuffer(ClientContext &context_p) :
|
17
|
+
UndoBuffer::UndoBuffer(ClientContext &context_p) : allocator(BufferAllocator::Get(context_p)) {
|
20
18
|
}
|
21
19
|
|
22
20
|
data_ptr_t UndoBuffer::CreateEntry(UndoFlags type, idx_t len) {
|
@@ -138,7 +136,7 @@ void UndoBuffer::Cleanup() {
|
|
138
136
|
|
139
137
|
void UndoBuffer::Commit(UndoBuffer::IteratorState &iterator_state, optional_ptr<WriteAheadLog> log,
|
140
138
|
transaction_t commit_id) {
|
141
|
-
CommitState state(
|
139
|
+
CommitState state(commit_id, log);
|
142
140
|
if (log) {
|
143
141
|
// commit WITH write ahead log
|
144
142
|
IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CommitEntry<true>(type, data); });
|
@@ -149,7 +147,7 @@ void UndoBuffer::Commit(UndoBuffer::IteratorState &iterator_state, optional_ptr<
|
|
149
147
|
}
|
150
148
|
|
151
149
|
void UndoBuffer::RevertCommit(UndoBuffer::IteratorState &end_state, transaction_t transaction_id) {
|
152
|
-
CommitState state(
|
150
|
+
CommitState state(transaction_id, nullptr);
|
153
151
|
UndoBuffer::IteratorState start_state;
|
154
152
|
IterateEntries(start_state, end_state, [&](UndoFlags type, data_ptr_t data) { state.RevertCommit(type, data); });
|
155
153
|
}
|
package/test/prepare.test.ts
CHANGED
@@ -652,7 +652,16 @@ describe('prepare', function() {
|
|
652
652
|
});
|
653
653
|
it("should aggregate kurtosis(num)", function (done) {
|
654
654
|
db.all("SELECT kurtosis(num) as kurtosis FROM foo", function (err: null | Error, res: TableData) {
|
655
|
-
|
655
|
+
// The `num` column of table `foo` contains each integer from 0 to 999,999 exactly once.
|
656
|
+
// This is a uniform distribution. The excess kurtosis for a uniform distribution is exactly -1.2.
|
657
|
+
// See https://en.wikipedia.org/wiki/Kurtosis#Other_well-known_distributions
|
658
|
+
const expected = -1.2;
|
659
|
+
|
660
|
+
// The calculated value can differ from the exact answer by small amounts on different platforms due
|
661
|
+
// to floating-point errors. This tolerance was determined experimentally.
|
662
|
+
const tolerance = Number.EPSILON * 10;
|
663
|
+
|
664
|
+
assert.ok(Math.abs(res[0].kurtosis - expected) < tolerance);
|
656
665
|
done(err);
|
657
666
|
});
|
658
667
|
});
|
@@ -90,7 +90,7 @@ const correct_answer_map: Record<string, any[]> = {
|
|
90
90
|
date_array: [
|
91
91
|
[],
|
92
92
|
[
|
93
|
-
new Date(1970, 0, 1),
|
93
|
+
new Date(Date.UTC(1970, 0, 1)),
|
94
94
|
null,
|
95
95
|
new Date("0001-01-01T00:00:00.000Z"),
|
96
96
|
new Date("9999-12-31T00:00:00.000Z"),
|
@@ -100,7 +100,7 @@ const correct_answer_map: Record<string, any[]> = {
|
|
100
100
|
timestamp_array: [
|
101
101
|
[],
|
102
102
|
[
|
103
|
-
new Date(1970, 0, 1),
|
103
|
+
new Date(Date.UTC(1970, 0, 1)),
|
104
104
|
null,
|
105
105
|
new Date("0001-01-01T00:00:00.000Z"),
|
106
106
|
new Date("9999-12-31T23:59:59.999Z"),
|
@@ -111,7 +111,7 @@ const correct_answer_map: Record<string, any[]> = {
|
|
111
111
|
timestamptz_array: [
|
112
112
|
[],
|
113
113
|
[
|
114
|
-
new Date(1970, 0, 1),
|
114
|
+
new Date(Date.UTC(1970, 0, 1)),
|
115
115
|
null,
|
116
116
|
new Date("0001-01-01T00:00:00.000Z"),
|
117
117
|
new Date("9999-12-31T23:59:59.999Z"),
|
@@ -171,7 +171,7 @@ const correct_answer_map: Record<string, any[]> = {
|
|
171
171
|
],
|
172
172
|
|
173
173
|
timestamp: [
|
174
|
-
new Date(
|
174
|
+
new Date(Date.UTC(1990, 0, 1)),
|
175
175
|
new Date("9999-12-31T23:59:59.000Z"),
|
176
176
|
null,
|
177
177
|
],
|