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/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
339k
      ql_env_(ql_env) {
55
339k
}
56
57
342k
SemContext::~SemContext() {
58
342k
}
59
60
//--------------------------------------------------------------------------------------------------
61
62
3.76M
MemoryContext *SemContext::PSemMem() const {
63
3.76M
  return parse_tree_->PSemMem();
64
3.76M
}
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
61.1k
std::string SemContext::CurrentKeyspace() const {
77
61.1k
  return ql_env_->CurrentKeyspace();
78
61.1k
}
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.60k
                              MCVector<ColumnDesc>* col_descs) {
86
3.60k
  const YBSchema& schema = table->schema();
87
3.60k
  const auto num_columns = schema.num_columns();
88
3.60k
  const auto num_key_columns = schema.num_key_columns();
89
3.60k
  const auto num_hash_key_columns = schema.num_hash_key_columns();
90
91
3.60k
  if (col_descs != nullptr) {
92
579
    col_descs->reserve(num_columns);
93
3.28k
    for (size_t idx = 0; idx < num_columns; 
idx++2.70k
) {
94
      // Find the column descriptor.
95
2.70k
      const YBColumnSchema col = schema.Column(idx);
96
2.70k
      col_descs->emplace_back(idx,
97
2.70k
                              schema.ColumnId(idx),
98
2.70k
                              col.name(),
99
2.70k
                              idx < num_hash_key_columns,
100
2.70k
                              idx < num_key_columns,
101
2.70k
                              col.is_static(),
102
2.70k
                              col.is_counter(),
103
2.70k
                              col.type(),
104
2.70k
                              YBColumnSchema::ToInternalDataType(col.type()),
105
2.70k
                              schema.table_properties().use_mangled_column_name());
106
107
      // Insert the column descriptor, and column definition if requested, to symbol table.
108
2.70k
      MCSharedPtr<MCString> col_name = MCMakeShared<MCString>(PSemMem(), col.name().c_str());
109
2.70k
      RETURN_NOT_OK(MapSymbol(*col_name, &(*col_descs)[idx]));
110
2.70k
    }
111
579
  }
112
113
3.60k
  return Status::OK();
114
3.60k
}
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.63k
                               MCVector<ColumnDesc>* col_descs) {
123
3.63k
  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_table0
&&
client::FLAGS_yb_system_namespace_readonly0
) {
129
0
    return Error(loc, ErrorCode::SYSTEM_NAMESPACE_READONLY);
130
0
  }
131
132
3.60k
  VLOG
(3) << "Loading table descriptor for " << name.ToString()0
;
133
3.60k
  *table = GetTableDesc(name);
134
3.60k
  if (*table == nullptr || 
(3.60k
(*table)->IsIndex()3.60k
&&
!FLAGS_allow_index_table_read_write0
) ||
135
      // Only looking for CQL tables.
136
3.60k
      
(*table)->table_type() != client::YBTableType::YQL_TABLE_TYPE3.60k
) {
137
3
    return Error(loc, ErrorCode::OBJECT_NOT_FOUND);
138
3
  }
139
140
3.60k
  return LoadSchema(*table, col_descs);
141
3.60k
}
142
143
7.20k
Status SemContext::MapSymbol(const MCString& name, PTColumnDefinition *entry) {
144
7.20k
  if (symtab_[name].column_ != nullptr) {
145
0
    return Error(entry, ErrorCode::DUPLICATE_COLUMN);
146
0
  }
147
7.20k
  symtab_[name].column_ = entry;
148
7.20k
  return Status::OK();
149
7.20k
}
150
151
57
Status SemContext::MapSymbol(const MCString& name, PTAlterColumnDefinition *entry) {
152
57
  if (symtab_[name].alter_column_ != nullptr) {
153
0
    return Error(entry, ErrorCode::DUPLICATE_COLUMN);
154
0
  }
155
57
  symtab_[name].alter_column_ = entry;
156
57
  return Status::OK();
157
57
}
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.70k
Status SemContext::MapSymbol(const MCString& name, ColumnDesc *entry) {
168
2.70k
  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.70k
  symtab_[name].column_desc_ = entry;
174
2.70k
  return Status::OK();
175
2.70k
}
176
177
129
Status SemContext::MapSymbol(const MCString& name, PTTypeField *entry) {
178
129
  if (symtab_[name].type_field_ != nullptr) {
179
2
    return Error(entry, ErrorCode::DUPLICATE_TYPE_FIELD);
180
2
  }
181
127
  symtab_[name].type_field_ = entry;
182
127
  return Status::OK();
183
129
}
184
185
327k
shared_ptr<YBTable> SemContext::GetTableDesc(const client::YBTableName& table_name) {
186
327k
  bool cache_used = false;
187
327k
  shared_ptr<YBTable> table = ql_env_->GetTableDesc(table_name, &cache_used);
188
327k
  if (
table != nullptr327k
) {
189
327k
    parse_tree_->AddAnalyzedTable(table_name);
190
327k
    if (cache_used) {
191
      // Remember cache was used.
192
282k
      cache_used_ = true;
193
282k
    }
194
327k
  }
195
327k
  return table;
196
327k
}
197
198
1.43k
shared_ptr<YBTable> SemContext::GetTableDesc(const TableId& table_id) {
199
1.43k
  bool cache_used = false;
200
1.43k
  shared_ptr<YBTable> table = ql_env_->GetTableDesc(table_id, &cache_used);
201
1.43k
  if (table != nullptr) {
202
1.43k
    parse_tree_->AddAnalyzedTable(table->name());
203
1.43k
    if (cache_used) {
204
      // Remember cache was used.
205
1.04k
      cache_used_ = true;
206
1.04k
    }
207
1.43k
  }
208
1.43k
  return table;
209
1.43k
}
210
211
std::shared_ptr<QLType> SemContext::GetUDType(const string &keyspace_name,
212
82
                                              const string &type_name) {
213
82
  bool cache_used = false;
214
82
  shared_ptr<QLType> type = ql_env_->GetUDType(keyspace_name, type_name, &cache_used);
215
216
82
  if (type != nullptr) {
217
75
    parse_tree_->AddAnalyzedUDType(keyspace_name, type_name);
218
75
    if (cache_used) {
219
      // Remember cache was used.
220
26
      cache_used_ = true;
221
26
    }
222
75
  }
223
224
82
  return type;
225
82
}
226
227
11.4k
const SymbolEntry *SemContext::SeekSymbol(const MCString& name) const {
228
11.4k
  MCMap<MCString, SymbolEntry>::const_iterator iter = symtab_.find(name);
229
11.4k
  if (iter != symtab_.end()) {
230
11.4k
    return &iter->second;
231
11.4k
  }
232
31
  return nullptr;
233
11.4k
}
234
235
6.43k
PTColumnDefinition *SemContext::GetColumnDefinition(const MCString& col_name) {
236
6.43k
  const SymbolEntry * entry = SeekSymbol(col_name);
237
6.43k
  if (entry == nullptr) {
238
29
    return nullptr;
239
29
  }
240
6.41k
  return entry->column_;
241
6.43k
}
242
243
5.05k
const ColumnDesc *SemContext::GetColumnDesc(const MCString& col_name) const {
244
5.05k
  const SymbolEntry * entry = SeekSymbol(col_name);
245
5.05k
  if (entry == nullptr) {
246
2
    return nullptr;
247
2
  }
248
249
5.04k
  PTDmlStmt *dml_stmt = current_dml_stmt();
250
5.04k
  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.04k
  if (sem_state_ && sem_state_->is_processing_index_column()) {
289
1.92k
    sem_state_->add_index_column_ref(entry->column_desc_->id());
290
1.92k
  }
291
292
5.04k
  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.04k
  return entry->column_desc_;
298
5.04k
}
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.47k
}
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.20k
}
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.06k
}
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.12k
}
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
729k
                               const std::shared_ptr<QLType>& rhs_type) const {
379
729k
  return QLType::IsImplicitlyConvertible(lhs_type, rhs_type);
380
729k
}
381
382
229k
bool SemContext::IsComparable(DataType lhs_type, DataType rhs_type) const {
383
229k
  return QLType::IsComparable(lhs_type, rhs_type);
384
229k
}
385
386
2.27M
const std::shared_ptr<QLType>& SemContext::expr_expected_ql_type() const {
387
2.27M
  DCHECK
(sem_state_) << "State variable is not set for the expression"31
;
388
2.27M
  return sem_state_->expected_ql_type();
389
2.27M
}
390
391
160k
NullIsAllowed SemContext::expected_ql_type_accepts_null() const {
392
18.4E
  DCHECK(sem_state_) << "State variable is not set for the expression";
393
160k
  return sem_state_->expected_ql_type_accepts_null();
394
160k
}
395
396
1.53M
InternalType SemContext::expr_expected_internal_type() const {
397
18.4E
  DCHECK(sem_state_) << "State variable is not set for the expression";
398
1.53M
  return sem_state_->expected_internal_type();
399
1.53M
}
400
401
2.38M
SelectScanInfo *SemContext::scan_state() const {
402
2.38M
  DCHECK
(sem_state_) << "State variable is not set for the expression"17
;
403
2.38M
  return sem_state_->scan_state();
404
2.38M
}
405
406
1.65M
bool SemContext::void_primary_key_condition() const {
407
1.65M
  DCHECK
(sem_state_) << "State variable is not set for the expression"45
;
408
1.65M
  return sem_state_->void_primary_key_condition();
409
1.65M
}
410
411
1.99M
WhereExprState *SemContext::where_state() const {
412
18.4E
  DCHECK(sem_state_) << "State variable is not set for the expression";
413
1.99M
  return sem_state_->where_state();
414
1.99M
}
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.53M
bool SemContext::validate_orderby_expr() const {
422
1.53M
  DCHECK
(sem_state_) << "State variable is not set for the expression"894
;
423
1.53M
  return sem_state_->validate_orderby_expr();
424
1.53M
}
425
426
3.17M
IdxPredicateState *SemContext::idx_predicate_state() const {
427
3.17M
  DCHECK
(sem_state_) << "State variable is not set for the expression"66
;
428
3.17M
  return sem_state_->idx_predicate_state();
429
3.17M
}
430
431
3.67M
bool SemContext::selecting_from_index() const {
432
3.67M
  DCHECK
(sem_state_) << "State variable is not set"16
;
433
3.67M
  return sem_state_->selecting_from_index();
434
3.67M
}
435
436
1.53M
size_t SemContext::index_select_prefix_length() const {
437
18.4E
  DCHECK(sem_state_) << "State variable is not set";
438
1.53M
  return sem_state_->index_select_prefix_length();
439
1.53M
}
440
441
14.3k
bool SemContext::processing_column_definition() const {
442
14.3k
  DCHECK
(sem_state_) << "State variable is not set"0
;
443
14.3k
  return sem_state_->processing_column_definition();
444
14.3k
}
445
446
17.2k
const MCSharedPtr<MCString>& SemContext::bindvar_name() const {
447
17.2k
  DCHECK
(sem_state_) << "State variable is not set for the expression"0
;
448
17.2k
  return sem_state_->bindvar_name();
449
17.2k
}
450
451
17.8k
const ColumnDesc *SemContext::hash_col() const {
452
17.8k
  DCHECK
(sem_state_) << "State variable is not set for the expression"1
;
453
17.8k
  return sem_state_->hash_col();
454
17.8k
}
455
456
14.8k
const ColumnDesc *SemContext::lhs_col() const {
457
14.8k
  DCHECK
(sem_state_) << "State variable is not set for the expression"0
;
458
14.8k
  return sem_state_->lhs_col();
459
14.8k
}
460
461
3.06M
bool SemContext::processing_set_clause() const {
462
3.06M
  DCHECK
(sem_state_) << "State variable is not set for the expression"85
;
463
3.06M
  return sem_state_->processing_set_clause();
464
3.06M
}
465
466
1.54M
bool SemContext::processing_assignee() const {
467
1.54M
  DCHECK
(sem_state_) << "State variable is not set for the expression"219
;
468
1.54M
  return sem_state_->processing_assignee();
469
1.54M
}
470
471
2.02M
bool SemContext::processing_if_clause() const {
472
2.02M
  DCHECK
(sem_state_) << "State variable is not set for the expression"4
;
473
2.02M
  return sem_state_->processing_if_clause();
474
2.02M
}
475
476
184
bool SemContext::allowing_aggregate() const {
477
184
  DCHECK
(sem_state_) << "State variable is not set for the expression"0
;
478
184
  return sem_state_->allowing_aggregate();
479
184
}
480
481
1.53M
bool SemContext::allowing_column_refs() const {
482
1.53M
  DCHECK
(sem_state_) << "State variable is not set for the expression"28
;
483
1.53M
  return sem_state_->allowing_column_refs();
484
1.53M
}
485
486
2.83M
PTDmlStmt *SemContext::current_dml_stmt() const {
487
2.83M
  return sem_state_->current_dml_stmt();
488
2.83M
}
489
490
324k
void SemContext::set_current_dml_stmt(PTDmlStmt *stmt) {
491
324k
  sem_state_->set_current_dml_stmt(stmt);
492
324k
}
493
494
542
void SemContext::set_void_primary_key_condition(bool val) {
495
542
  DCHECK
(sem_state_) << "State variable is not set for the expression"0
;
496
542
  sem_state_->set_void_primary_key_condition(val);
497
542
}
498
499
339
bool SemContext::IsUncoveredIndexSelect() const {
500
339
  return sem_state_->is_uncovered_index_select();
501
339
}
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