YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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