1#include "duckdb/transaction/cleanup_state.hpp"
2#include "duckdb/transaction/delete_info.hpp"
3#include "duckdb/transaction/update_info.hpp"
4
5#include "duckdb/storage/data_table.hpp"
6
7#include "duckdb/catalog/catalog.hpp"
8#include "duckdb/catalog/dependency_manager.hpp"
9#include "duckdb/storage/table/chunk_info.hpp"
10#include "duckdb/storage/table/update_segment.hpp"
11
12namespace duckdb {
13
14CleanupState::CleanupState() : current_table(nullptr), count(0) {
15}
16
17CleanupState::~CleanupState() {
18 Flush();
19}
20
21void CleanupState::CleanupEntry(UndoFlags type, data_ptr_t data) {
22 switch (type) {
23 case UndoFlags::CATALOG_ENTRY: {
24 auto catalog_entry = Load<CatalogEntry *>(ptr: data);
25 D_ASSERT(catalog_entry);
26 D_ASSERT(catalog_entry->set);
27 catalog_entry->set->CleanupEntry(catalog_entry&: *catalog_entry);
28 break;
29 }
30 case UndoFlags::DELETE_TUPLE: {
31 auto info = reinterpret_cast<DeleteInfo *>(data);
32 CleanupDelete(info&: *info);
33 break;
34 }
35 case UndoFlags::UPDATE_TUPLE: {
36 auto info = reinterpret_cast<UpdateInfo *>(data);
37 CleanupUpdate(info&: *info);
38 break;
39 }
40 default:
41 break;
42 }
43}
44
45void CleanupState::CleanupUpdate(UpdateInfo &info) {
46 // remove the update info from the update chain
47 // first obtain an exclusive lock on the segment
48 info.segment->CleanupUpdate(info);
49}
50
51void CleanupState::CleanupDelete(DeleteInfo &info) {
52 auto version_table = info.table;
53 D_ASSERT(version_table->info->cardinality >= info.count);
54 version_table->info->cardinality -= info.count;
55
56 if (version_table->info->indexes.Empty()) {
57 // this table has no indexes: no cleanup to be done
58 return;
59 }
60
61 if (current_table != version_table) {
62 // table for this entry differs from previous table: flush and switch to the new table
63 Flush();
64 current_table = version_table;
65 }
66
67 // possibly vacuum any indexes in this table later
68 indexed_tables[current_table->info->table] = current_table;
69
70 count = 0;
71 for (idx_t i = 0; i < info.count; i++) {
72 row_numbers[count++] = info.vinfo->start + info.rows[i];
73 }
74 Flush();
75}
76
77void CleanupState::Flush() {
78 if (count == 0) {
79 return;
80 }
81
82 // set up the row identifiers vector
83 Vector row_identifiers(LogicalType::ROW_TYPE, data_ptr_cast(src: row_numbers));
84
85 // delete the tuples from all the indexes
86 try {
87 current_table->RemoveFromIndexes(row_identifiers, count);
88 } catch (...) {
89 }
90
91 count = 0;
92}
93
94} // namespace duckdb
95