13
13
#include " executor/alter_executor.h"
14
14
15
15
#include " catalog/catalog.h"
16
+ #include " catalog/table_catalog.h"
16
17
#include " common/logger.h"
17
18
#include " executor/executor_context.h"
19
+ #include " storage/data_table.h"
18
20
19
21
namespace peloton {
20
22
namespace executor {
21
23
22
24
// Constructor for alter table executor
23
25
AlterExecutor::AlterExecutor (const planner::AbstractPlan *node,
24
26
ExecutorContext *executor_context)
25
- : AbstractExecutor(node, executor_context),
26
- isAlter_ (
27
- !reinterpret_cast <const planner::AlterPlan *>(node)->IsRename()) {}
27
+ : AbstractExecutor(node, executor_context) {}
28
28
29
29
// Initialize executor
30
30
// Nothing to initialize for now
@@ -38,24 +38,20 @@ bool AlterExecutor::DInit() {
38
38
bool AlterExecutor::DExecute () {
39
39
LOG_TRACE (" Executing Alter..." );
40
40
bool result = false ;
41
- if (!isAlter_) {
42
- const planner::AlterPlan &node = GetPlanNode<planner::AlterPlan>();
43
- auto current_txn = executor_context_->GetTransaction ();
44
- result = RenameColumn (node, current_txn);
45
- } else {
46
- const planner::AlterPlan &node = GetPlanNode<planner::AlterPlan>();
47
- auto current_txn = executor_context_->GetTransaction ();
48
- AlterType type = node.GetAlterTableType ();
49
- switch (type) {
50
- case AlterType::ALTER:
51
- result = DropColumn (node, current_txn);
52
- break ;
53
- default :
54
- throw NotImplementedException (StringUtil::Format (
55
- " Alter Type not supported, %s" , AlterTypeToString (type).c_str ()));
56
- }
41
+ const planner::AlterPlan &node = GetPlanNode<planner::AlterPlan>();
42
+ auto current_txn = executor_context_->GetTransaction ();
43
+ AlterType type = node.GetAlterTableType ();
44
+ switch (type) {
45
+ case AlterType::RENAME:
46
+ result = RenameColumn (node, current_txn);
47
+ break ;
48
+ case AlterType::ALTER:
49
+ result = AlterTable (node, current_txn);
50
+ break ;
51
+ default :
52
+ throw NotImplementedException (StringUtil::Format (
53
+ " Alter Type not supported, %s" , AlterTypeToString (type).c_str ()));
57
54
}
58
-
59
55
return result;
60
56
}
61
57
@@ -82,23 +78,109 @@ bool AlterExecutor::RenameColumn(
82
78
return false ;
83
79
}
84
80
85
- bool AlterExecutor::DropColumn (const peloton::planner::AlterPlan &node,
81
+ bool AlterExecutor::AlterTable (const peloton::planner::AlterPlan &node,
86
82
peloton::concurrency::TransactionContext *txn) {
87
83
auto database_name = node.GetDatabaseName ();
88
84
auto table_name = node.GetTableName ();
89
- auto drop_columns = node.GetDroppedColumns ();
90
85
91
- ResultType result = catalog::Catalog::GetInstance ()->DropColumn (
92
- database_name, table_name, drop_columns, txn);
93
- txn->SetResult (result);
86
+ auto table_catalog_obj = catalog::Catalog::GetInstance ()->GetTableObject (
87
+ database_name, table_name, txn);
88
+ oid_t database_oid = table_catalog_obj->GetDatabaseOid ();
89
+ oid_t table_oid = table_catalog_obj->GetTableOid ();
90
+
91
+ auto old_table = catalog::Catalog::GetInstance ()->GetTableWithName (
92
+ database_name, table_name, txn);
93
+ auto old_schema = old_table->GetSchema ();
94
+ std::vector<oid_t > column_ids;
95
+
96
+ // Step 1: remove drop columns from old schema
97
+ for (oid_t i = 0 ; i < old_schema->GetColumnCount (); ++i) {
98
+ bool is_found = false ;
99
+ for (auto drop_column : node.GetDroppedColumns ()) {
100
+ if (old_schema->GetColumn (i).GetName () == drop_column) {
101
+ is_found = true ;
102
+ }
103
+ }
104
+ if (!is_found) {
105
+ column_ids.push_back (i);
106
+ }
107
+ }
108
+ // Check if dropped column exists
109
+ if (column_ids.size () + node.GetDroppedColumns ().size () !=
110
+ old_schema->GetColumnCount ()) {
111
+ LOG_TRACE (" Dropped column not exists" );
112
+ txn->SetResult (ResultType::FAILURE);
113
+ return false ;
114
+ }
115
+ std::unique_ptr<catalog::Schema> temp_schema (
116
+ catalog::Schema::CopySchema (old_schema, column_ids));
117
+
118
+ // Step 2: change column type if exists
119
+ for (auto change_pair : node.GetChangedTypeColumns ()) {
120
+ bool is_found = false ;
121
+ oid_t i = 0 ;
122
+ for (; i < temp_schema->GetColumnCount (); ++i) {
123
+ if (temp_schema->GetColumn (i).GetName () == change_pair.first ) {
124
+ is_found = true ;
125
+ break ;
126
+ }
127
+ }
128
+ if (!is_found) {
129
+ LOG_TRACE (" Change column type failed: Column %s does not exists" ,
130
+ change_pair.first .c_str ());
131
+ txn->SetResult (ResultType::FAILURE);
132
+ return false ;
133
+ } else {
134
+ temp_schema->ChangeColumnType (i, change_pair.second );
135
+ }
136
+ }
94
137
95
- if (txn->GetResult () == ResultType::SUCCESS) {
96
- LOG_TRACE (" Drop column succeed!" );
138
+ // Step 3: append add column to new schema
139
+ // construct add column schema
140
+ std::vector<catalog::Column> add_columns;
141
+ for (size_t i = 0 ; i < node.GetAddedColumns ().size (); ++i) {
142
+ for (auto column : node.GetAddedColumns ()[i]->GetColumns ()) {
143
+ add_columns.push_back (column);
144
+ }
145
+ }
146
+ std::unique_ptr<catalog::Schema> add_column_schema (
147
+ new catalog::Schema (add_columns));
148
+ // Check if added column exists
149
+ for (auto new_column : add_column_schema->GetColumns ()) {
150
+ for (auto old_column : old_schema->GetColumns ()) {
151
+ if (new_column.GetName () == old_column.GetName ()) {
152
+ LOG_TRACE (" Add column failed: Column %s already exists" ,
153
+ new_column.GetName ().c_str ());
154
+ txn->SetResult (ResultType::FAILURE);
155
+ return false ;
156
+ }
157
+ }
158
+ }
97
159
98
- // TODO: Add on succeed logic if necessary
99
- executor_context_->num_processed = 1 ;
100
- } else {
101
- LOG_TRACE (" Result is: %s" , ResultTypeToString (txn->GetResult ()).c_str ());
160
+ // Construct new schema
161
+ std::unique_ptr<catalog::Schema> new_schema (catalog::Schema::AppendSchema (
162
+ temp_schema.get (), add_column_schema.get ()));
163
+
164
+ // Copy and replace table content to new schema in catalog
165
+ ResultType result = catalog::Catalog::GetInstance ()->AlterTable (
166
+ database_oid, table_oid, new_schema, txn);
167
+ txn->SetResult (result);
168
+
169
+ switch (txn->GetResult ()) {
170
+ case ResultType::SUCCESS:
171
+ LOG_TRACE (" Alter table succeed!" );
172
+
173
+ // TODO: Add on succeed logic if necessary
174
+ executor_context_->num_processed = 1 ;
175
+ break ;
176
+ case ResultType::FAILURE:
177
+ LOG_TRACE (" Alter table failed!" );
178
+
179
+ // TODO: Add on failed logic if necessary
180
+ break ;
181
+ default :
182
+ LOG_TRACE (" Result is: %s" , ResultTypeToString (txn->GetResult ()).c_str ());
183
+ break ;
102
184
}
103
185
return false ;
104
186
}
0 commit comments