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#include "duckdb/storage/uncompressed_segment.hpp"
7
8#include "duckdb/catalog/catalog.hpp"
9#include "duckdb/catalog/dependency_manager.hpp"
10
11using namespace duckdb;
12using namespace std;
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 CatalogEntry *catalog_entry = *((CatalogEntry **)data);
25 // destroy the backed up entry: it is no longer required
26 assert(catalog_entry->parent);
27 if (catalog_entry->parent->type != CatalogType::UPDATED_ENTRY) {
28 if (!catalog_entry->parent->child->deleted) {
29 // delete the entry from the dependency manager, if it is not deleted yet
30 catalog_entry->catalog->dependency_manager.EraseObject(catalog_entry->parent->child.get());
31 }
32 catalog_entry->parent->child = move(catalog_entry->child);
33 }
34 break;
35 }
36 case UndoFlags::DELETE_TUPLE: {
37 auto info = (DeleteInfo *)data;
38 CleanupDelete(info);
39 break;
40 }
41 case UndoFlags::UPDATE_TUPLE: {
42 auto info = (UpdateInfo *)data;
43 CleanupUpdate(info);
44 break;
45 }
46 default:
47 break;
48 }
49}
50
51void CleanupState::CleanupUpdate(UpdateInfo *info) {
52 // remove the update info from the update chain
53 // first obtain an exclusive lock on the segment
54 auto lock = info->segment->lock.GetExclusiveLock();
55 info->segment->CleanupUpdate(info);
56}
57
58void CleanupState::CleanupDelete(DeleteInfo *info) {
59 auto version_table = info->table;
60 if (version_table->info->indexes.size() == 0) {
61 // this table has no indexes: no cleanup to be done
62 return;
63 }
64 if (current_table != version_table) {
65 // table for this entry differs from previous table: flush and switch to the new table
66 Flush();
67 current_table = version_table;
68 }
69 for (idx_t i = 0; i < info->count; i++) {
70 if (count == STANDARD_VECTOR_SIZE) {
71 Flush();
72 }
73 row_numbers[count++] = info->vinfo->start + info->rows[i];
74 }
75}
76
77void CleanupState::Flush() {
78 if (count == 0) {
79 return;
80 }
81
82 // set up the row identifiers vector
83 Vector row_identifiers(ROW_TYPE, (data_ptr_t)row_numbers);
84
85 // delete the tuples from all the indexes
86 current_table->RemoveFromIndexes(row_identifiers, count);
87
88 count = 0;
89}
90