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.
Files changed (62) hide show
  1. package/package.json +1 -1
  2. package/src/duckdb/extension/parquet/parquet_extension.cpp +1 -1
  3. package/src/duckdb/src/common/enum_util.cpp +5 -0
  4. package/src/duckdb/src/common/file_buffer.cpp +1 -1
  5. package/src/duckdb/src/common/types/date.cpp +1 -1
  6. package/src/duckdb/src/common/types/validity_mask.cpp +56 -0
  7. package/src/duckdb/src/execution/index/fixed_size_buffer.cpp +3 -10
  8. package/src/duckdb/src/execution/operator/csv_scanner/parallel_csv_reader.cpp +6 -3
  9. package/src/duckdb/src/execution/operator/persistent/physical_batch_insert.cpp +1 -1
  10. package/src/duckdb/src/execution/operator/persistent/physical_insert.cpp +1 -1
  11. package/src/duckdb/src/function/table/arrow_conversion.cpp +9 -1
  12. package/src/duckdb/src/function/table/read_csv.cpp +5 -22
  13. package/src/duckdb/src/function/table/version/pragma_version.cpp +2 -2
  14. package/src/duckdb/src/include/duckdb/common/constants.hpp +0 -15
  15. package/src/duckdb/src/include/duckdb/common/serializer/memory_stream.hpp +1 -1
  16. package/src/duckdb/src/include/duckdb/common/types/validity_mask.hpp +3 -0
  17. package/src/duckdb/src/include/duckdb/function/table/arrow.hpp +3 -0
  18. package/src/duckdb/src/include/duckdb/main/query_result.hpp +1 -1
  19. package/src/duckdb/src/include/duckdb/storage/block.hpp +3 -3
  20. package/src/duckdb/src/include/duckdb/storage/compression/bitpacking.hpp +1 -8
  21. package/src/duckdb/src/include/duckdb/storage/data_pointer.hpp +2 -2
  22. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_manager.hpp +2 -0
  23. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_reader.hpp +2 -0
  24. package/src/duckdb/src/include/duckdb/storage/metadata/metadata_writer.hpp +6 -2
  25. package/src/duckdb/src/include/duckdb/storage/storage_info.hpp +19 -0
  26. package/src/duckdb/src/include/duckdb/storage/table/chunk_info.hpp +19 -13
  27. package/src/duckdb/src/include/duckdb/storage/table/column_data.hpp +1 -1
  28. package/src/duckdb/src/include/duckdb/storage/table/row_group.hpp +15 -15
  29. package/src/duckdb/src/include/duckdb/storage/table/row_version_manager.hpp +59 -0
  30. package/src/duckdb/src/include/duckdb/storage/table/update_segment.hpp +1 -1
  31. package/src/duckdb/src/include/duckdb/transaction/commit_state.hpp +1 -6
  32. package/src/duckdb/src/include/duckdb/transaction/delete_info.hpp +3 -2
  33. package/src/duckdb/src/include/duckdb/transaction/duck_transaction.hpp +4 -2
  34. package/src/duckdb/src/include/duckdb/transaction/local_storage.hpp +1 -1
  35. package/src/duckdb/src/include/duckdb/transaction/undo_buffer.hpp +0 -1
  36. package/src/duckdb/src/main/settings/settings.cpp +5 -10
  37. package/src/duckdb/src/optimizer/statistics/expression/propagate_cast.cpp +14 -0
  38. package/src/duckdb/src/storage/checkpoint/table_data_writer.cpp +0 -1
  39. package/src/duckdb/src/storage/checkpoint_manager.cpp +37 -36
  40. package/src/duckdb/src/storage/compression/bitpacking.cpp +55 -48
  41. package/src/duckdb/src/storage/data_table.cpp +1 -1
  42. package/src/duckdb/src/storage/local_storage.cpp +9 -2
  43. package/src/duckdb/src/storage/metadata/metadata_manager.cpp +41 -2
  44. package/src/duckdb/src/storage/metadata/metadata_reader.cpp +12 -3
  45. package/src/duckdb/src/storage/metadata/metadata_writer.cpp +8 -2
  46. package/src/duckdb/src/storage/single_file_block_manager.cpp +1 -2
  47. package/src/duckdb/src/storage/storage_info.cpp +1 -1
  48. package/src/duckdb/src/storage/table/chunk_info.cpp +39 -33
  49. package/src/duckdb/src/storage/table/column_data.cpp +14 -9
  50. package/src/duckdb/src/storage/table/list_column_data.cpp +2 -2
  51. package/src/duckdb/src/storage/table/row_group.cpp +102 -192
  52. package/src/duckdb/src/storage/table/row_group_collection.cpp +2 -2
  53. package/src/duckdb/src/storage/table/row_version_manager.cpp +228 -0
  54. package/src/duckdb/src/storage/table/update_segment.cpp +2 -2
  55. package/src/duckdb/src/transaction/cleanup_state.cpp +2 -1
  56. package/src/duckdb/src/transaction/commit_state.cpp +5 -4
  57. package/src/duckdb/src/transaction/duck_transaction.cpp +4 -2
  58. package/src/duckdb/src/transaction/rollback_state.cpp +2 -1
  59. package/src/duckdb/src/transaction/undo_buffer.cpp +3 -5
  60. package/src/duckdb/ub_src_storage_table.cpp +2 -0
  61. package/test/prepare.test.ts +10 -1
  62. 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 < RowGroup::ROW_GROUP_VECTOR_COUNT);
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 < RowGroup::ROW_GROUP_VECTOR_COUNT);
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.vinfo->start + info.rows[i];
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(ClientContext &context, transaction_t commit_id, optional_ptr<WriteAheadLog> log)
25
- : log(log), commit_id(commit_id), current_table_info(nullptr), context(context) {
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->vinfo->CommitDelete(commit_id, info->rows, info->count);
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->vinfo->CommitDelete(transaction_id, info->rows, info->count);
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, ChunkVectorInfo *vinfo, row_t rows[], idx_t count, idx_t base_row) {
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->vinfo = vinfo;
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->vinfo->CommitDelete(NOT_DELETED_ID, info->rows, info->count);
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) : context(context_p), allocator(BufferAllocator::Get(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(context, commit_id, log);
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(context, transaction_id, nullptr);
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
  }
@@ -18,6 +18,8 @@
18
18
 
19
19
  #include "src/storage/table/row_group_collection.cpp"
20
20
 
21
+ #include "src/storage/table/row_version_manager.cpp"
22
+
21
23
  #include "src/storage/table/scan_state.cpp"
22
24
 
23
25
  #include "src/storage/table/standard_column_data.cpp"
@@ -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
- assert.equal(res[0].kurtosis, -1.1999999999999997);
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("1990-01-01T00:00"),
174
+ new Date(Date.UTC(1990, 0, 1)),
175
175
  new Date("9999-12-31T23:59:59.000Z"),
176
176
  null,
177
177
  ],