YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/yql/cql/ql/ptree/sem_context.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
#include "yb/yql/cql/ql/ptree/sem_context.h"
16
17
#include "yb/client/schema.h"
18
#include "yb/client/table.h"
19
#include "yb/common/roles_permissions.h"
20
#include "yb/common/schema.h"
21
#include "yb/util/flag_tags.h"
22
#include "yb/util/status_format.h"
23
#include "yb/util/status_log.h"
24
#include "yb/yql/cql/ql/ptree/column_desc.h"
25
#include "yb/yql/cql/ql/ptree/parse_tree.h"
26
#include "yb/yql/cql/ql/ptree/pt_alter_table.h"
27
#include "yb/yql/cql/ql/ptree/pt_column_definition.h"
28
#include "yb/yql/cql/ql/ptree/pt_create_index.h"
29
#include "yb/yql/cql/ql/ptree/pt_create_type.h"
30
#include "yb/yql/cql/ql/ptree/pt_dml.h"
31
#include "yb/yql/cql/ql/ptree/sem_state.h"
32
#include "yb/yql/cql/ql/util/errcodes.h"
33
#include "yb/yql/cql/ql/util/ql_env.h"
34
35
DECLARE_bool(use_cassandra_authentication);
36
37
DEFINE_bool(allow_index_table_read_write, false, "Allow direct read and write of index tables");
38
TAG_FLAG(allow_index_table_read_write, hidden);
39
40
namespace yb {
41
namespace ql {
42
43
using std::shared_ptr;
44
using client::YBTable;
45
using client::YBTableName;
46
using client::YBColumnSchema;
47
using client::YBSchema;
48
49
//--------------------------------------------------------------------------------------------------
50
51
SemContext::SemContext(ParseTreePtr parse_tree, QLEnv *ql_env)
52
    : ProcessContext(std::move(parse_tree)),
53
      symtab_(PTempMem()),
54
330k
      ql_env_(ql_env) {
55
330k
}
56
57
336k
SemContext::~SemContext() {
58
336k
}
59
60
//--------------------------------------------------------------------------------------------------
61
62
3.72M
MemoryContext *SemContext::PSemMem() const {
63
3.72M
  return parse_tree_->PSemMem();
64
3.72M
}
65
66
0
PTCreateIndex *SemContext::current_create_index_stmt() {
67
0
  PTCreateTable* const table = current_create_table_stmt();
68
0
  return (table != nullptr && table->opcode() == TreeNodeOpcode::kPTCreateIndex)
69
0
      ? static_cast<PTCreateIndex*>(table) : nullptr;
70
0
}
71
72
0
void SemContext::set_current_create_index_stmt(PTCreateIndex *index) {
73
0
  set_current_create_table_stmt(index);
74
0
}
75
76
59.2k
std::string SemContext::CurrentKeyspace() const {
77
59.2k
  return ql_env_->CurrentKeyspace();
78
59.2k
}
79
80
737
std::string SemContext::CurrentRoleName() const {
81
737
  return ql_env_->CurrentRoleName();
82
737
}
83
84
Status SemContext::LoadSchema(const shared_ptr<YBTable>& table,
85
3.59k
                              MCVector<ColumnDesc>* col_descs) {
86
3.59k
  const YBSchema& schema = table->schema();
87
3.59k
  const auto num_columns = schema.num_columns();
88
3.59k
  const auto num_key_columns = schema.num_key_columns();
89
3.59k
  const auto num_hash_key_columns = schema.num_hash_key_columns();
90
91
3.59k
  if (col_descs != nullptr) {
92
572
    col_descs->reserve(num_columns);
93
3.25k
    for (size_t idx = 0; idx < num_columns; idx++) {
94
      // Find the column descriptor.
95
2.68k
      const YBColumnSchema col = schema.Column(idx);
96
2.68k
      col_descs->emplace_back(idx,
97
2.68k
                              schema.ColumnId(idx),
98
2.68k
                              col.name(),
99
2.68k
                              idx < num_hash_key_columns,
100
2.68k
                              idx < num_key_columns,
101
2.68k
                              col.is_static(),
102
2.68k
                              col.is_counter(),
103
2.68k
                              col.type(),
104
2.68k
                              YBColumnSchema::ToInternalDataType(col.type()),
105
2.68k
                              schema.table_properties().use_mangled_column_name());
106
107
      // Insert the column descriptor, and column definition if requested, to symbol table.
108
2.68k
      MCSharedPtr<MCString> col_name = MCMakeShared<MCString>(PSemMem(), col.name().c_str());
109
2.68k
      RETURN_NOT_OK(MapSymbol(*col_name, &(*col_descs)[idx]));
110
2.68k
    }
111
572
  }
112
113
3.59k
  return Status::OK();
114
3.59k
}
115
116
Status SemContext::LookupTable(const YBTableName& name,
117
                               const YBLocation& loc,
118
                               const bool write_table,
119
                               const PermissionType permission,
120
                               shared_ptr<YBTable>* table,
121
                               bool* is_system,
122
3.62k
                               MCVector<ColumnDesc>* col_descs) {
123
3.62k
  if (FLAGS_use_cassandra_authentication) {
124
58
    RETURN_NOT_OK(CheckHasTablePermission(loc, permission, name.namespace_name(),
125
58
                                          name.table_name()));
126
58
  }
127
3.60k
  *is_system = name.is_system();
128
3.60k
  if (*is_system && write_table && client::FLAGS_yb_system_namespace_readonly) {
129
0
    return Error(loc, ErrorCode::SYSTEM_NAMESPACE_READONLY);
130
0
  }
131
132
0
  VLOG(3) << "Loading table descriptor for " << name.ToString();
133
3.60k
  *table = GetTableDesc(name);
134
3.60k
  if (*table == nullptr || ((*table)->IsIndex() && !FLAGS_allow_index_table_read_write) ||
135
      // Only looking for CQL tables.
136
3.59k
      (*table)->table_type() != client::YBTableType::YQL_TABLE_TYPE) {
137
3
    return Error(loc, ErrorCode::OBJECT_NOT_FOUND);
138
3
  }
139
140
3.59k
  return LoadSchema(*table, col_descs);
141
3.59k
}
142
143
6.80k
Status SemContext::MapSymbol(const MCString& name, PTColumnDefinition *entry) {
144
6.80k
  if (symtab_[name].column_ != nullptr) {
145
0
    return Error(entry, ErrorCode::DUPLICATE_COLUMN);
146
0
  }
147
6.80k
  symtab_[name].column_ = entry;
148
6.80k
  return Status::OK();
149
6.80k
}
150
151
56
Status SemContext::MapSymbol(const MCString& name, PTAlterColumnDefinition *entry) {
152
56
  if (symtab_[name].alter_column_ != nullptr) {
153
0
    return Error(entry, ErrorCode::DUPLICATE_COLUMN);
154
0
  }
155
56
  symtab_[name].alter_column_ = entry;
156
56
  return Status::OK();
157
56
}
158
159
0
Status SemContext::MapSymbol(const MCString& name, PTCreateTable *entry) {
160
0
  if (symtab_[name].create_table_ != nullptr) {
161
0
    return Error(entry, ErrorCode::DUPLICATE_OBJECT);
162
0
  }
163
0
  symtab_[name].create_table_ = entry;
164
0
  return Status::OK();
165
0
}
166
167
2.68k
Status SemContext::MapSymbol(const MCString& name, ColumnDesc *entry) {
168
2.68k
  if (symtab_[name].column_desc_ != nullptr) {
169
0
    LOG(FATAL) << "Entries of the same symbol are inserted"
170
0
               << ", Existing entry = " << symtab_[name].column_desc_
171
0
               << ", New entry = " << entry;
172
0
  }
173
2.68k
  symtab_[name].column_desc_ = entry;
174
2.68k
  return Status::OK();
175
2.68k
}
176
177
126
Status SemContext::MapSymbol(const MCString& name, PTTypeField *entry) {
178
126
  if (symtab_[name].type_field_ != nullptr) {
179
2
    return Error(entry, ErrorCode::DUPLICATE_TYPE_FIELD);
180
2
  }
181
124
  symtab_[name].type_field_ = entry;
182
124
  return Status::OK();
183
124
}
184
185
321k
shared_ptr<YBTable> SemContext::GetTableDesc(const client::YBTableName& table_name) {
186
321k
  bool cache_used = false;
187
321k
  shared_ptr<YBTable> table = ql_env_->GetTableDesc(table_name, &cache_used);
188
322k
  if (table != nullptr) {
189
322k
    parse_tree_->AddAnalyzedTable(table_name);
190
322k
    if (cache_used) {
191
      // Remember cache was used.
192
278k
      cache_used_ = true;
193
278k
    }
194
322k
  }
195
321k
  return table;
196
321k
}
197
198
1.41k
shared_ptr<YBTable> SemContext::GetTableDesc(const TableId& table_id) {
199
1.41k
  bool cache_used = false;
200
1.41k
  shared_ptr<YBTable> table = ql_env_->GetTableDesc(table_id, &cache_used);
201
1.41k
  if (table != nullptr) {
202
1.41k
    parse_tree_->AddAnalyzedTable(table->name());
203
1.41k
    if (cache_used) {
204
      // Remember cache was used.
205
1.04k
      cache_used_ = true;
206
1.04k
    }
207
1.41k
  }
208
1.41k
  return table;
209
1.41k
}
210
211
std::shared_ptr<QLType> SemContext::GetUDType(const string &keyspace_name,
212
81
                                              const string &type_name) {
213
81
  bool cache_used = false;
214
81
  shared_ptr<QLType> type = ql_env_->GetUDType(keyspace_name, type_name, &cache_used);
215
216
81
  if (type != nullptr) {
217
74
    parse_tree_->AddAnalyzedUDType(keyspace_name, type_name);
218
74
    if (cache_used) {
219
      // Remember cache was used.
220
26
      cache_used_ = true;
221
26
    }
222
74
  }
223
224
81
  return type;
225
81
}
226
227
11.0k
const SymbolEntry *SemContext::SeekSymbol(const MCString& name) const {
228
11.0k
  MCMap<MCString, SymbolEntry>::const_iterator iter = symtab_.find(name);
229
11.0k
  if (iter != symtab_.end()) {
230
11.0k
    return &iter->second;
231
11.0k
  }
232
31
  return nullptr;
233
31
}
234
235
6.09k
PTColumnDefinition *SemContext::GetColumnDefinition(const MCString& col_name) {
236
6.09k
  const SymbolEntry * entry = SeekSymbol(col_name);
237
6.09k
  if (entry == nullptr) {
238
29
    return nullptr;
239
29
  }
240
6.06k
  return entry->column_;
241
6.06k
}
242
243
5.00k
const ColumnDesc *SemContext::GetColumnDesc(const MCString& col_name) const {
244
5.00k
  const SymbolEntry * entry = SeekSymbol(col_name);
245
5.00k
  if (entry == nullptr) {
246
2
    return nullptr;
247
2
  }
248
249
5.00k
  PTDmlStmt *dml_stmt = current_dml_stmt();
250
5.00k
  if (dml_stmt != nullptr) {
251
    // To indicate that DocDB must read a columm value to execute an expression, the column is added
252
    // to the column_refs list.
253
0
    bool reading_column = false;
254
255
0
    switch (dml_stmt->opcode()) {
256
0
      case TreeNodeOpcode::kPTSelectStmt:
257
0
        reading_column = true;
258
0
        break;
259
0
      case TreeNodeOpcode::kPTUpdateStmt:
260
0
        if (sem_state() != nullptr && processing_set_clause() && !processing_assignee()) {
261
0
          reading_column = true;
262
0
          break;
263
0
        }
264
0
        FALLTHROUGH_INTENDED;
265
0
      case TreeNodeOpcode::kPTInsertStmt:
266
0
      case TreeNodeOpcode::kPTDeleteStmt:
267
0
        if (sem_state() != nullptr && processing_if_clause()) {
268
0
          reading_column = true;
269
0
          break;
270
0
        }
271
0
        break;
272
0
      default:
273
0
        break;
274
0
    }
275
276
0
    if (reading_column) {
277
      // TODO(neil) Currently AddColumnRef() relies on MCSet datatype to guarantee that we have a
278
      // unique list of IDs, but we should take advantage to "symbol table" when collecting data
279
      // for execution. Symbol table and "column_read_count_" need to be corrected so that we can
280
      // use MCList instead.
281
282
      // Indicate that this column must be read for the statement execution.
283
0
      dml_stmt->AddColumnRef(*entry->column_desc_);
284
0
    }
285
0
  }
286
287
  // Setup the column to which the INDEX column is referencing.
288
5.00k
  if (sem_state_ && sem_state_->is_processing_index_column()) {
289
1.90k
    sem_state_->add_index_column_ref(entry->column_desc_->id());
290
1.90k
  }
291
292
5.00k
  if (sem_state_ && sem_state_->idx_predicate_state()) {
293
    // We are in CREATE INDEX path of a partial index. Save column ids referenced in the predicate.
294
180
    sem_state_->idx_predicate_state()->column_refs()->insert(entry->column_desc_->id());
295
180
  }
296
297
5.00k
  return entry->column_desc_;
298
5.00k
}
299
300
Status SemContext::HasKeyspacePermission(PermissionType permission,
301
1.47k
                                         const NamespaceName& keyspace_name) {
302
303
1.47k
  DFATAL_OR_RETURN_ERROR_IF(keyspace_name.empty(),
304
1.47k
                            STATUS(InvalidArgument, "Invalid empty keyspace"));
305
1.47k
  return ql_env_->HasResourcePermission(get_canonical_keyspace(keyspace_name),
306
1.47k
                                        ObjectType::SCHEMA, permission, keyspace_name);
307
1.47k
}
308
309
Status SemContext::CheckHasKeyspacePermission(const YBLocation& loc,
310
                                              const PermissionType permission,
311
1.47k
                                              const NamespaceName& keyspace_name) {
312
1.47k
  auto s = HasKeyspacePermission(permission, keyspace_name);
313
1.47k
  if (!s.ok()) {
314
37
    return Error(loc, s.message().ToBuffer().c_str(), ErrorCode::UNAUTHORIZED);
315
37
  }
316
1.43k
  return Status::OK();
317
1.43k
}
318
319
Status SemContext::CheckHasTablePermission(const YBLocation &loc,
320
                                           PermissionType permission,
321
                                           const NamespaceName& keyspace_name,
322
2.20k
                                           const TableName& table_name) {
323
2.20k
  DFATAL_OR_RETURN_ERROR_IF(keyspace_name.empty(),
324
2.20k
                            STATUS_SUBSTITUTE(InvalidArgument, "Empty keyspace for table $0",
325
2.20k
                                              table_name));
326
2.20k
  DFATAL_OR_RETURN_ERROR_IF(table_name.empty(),
327
2.20k
                            STATUS(InvalidArgument, "Table name cannot be empty"));
328
329
2.20k
  auto s = ql_env_->HasTablePermission(keyspace_name, table_name, permission);
330
2.20k
  if (!s.ok()) {
331
92
    return Error(loc, s.message().ToBuffer().c_str(), ErrorCode::UNAUTHORIZED);
332
92
  }
333
2.11k
  return Status::OK();
334
2.11k
}
335
336
Status SemContext::CheckHasTablePermission(const YBLocation& loc,
337
                                           const PermissionType permission,
338
2.14k
                                           client::YBTableName table_name) {
339
2.14k
  return CheckHasTablePermission(loc, permission, table_name.namespace_name(),
340
2.14k
                                 table_name.table_name());
341
2.14k
}
342
343
Status SemContext::CheckHasRolePermission(const YBLocation& loc,
344
                                          PermissionType permission,
345
1.06k
                                          const RoleName& role_name) {
346
347
1.06k
  auto s = ql_env_->HasRolePermission(role_name, permission);
348
1.06k
  if (!s.ok()) {
349
22
    return Error(loc, s.message().ToBuffer().c_str(), ErrorCode::UNAUTHORIZED);
350
22
  }
351
1.04k
  return Status::OK();
352
1.04k
}
353
354
Status SemContext::CheckHasAllKeyspacesPermission(const YBLocation& loc,
355
1.12k
                                                  PermissionType permission) {
356
357
1.12k
  auto s = ql_env_->HasResourcePermission(kRolesDataResource, ObjectType::SCHEMA,
358
1.12k
                                          permission);
359
1.12k
  if (!s.ok()) {
360
48
    return Error(loc, s.message().ToBuffer().c_str(), ErrorCode::UNAUTHORIZED);
361
48
  }
362
1.07k
  return Status::OK();
363
1.07k
}
364
365
Status SemContext::CheckHasAllRolesPermission(const YBLocation& loc,
366
826
                                              PermissionType permission) {
367
368
826
  auto s = ql_env_->HasResourcePermission(kRolesRoleResource, ObjectType::ROLE, permission);
369
826
  if (!s.ok()) {
370
0
    return Error(loc, s.message().ToBuffer().c_str(), ErrorCode::UNAUTHORIZED);
371
0
  }
372
826
  return Status::OK();
373
826
}
374
375
//--------------------------------------------------------------------------------------------------
376
377
bool SemContext::IsConvertible(const std::shared_ptr<QLType>& lhs_type,
378
714k
                               const std::shared_ptr<QLType>& rhs_type) const {
379
714k
  return QLType::IsImplicitlyConvertible(lhs_type, rhs_type);
380
714k
}
381
382
226k
bool SemContext::IsComparable(DataType lhs_type, DataType rhs_type) const {
383
226k
  return QLType::IsComparable(lhs_type, rhs_type);
384
226k
}
385
386
2.23M
const std::shared_ptr<QLType>& SemContext::expr_expected_ql_type() const {
387
72
  DCHECK(sem_state_) << "State variable is not set for the expression";
388
2.23M
  return sem_state_->expected_ql_type();
389
2.23M
}
390
391
158k
NullIsAllowed SemContext::expected_ql_type_accepts_null() const {
392
35
  DCHECK(sem_state_) << "State variable is not set for the expression";
393
158k
  return sem_state_->expected_ql_type_accepts_null();
394
158k
}
395
396
1.50M
InternalType SemContext::expr_expected_internal_type() const {
397
1
  DCHECK(sem_state_) << "State variable is not set for the expression";
398
1.50M
  return sem_state_->expected_internal_type();
399
1.50M
}
400
401
2.35M
SelectScanInfo *SemContext::scan_state() const {
402
45
  DCHECK(sem_state_) << "State variable is not set for the expression";
403
2.35M
  return sem_state_->scan_state();
404
2.35M
}
405
406
1.63M
bool SemContext::void_primary_key_condition() const {
407
36
  DCHECK(sem_state_) << "State variable is not set for the expression";
408
1.63M
  return sem_state_->void_primary_key_condition();
409
1.63M
}
410
411
1.96M
WhereExprState *SemContext::where_state() const {
412
18.4E
  DCHECK(sem_state_) << "State variable is not set for the expression";
413
1.96M
  return sem_state_->where_state();
414
1.96M
}
415
416
0
IfExprState *SemContext::if_state() const {
417
0
  DCHECK(sem_state_) << "State variable is not set for the expression";
418
0
  return sem_state_->if_state();
419
0
}
420
421
1.51M
bool SemContext::validate_orderby_expr() const {
422
25
  DCHECK(sem_state_) << "State variable is not set for the expression";
423
1.51M
  return sem_state_->validate_orderby_expr();
424
1.51M
}
425
426
3.11M
IdxPredicateState *SemContext::idx_predicate_state() const {
427
18.4E
  DCHECK(sem_state_) << "State variable is not set for the expression";
428
3.11M
  return sem_state_->idx_predicate_state();
429
3.11M
}
430
431
3.62M
bool SemContext::selecting_from_index() const {
432
124
  DCHECK(sem_state_) << "State variable is not set";
433
3.62M
  return sem_state_->selecting_from_index();
434
3.62M
}
435
436
1.51M
size_t SemContext::index_select_prefix_length() const {
437
10
  DCHECK(sem_state_) << "State variable is not set";
438
1.51M
  return sem_state_->index_select_prefix_length();
439
1.51M
}
440
441
13.3k
bool SemContext::processing_column_definition() const {
442
0
  DCHECK(sem_state_) << "State variable is not set";
443
13.3k
  return sem_state_->processing_column_definition();
444
13.3k
}
445
446
16.0k
const MCSharedPtr<MCString>& SemContext::bindvar_name() const {
447
0
  DCHECK(sem_state_) << "State variable is not set for the expression";
448
16.0k
  return sem_state_->bindvar_name();
449
16.0k
}
450
451
16.2k
const ColumnDesc *SemContext::hash_col() const {
452
0
  DCHECK(sem_state_) << "State variable is not set for the expression";
453
16.2k
  return sem_state_->hash_col();
454
16.2k
}
455
456
14.8k
const ColumnDesc *SemContext::lhs_col() const {
457
0
  DCHECK(sem_state_) << "State variable is not set for the expression";
458
14.8k
  return sem_state_->lhs_col();
459
14.8k
}
460
461
3.01M
bool SemContext::processing_set_clause() const {
462
18
  DCHECK(sem_state_) << "State variable is not set for the expression";
463
3.01M
  return sem_state_->processing_set_clause();
464
3.01M
}
465
466
1.51M
bool SemContext::processing_assignee() const {
467
26
  DCHECK(sem_state_) << "State variable is not set for the expression";
468
1.51M
  return sem_state_->processing_assignee();
469
1.51M
}
470
471
1.98M
bool SemContext::processing_if_clause() const {
472
160
  DCHECK(sem_state_) << "State variable is not set for the expression";
473
1.98M
  return sem_state_->processing_if_clause();
474
1.98M
}
475
476
175
bool SemContext::allowing_aggregate() const {
477
0
  DCHECK(sem_state_) << "State variable is not set for the expression";
478
175
  return sem_state_->allowing_aggregate();
479
175
}
480
481
1.51M
bool SemContext::allowing_column_refs() const {
482
427
  DCHECK(sem_state_) << "State variable is not set for the expression";
483
1.51M
  return sem_state_->allowing_column_refs();
484
1.51M
}
485
486
2.79M
PTDmlStmt *SemContext::current_dml_stmt() const {
487
2.79M
  return sem_state_->current_dml_stmt();
488
2.79M
}
489
490
316k
void SemContext::set_current_dml_stmt(PTDmlStmt *stmt) {
491
316k
  sem_state_->set_current_dml_stmt(stmt);
492
316k
}
493
494
531
void SemContext::set_void_primary_key_condition(bool val) {
495
0
  DCHECK(sem_state_) << "State variable is not set for the expression";
496
531
  sem_state_->set_void_primary_key_condition(val);
497
531
}
498
499
335
bool SemContext::IsUncoveredIndexSelect() const {
500
335
  return sem_state_->is_uncovered_index_select();
501
335
}
502
503
90
bool SemContext::IsPartialIndexSelect() const {
504
90
  return sem_state_->is_partial_index_select();
505
90
}
506
507
}  // namespace ql
508
}  // namespace yb