/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/ptree/pt_alter_table.cc
Line | Count | Source (jump to first uncovered line) |
1 | | //-------------------------------------------------------------------------------------------------- |
2 | | // Copyright (c) YugaByte, Inc. |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
5 | | // in compliance with the License. You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
10 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
11 | | // or implied. See the License for the specific language governing permissions and limitations |
12 | | // under the License. |
13 | | // |
14 | | // |
15 | | // Treenode definitions for ALTER TABLE statements. |
16 | | //-------------------------------------------------------------------------------------------------- |
17 | | |
18 | | #include "yb/yql/cql/ql/ptree/pt_alter_table.h" |
19 | | |
20 | | #include "yb/client/table.h" |
21 | | |
22 | | #include "yb/common/index.h" |
23 | | #include "yb/common/schema.h" |
24 | | |
25 | | #include "yb/util/logging.h" |
26 | | |
27 | | #include "yb/yql/cql/ql/ptree/column_desc.h" |
28 | | #include "yb/yql/cql/ql/ptree/pt_option.h" |
29 | | #include "yb/yql/cql/ql/ptree/sem_context.h" |
30 | | #include "yb/yql/cql/ql/ptree/yb_location.h" |
31 | | |
32 | | namespace yb { |
33 | | namespace ql { |
34 | | |
35 | | //-------------------------------------------------------------------------------------------------- |
36 | | |
37 | | PTAlterTable::PTAlterTable(MemoryContext *memctx, |
38 | | YBLocationPtr loc, |
39 | | PTQualifiedName::SharedPtr name, |
40 | | const PTListNode::SharedPtr &commands) |
41 | | : TreeNode(memctx, loc), |
42 | | name_(name), |
43 | | commands_(commands), |
44 | | table_columns_(memctx), |
45 | | mod_columns_(memctx), |
46 | 71 | mod_props_(memctx) { |
47 | 71 | } |
48 | | |
49 | 62 | PTAlterTable::~PTAlterTable() { |
50 | 62 | } |
51 | | |
52 | 71 | CHECKED_STATUS PTAlterTable::Analyze(SemContext *sem_context) { |
53 | | // Populate internal table_ variable. |
54 | 71 | bool is_system_ignored = false; |
55 | 71 | RETURN_NOT_OK(name_->AnalyzeName(sem_context, ObjectType::TABLE)); |
56 | | |
57 | | // Permissions check happen in LookupTable if flag use_cassandra_authentication is enabled. |
58 | 71 | RETURN_NOT_OK(sem_context->LookupTable(name_->ToTableName(), name_->loc(), true /* write_table */, |
59 | 71 | PermissionType::ALTER_PERMISSION, |
60 | 71 | &table_, &is_system_ignored, &table_columns_)); |
61 | | |
62 | | // Save context state, and set "this" as current table being altered. |
63 | 71 | SymbolEntry cached_entry = *sem_context->current_processing_id(); |
64 | 71 | sem_context->set_current_alter_table(this); |
65 | | |
66 | | // Process alter commands. |
67 | 71 | RETURN_NOT_OK(commands_->Analyze(sem_context)); |
68 | | |
69 | | // Restore saved context state. |
70 | 63 | sem_context->set_current_processing_id(cached_entry); |
71 | | |
72 | 63 | if (VLOG_IS_ON(3)) { |
73 | 0 | PrintSemanticAnalysisResult(sem_context); |
74 | 0 | } |
75 | 63 | return Status::OK(); |
76 | 71 | } |
77 | | |
78 | 0 | void PTAlterTable::PrintSemanticAnalysisResult(SemContext *sem_context) { |
79 | 0 | MCString sem_output("\tAltering Table ", sem_context->PTempMem()); |
80 | 0 | sem_output += yb_table_name().ToString().c_str(); |
81 | 0 | sem_output += "("; |
82 | | // TODO: Add debugging info for what this alter command is. |
83 | 0 | sem_output += ")"; |
84 | 0 | VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << sem_output; |
85 | 0 | } |
86 | | |
87 | | CHECKED_STATUS PTAlterTable::AppendModColumn(SemContext *sem_context, |
88 | 71 | PTAlterColumnDefinition *column) { |
89 | | // Make sure column already exists and isn't key column. |
90 | 71 | if (column->old_name() != nullptr) { |
91 | 28 | const ColumnDesc* desc = sem_context->GetColumnDesc(column->old_name()->last_name()); |
92 | 28 | if (desc == nullptr) { |
93 | 2 | return sem_context->Error(this, "Column doesn't exist", ErrorCode::UNDEFINED_COLUMN); |
94 | 2 | } |
95 | | |
96 | 26 | if (desc->is_hash() && column->mod_type() != ALTER_RENAME1 ) { |
97 | 0 | return sem_context->Error(this, "Can't alter key column", ErrorCode::ALTER_KEY_COLUMN); |
98 | 0 | } |
99 | | |
100 | 26 | if (column->mod_type() == ALTER_DROP) { |
101 | | // Check column dependencies. |
102 | 12 | const ColumnId column_id(desc->id()); |
103 | 12 | for (const auto& index_item : table_->index_map()) { |
104 | 6 | const auto& index = index_item.second; |
105 | | // Check if this "index" is dependent on the column being dropped. |
106 | 6 | if (index.CheckColumnDependency(column_id)) { |
107 | 4 | auto index_table = sem_context->GetTableDesc(index.table_id()); |
108 | 4 | return sem_context->Error(this, |
109 | 4 | Format("Can't drop column used in an index. Remove '$0' index first and try again", |
110 | 4 | (index_table ? index_table->name().table_name() : "-unknown-"0 )), |
111 | 4 | ErrorCode::FEATURE_NOT_YET_IMPLEMENTED); |
112 | 4 | } |
113 | 6 | } |
114 | 12 | } |
115 | 26 | } |
116 | | |
117 | | // Make sure column already doesn't exist with the same name. |
118 | 65 | if (column->new_name() != nullptr) { |
119 | 57 | MCString name = *column->new_name(); |
120 | 57 | const ColumnDesc* desc = sem_context->GetColumnDesc(name); |
121 | 57 | if (desc != nullptr) { |
122 | | // Expecting the error message matching to the reg-exp: "[Ii]nvalid column name" |
123 | | // for the error correct handling in tools (like Kong). |
124 | 1 | return sem_context->Error(this, |
125 | 1 | Format("Invalid column name because it conflicts with the existing column: $0", |
126 | 1 | name.c_str()), |
127 | 1 | ErrorCode::DUPLICATE_COLUMN); |
128 | 1 | } |
129 | 57 | } |
130 | | |
131 | 64 | mod_columns_.push_back(column); |
132 | 64 | return Status::OK(); |
133 | 65 | } |
134 | | |
135 | 7 | CHECKED_STATUS PTAlterTable::AppendAlterProperty(SemContext *sem_context, PTTableProperty *prop) { |
136 | 7 | mod_props_.push_back(prop); |
137 | 7 | return Status::OK(); |
138 | 7 | } |
139 | | |
140 | 7 | CHECKED_STATUS PTAlterTable::ToTableProperties(TableProperties *table_properties) const { |
141 | 7 | DCHECK_ONLY_NOTNULL(table_.get()); |
142 | | // Init by values from the current table properties. |
143 | 7 | *DCHECK_NOTNULL(table_properties) = table_->schema().table_properties(); |
144 | 7 | for (const auto& table_property : mod_props_) { |
145 | 7 | RETURN_NOT_OK(table_property->SetTableProperty(table_properties)); |
146 | 7 | } |
147 | | |
148 | 7 | return Status::OK(); |
149 | 7 | } |
150 | | |
151 | | //-------------------------------------------------------------------------------------------------- |
152 | | |
153 | | PTAlterColumnDefinition::PTAlterColumnDefinition(MemoryContext *memctx, |
154 | | YBLocation::SharedPtr loc, |
155 | | PTQualifiedName::SharedPtr name, |
156 | | const MCSharedPtr<MCString>& new_name, |
157 | | const PTBaseType::SharedPtr& datatype, |
158 | | AlterColumnType type) |
159 | | : TreeNode(memctx, loc), |
160 | | name_(name), |
161 | | new_name_(new_name), |
162 | | datatype_(datatype), |
163 | 71 | type_(type) { |
164 | 71 | } |
165 | | |
166 | 62 | PTAlterColumnDefinition::~PTAlterColumnDefinition() { |
167 | 62 | } |
168 | | |
169 | 71 | CHECKED_STATUS PTAlterColumnDefinition::Analyze(SemContext *sem_context) { |
170 | 71 | if (name_ != nullptr) { |
171 | 28 | RETURN_NOT_OK(name_->Analyze(sem_context)); |
172 | 28 | } |
173 | | |
174 | 71 | if (new_name_ != nullptr) { |
175 | 57 | RETURN_NOT_OK(sem_context->MapSymbol(*new_name_, this)); |
176 | 57 | } |
177 | | |
178 | 71 | if (datatype_ != nullptr) { |
179 | 43 | RETURN_NOT_OK(datatype_->Analyze(sem_context)); |
180 | 43 | } |
181 | | |
182 | 71 | PTAlterTable *table = sem_context->current_alter_table(); |
183 | 71 | RETURN_NOT_OK(table->AppendModColumn(sem_context, this)); |
184 | | |
185 | 64 | return Status::OK(); |
186 | 71 | } |
187 | | |
188 | | } // namespace ql |
189 | | } // namespace yb |