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/pt_expr.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 expressions.
16
//--------------------------------------------------------------------------------------------------
17
18
#include "yb/yql/cql/ql/ptree/pt_expr.h"
19
20
#include "yb/bfql/tserver_opcodes.h"
21
22
#include "yb/client/table.h"
23
24
#include "yb/common/common.pb.h"
25
#include "yb/common/index.h"
26
#include "yb/common/index_column.h"
27
#include "yb/common/ql_type.h"
28
29
#include "yb/gutil/casts.h"
30
31
#include "yb/util/date_time.h"
32
#include "yb/util/decimal.h"
33
#include "yb/util/net/inetaddress.h"
34
#include "yb/util/net/net_util.h"
35
#include "yb/util/stol_utils.h"
36
37
#include "yb/yql/cql/ql/ptree/column_desc.h"
38
#include "yb/yql/cql/ql/ptree/pt_bcall.h"
39
#include "yb/yql/cql/ql/ptree/pt_select.h"
40
#include "yb/yql/cql/ql/ptree/pt_type.h"
41
#include "yb/yql/cql/ql/ptree/sem_context.h"
42
#include "yb/yql/cql/ql/ptree/yb_location.h"
43
44
namespace yb {
45
namespace ql {
46
47
using client::YBColumnSchema;
48
using std::shared_ptr;
49
50
//--------------------------------------------------------------------------------------------------
51
52
PTExpr::PTExpr(
53
    MemoryContext *memctx,
54
    YBLocation::SharedPtr loc,
55
    ExprOperator op,
56
    yb::QLOperator ql_op,
57
    InternalType internal_type,
58
    DataType ql_type_id)
59
1.16M
    : PTExpr(memctx, loc, op, ql_op, internal_type, QLType::Create(ql_type_id)) {
60
1.16M
}
61
62
PTExpr::PTExpr(
63
    MemoryContext *memctx,
64
    YBLocation::SharedPtr loc,
65
    ExprOperator op,
66
    yb::QLOperator ql_op,
67
    InternalType internal_type,
68
    const QLTypePtr& ql_type)
69
    : TreeNode(memctx, loc),
70
      op_(op),
71
      ql_op_(ql_op),
72
      internal_type_(internal_type),
73
      ql_type_(ql_type),
74
      expected_internal_type_(InternalType::VALUE_NOT_SET),
75
      is_in_operand_(false),
76
1.17M
      index_name_(MCMakeShared<MCString>(memctx)) {
77
1.17M
}
78
79
0
void PTExpr::set_ql_type(DataType type_id) {
80
0
  ql_type_ = QLType::Create(type_id);
81
0
}
82
83
979
void PTExpr::set_ql_type_id(DataType type_id) {
84
979
  ql_type_ = QLType::Create(type_id);
85
979
}
86
87
5.05M
DataType PTExpr::ql_type_id() const {
88
5.05M
  return ql_type_->main();
89
5.05M
}
90
91
1.48M
bool PTExpr::has_valid_ql_type_id() {
92
1.48M
  return ql_type_->main() != DataType::UNKNOWN_DATA;
93
1.48M
}
94
95
0
bfql::TSOpcode PTExpr::aggregate_opcode() const {
96
0
  return bfql::TSOpcode::kNoOp;
97
0
}
98
99
143k
bool PTExpr::is_null() const {
100
143k
  return ql_type_->main() == DataType::NULL_VALUE_TYPE;
101
143k
}
102
103
319
std::string PTExpr::MetadataName() const {
104
  // If this expression was used to define an index column, use its descriptor name.
105
316
  return index_desc_ ? index_desc_->MetadataName() : QLName(QLNameOption::kMetadataName);
106
319
}
107
108
1.48M
bool PTExpr::has_valid_internal_type() {
109
  // internal_type_ is not set in case of PTNull.
110
1.48M
  return ql_type_->main() == DataType::NULL_VALUE_TYPE ||
111
1.32M
         internal_type_ != InternalType::VALUE_NOT_SET;
112
1.48M
}
113
114
392k
void PTExpr::rscol_type_PB(QLTypePB *pb_type ) const {
115
392k
  ql_type_->ToQLTypePB(pb_type);
116
392k
}
117
118
1.50M
bool PTExpr::CheckIndexColumn(SemContext *sem_context) {
119
1.50M
  if (!sem_context->selecting_from_index()) {
120
1.49M
    return false;
121
1.49M
  }
122
123
  // Currently, only PTJsonColumnWithOperators node is allowed to be an IndexColumn. However, define
124
  // this analysis in PTExpr class so that it's easier to extend the support INDEX by expression.
125
7.24k
  if (op_ != ExprOperator::kJsonOperatorRef) {
126
7.24k
    return false;
127
7.24k
  }
128
129
  // Check if this expression is used for indexing.
130
18.4E
  index_desc_ = GetColumnDesc(sem_context);
131
18.4E
  if (index_desc_ != nullptr) {
132
    // Type resolution: This expr should have the same datatype as the column.
133
47
    index_name_->assign(QLName().c_str());
134
47
    internal_type_ = index_desc_->internal_type();
135
47
    ql_type_ = index_desc_->ql_type();
136
47
    return true;
137
47
  }
138
139
18.4E
  return false;
140
18.4E
}
141
142
1.50M
CHECKED_STATUS PTExpr::CheckOperator(SemContext *sem_context) {
143
  // Where clause only allow AND, EQ, LT, LE, GT, and GE operators.
144
1.50M
  if (sem_context->where_state() != nullptr) {
145
385k
    switch (ql_op_) {
146
21.5k
      case QL_OP_AND:
147
140k
      case QL_OP_EQUAL:
148
140k
      case QL_OP_LESS_THAN:
149
141k
      case QL_OP_LESS_THAN_EQUAL:
150
141k
      case QL_OP_GREATER_THAN:
151
142k
      case QL_OP_GREATER_THAN_EQUAL:
152
142k
      case QL_OP_IN:
153
142k
      case QL_OP_NOT_IN:
154
142k
      case QL_OP_NOT_EQUAL:
155
386k
      case QL_OP_NOOP:
156
386k
        break;
157
0
      default:
158
0
        return sem_context->Error(this, "This operator is not allowed in where clause",
159
0
                                  ErrorCode::CQL_STATEMENT_INVALID);
160
1.50M
    }
161
1.50M
  }
162
163
  // Partial index where clause only supports these operators: =, AND, !=, >, <, >=, <=.
164
1.50M
  if (sem_context->idx_predicate_state() != nullptr) {
165
600
    switch (ql_op_) {
166
48
      case QL_OP_AND:
167
116
      case QL_OP_EQUAL:
168
144
      case QL_OP_NOT_EQUAL:
169
213
      case QL_OP_GREATER_THAN:
170
218
      case QL_OP_GREATER_THAN_EQUAL:
171
223
      case QL_OP_LESS_THAN:
172
228
      case QL_OP_LESS_THAN_EQUAL:
173
600
      case QL_OP_NOOP:
174
600
        break;
175
0
      default:
176
0
        return sem_context->Error(this,
177
0
                                  "This operator is not allowed in partial index where clause",
178
0
                                  ErrorCode::CQL_STATEMENT_INVALID);
179
1.50M
    }
180
1.50M
  }
181
1.50M
  return Status::OK();
182
1.50M
}
183
184
0
CHECKED_STATUS PTExpr::AnalyzeOperator(SemContext *sem_context) {
185
0
  return Status::OK();
186
0
}
187
188
CHECKED_STATUS PTExpr::AnalyzeOperator(SemContext *sem_context,
189
0
                                       PTExpr::SharedPtr op1) {
190
0
  return Status::OK();
191
0
}
192
193
CHECKED_STATUS PTExpr::AnalyzeOperator(SemContext *sem_context,
194
                                       PTExpr::SharedPtr op1,
195
0
                                       PTExpr::SharedPtr op2) {
196
0
  return Status::OK();
197
0
}
198
199
CHECKED_STATUS PTExpr::AnalyzeOperator(SemContext *sem_context,
200
                                       PTExpr::SharedPtr op1,
201
                                       PTExpr::SharedPtr op2,
202
0
                                       PTExpr::SharedPtr op3) {
203
0
  return Status::OK();
204
0
}
205
206
0
CHECKED_STATUS PTExpr::SetupSemStateForOp1(SemState *sem_state) {
207
0
  return Status::OK();
208
0
}
209
210
0
CHECKED_STATUS PTExpr::SetupSemStateForOp2(SemState *sem_state) {
211
  // Passing down where clause state variables.
212
0
  return Status::OK();
213
0
}
214
215
0
CHECKED_STATUS PTExpr::SetupSemStateForOp3(SemState *sem_state) {
216
0
  return Status::OK();
217
0
}
218
219
1.49M
CHECKED_STATUS PTExpr::CheckExpectedTypeCompatibility(SemContext *sem_context) {
220
1.49M
  CHECK(has_valid_internal_type() && has_valid_ql_type_id());
221
222
  // Check if RHS accepts NULL.
223
1.49M
  if (ql_type_->main() == DataType::NULL_VALUE_TYPE &&
224
158k
      !sem_context->expected_ql_type_accepts_null()) {
225
46
    return sem_context->Error(this, ErrorCode::NULL_IN_COLLECTIONS);
226
46
  }
227
228
  // Check if RHS support counter update.
229
1.49M
  if (sem_context->processing_set_clause() &&
230
7.64k
      sem_context->lhs_col() != nullptr &&
231
6.49k
      sem_context->lhs_col()->is_counter()) {
232
28
    RETURN_NOT_OK(this->CheckCounterUpdateSupport(sem_context));
233
28
  }
234
235
  // Check if RHS is convertible to LHS.
236
1.49M
  if (!sem_context->expr_expected_ql_type()->IsUnknown()) {
237
714k
    if (!sem_context->IsConvertible(sem_context->expr_expected_ql_type(), ql_type_)) {
238
142
      return sem_context->Error(this, ErrorCode::DATATYPE_MISMATCH);
239
142
    }
240
1.49M
  }
241
242
  // Resolve internal type.
243
1.49M
  const InternalType expected_itype = sem_context->expr_expected_internal_type();
244
1.49M
  if (expected_itype == InternalType::VALUE_NOT_SET) {
245
773k
    expected_internal_type_ = internal_type_;
246
716k
  } else {
247
716k
    expected_internal_type_ = expected_itype;
248
716k
  }
249
1.49M
  return Status::OK();
250
1.49M
}
251
252
//--------------------------------------------------------------------------------------------------
253
CHECKED_STATUS PTExpr::CheckInequalityOperands(SemContext *sem_context,
254
                                               PTExpr::SharedPtr lhs,
255
225k
                                               PTExpr::SharedPtr rhs) {
256
225k
  if (!sem_context->IsComparable(lhs->ql_type_id(), rhs->ql_type_id())) {
257
26
    return sem_context->Error(this, "Cannot compare values of these datatypes",
258
26
                              ErrorCode::INCOMPARABLE_DATATYPES);
259
26
  }
260
225k
  return Status::OK();
261
225k
}
262
263
CHECKED_STATUS PTExpr::CheckEqualityOperands(SemContext *sem_context,
264
                                             PTExpr::SharedPtr lhs,
265
222k
                                             PTExpr::SharedPtr rhs) {
266
223k
  if (QLType::IsNull(lhs->ql_type_id()) || QLType::IsNull(rhs->ql_type_id())) {
267
799
    return Status::OK();
268
222k
  } else {
269
222k
    return CheckInequalityOperands(sem_context, lhs, rhs);
270
222k
  }
271
222k
}
272
273
274
188
CHECKED_STATUS PTExpr::CheckLhsExpr(SemContext *sem_context) {
275
188
  if (op_ != ExprOperator::kRef && op_ != ExprOperator::kBcall) {
276
0
    return sem_context->Error(this,
277
0
                              "Only column refs and builtin calls are allowed for left hand value",
278
0
                              ErrorCode::CQL_STATEMENT_INVALID);
279
0
  }
280
188
  return Status::OK();
281
188
}
282
283
467k
CHECKED_STATUS PTExpr::CheckRhsExpr(SemContext *sem_context) {
284
  // Check for limitation in QL (Not all expressions are acceptable).
285
467k
  switch (op_) {
286
690
    case ExprOperator::kRef:
287
      // Only accept column references where they are explicitly allowed.
288
690
      if (sem_context->sem_state() == nullptr || !sem_context->allowing_column_refs()) {
289
23
        return sem_context->Error(this,
290
23
                                  "Column references are not allowed in this context",
291
23
                                  ErrorCode::CQL_STATEMENT_INVALID);
292
23
      }
293
667
      FALLTHROUGH_INTENDED;
294
444k
    case ExprOperator::kConst: FALLTHROUGH_INTENDED;
295
445k
    case ExprOperator::kCollection: FALLTHROUGH_INTENDED;
296
450k
    case ExprOperator::kUMinus: FALLTHROUGH_INTENDED;
297
466k
    case ExprOperator::kBindVar: FALLTHROUGH_INTENDED;
298
466k
    case ExprOperator::kJsonOperatorRef: FALLTHROUGH_INTENDED;
299
466k
    case ExprOperator::kBcall:
300
466k
      break;
301
0
    default:
302
0
      return sem_context->Error(this, "Operator not allowed as right hand value",
303
0
                                ErrorCode::CQL_STATEMENT_INVALID);
304
466k
  }
305
306
466k
  return Status::OK();
307
466k
}
308
309
1
CHECKED_STATUS PTExpr::CheckCounterUpdateSupport(SemContext *sem_context) const {
310
1
  return sem_context->Error(this, ErrorCode::INVALID_COUNTING_EXPR);
311
1
}
312
313
PTExpr::SharedPtr PTExpr::CreateConst(MemoryContext *memctx,
314
                                      YBLocation::SharedPtr loc,
315
113
                                      PTBaseType::SharedPtr data_type) {
316
113
  switch(data_type->ql_type()->main()) {
317
16
    case DataType::DOUBLE:
318
16
      return PTConstDouble::MakeShared(memctx, loc, 0);
319
6
    case DataType::FLOAT:
320
6
      return PTConstFloat::MakeShared(memctx, loc, 0);
321
9
    case DataType::INT16:
322
9
      return PTConstInt16::MakeShared(memctx, loc, 0);
323
21
    case DataType::INT32:
324
21
      return PTConstInt32::MakeShared(memctx, loc, 0);
325
17
    case DataType::INT64:
326
17
      return PTConstInt::MakeShared(memctx, loc, 0);
327
23
    case DataType::STRING:
328
23
      return PTConstText::MakeShared(memctx, loc, MCMakeShared<MCString>(memctx, ""));
329
2
    case DataType::TIMESTAMP:
330
2
      return PTConstTimestamp::MakeShared(memctx, loc, 0);
331
1
    case DataType::DATE:
332
1
      return PTConstDate::MakeShared(memctx, loc, 0);
333
2
    case DataType::DECIMAL:
334
2
      return PTConstDecimal::MakeShared(memctx, loc, MCMakeShared<MCString>(memctx));
335
16
    default:
336
16
      LOG(WARNING) << "Unexpected QL type: " << data_type->ql_type()->ToString();
337
16
      return nullptr;
338
113
  }
339
113
}
340
341
//--------------------------------------------------------------------------------------------------
342
343
PTLiteralString::PTLiteralString(MCSharedPtr<MCString> value)
344
341k
    : PTLiteral<MCSharedPtr<MCString>>(value) {
345
341k
}
346
347
344k
PTLiteralString::~PTLiteralString() {
348
344k
}
349
350
3.87M
CHECKED_STATUS PTLiteralString::ToInt64(int64_t *value, bool negate) const {
351
1.57k
  auto temp = negate ? CheckedStoll(string("-") + value_->c_str())
352
3.87M
              : CheckedStoll(*value_);
353
3.87M
  RETURN_NOT_OK(temp);
354
3.87M
  *value = *temp;
355
3.87M
  return Status::OK();
356
3.87M
}
357
358
1.72k
CHECKED_STATUS PTLiteralString::ToDouble(long double *value, bool negate) const {
359
1.72k
  auto temp = CheckedStold(*value_);
360
1.72k
  RETURN_NOT_OK(temp);
361
1.71k
  *value = negate ? -*temp : *temp;
362
1.71k
  return Status::OK();
363
1.72k
}
364
365
0
CHECKED_STATUS PTLiteralString::ToDecimal(util::Decimal *value, bool negate) const {
366
0
  if (negate) {
367
0
    return value->FromString(string("-") + value_->c_str());
368
0
  } else {
369
0
    return value->FromString(value_->c_str());
370
0
  }
371
0
}
372
373
2.75k
CHECKED_STATUS PTLiteralString::ToDecimal(string *value, bool negate) const {
374
2.75k
  util::Decimal d;
375
2.75k
  if (negate) {
376
1.05k
    RETURN_NOT_OK(d.FromString(string("-") + value_->c_str()));
377
1.69k
  } else {
378
1.69k
    RETURN_NOT_OK(d.FromString(value_->c_str()));
379
1.69k
  }
380
2.75k
  *value = d.EncodeToComparable();
381
2.75k
  return Status::OK();
382
2.75k
}
383
384
2.10k
CHECKED_STATUS PTLiteralString::ToVarInt(string *value, bool negate) const {
385
2.10k
  util::VarInt v;
386
2.10k
  if (negate) {
387
861
    RETURN_NOT_OK(v.FromString(string("-") + value_->c_str()));
388
1.24k
  } else {
389
1.24k
    RETURN_NOT_OK(v.FromString(value_->c_str()));
390
1.24k
  }
391
2.10k
  *value = v.EncodeToComparable();
392
2.10k
  return Status::OK();
393
2.10k
}
394
395
98
std::string PTLiteralString::ToString() const {
396
98
  return string(value_->c_str());
397
98
}
398
399
177k
CHECKED_STATUS PTLiteralString::ToString(string *value) const {
400
177k
  *value = value_->c_str();
401
177k
  return Status::OK();
402
177k
}
403
404
1.36k
CHECKED_STATUS PTLiteralString::ToTimestamp(int64_t *value) const {
405
1.32k
  *value = VERIFY_RESULT(DateTime::TimestampFromString(value_->c_str())).ToInt64();
406
1.32k
  return Status::OK();
407
1.36k
}
408
409
26
CHECKED_STATUS PTLiteralString::ToDate(uint32_t *value) const {
410
22
  *value = VERIFY_RESULT(DateTime::DateFromString(value_->c_str()));
411
22
  return Status::OK();
412
26
}
413
414
10
CHECKED_STATUS PTLiteralString::ToTime(int64_t *value) const {
415
5
  *value = VERIFY_RESULT(DateTime::TimeFromString(value_->c_str()));
416
5
  return Status::OK();
417
10
}
418
419
355
CHECKED_STATUS PTLiteralString::ToInetaddress(InetAddress *value) const {
420
353
  *value = InetAddress(VERIFY_RESULT(HostToAddress(value_->c_str())));
421
353
  return Status::OK();
422
355
}
423
424
//--------------------------------------------------------------------------------------------------
425
// Collections.
426
427
CHECKED_STATUS PTCollectionExpr::InitializeUDTValues(const QLType::SharedPtr& expected_type,
428
232
                                                     ProcessContextBase* process_context) {
429
232
  SCHECK(expected_type->IsUserDefined(), Corruption, "Expected type should be UDT");
430
232
  SCHECK_EQ(keys_.size(), values_.size(), Corruption,
431
232
            "Expected keys and values to be of the same size");
432
433
232
  udtype_field_values_.resize(expected_type->udtype_field_names().size());
434
  // Each literal key/value pair must correspond to a field name/type pair from the UDT
435
232
  auto values_it = values_.begin();
436
436
  for (const auto& key : keys_) {
437
    // All keys must be field refs
438
439
    // TODO (mihnea) Consider unifying handling of field references (for user-defined types) and
440
    // column references (for tables) to simplify this path.
441
436
    if (key->opcode() != TreeNodeOpcode::kPTRef) {
442
14
      return process_context->Error(this,
443
14
                                    "Field names for user-defined types must be field reference",
444
14
                                    ErrorCode::INVALID_ARGUMENTS);
445
14
    }
446
422
    PTRef* field_ref = down_cast<PTRef*>(key.get());
447
422
    if (!field_ref->name()->IsSimpleName()) {
448
0
      return process_context->Error(this,
449
0
                                    "Qualified names not allowed for fields of user-defined types",
450
0
                                    ErrorCode::INVALID_ARGUMENTS);
451
0
    }
452
422
    string field_name(field_ref->name()->last_name().c_str());
453
454
    // All keys must be existing field names from the UDT
455
422
    auto field_idx = expected_type->GetUDTypeFieldIdxByName(field_name);
456
422
    if (!field_idx) {
457
0
      return process_context->Error(this, "Invalid field name found for user-defined type instance",
458
0
                                    ErrorCode::INVALID_ARGUMENTS);
459
0
    }
460
461
    // Setting the corresponding field value
462
422
    udtype_field_values_[*field_idx] = *values_it;
463
422
    values_it++;
464
422
  }
465
218
  return Status::OK();
466
232
}
467
468
PTCollectionExpr::PTCollectionExpr(MemoryContext* memctx,
469
                 YBLocationPtr loc,
470
                 const QLTypePtr& ql_type)
471
    : PTExpr(memctx, loc, ExprOperator::kCollection, yb::QLOperator::QL_OP_NOOP,
472
             client::YBColumnSchema::ToInternalDataType(ql_type), ql_type),
473
1.37k
      keys_(memctx), values_(memctx), udtype_field_values_(memctx) {}
474
475
PTCollectionExpr::PTCollectionExpr(MemoryContext* memctx, YBLocationPtr loc, DataType literal_type)
476
1.32k
    : PTCollectionExpr(memctx, loc, QLType::Create(literal_type)) {}
Unexecuted instantiation: _ZN2yb2ql16PTCollectionExprC2EPNS_8internal9ArenaBaseINS2_11ArenaTraitsEEENSt3__110shared_ptrINS0_10YBLocationEEENS_8DataTypeE
_ZN2yb2ql16PTCollectionExprC1EPNS_8internal9ArenaBaseINS2_11ArenaTraitsEEENSt3__110shared_ptrINS0_10YBLocationEEENS_8DataTypeE
Line
Count
Source
476
1.32k
    : PTCollectionExpr(memctx, loc, QLType::Create(literal_type)) {}
477
478
2.01k
CHECKED_STATUS PTCollectionExpr::Analyze(SemContext *sem_context) {
479
  // Before traversing the expression, check if this whole expression is actually a column.
480
2.01k
  if (CheckIndexColumn(sem_context)) {
481
0
    return Status::OK();
482
0
  }
483
484
2.01k
  RETURN_NOT_OK(CheckOperator(sem_context));
485
2.01k
  const shared_ptr<QLType>& expected_type = sem_context->expr_expected_ql_type();
486
487
  // If no expected type is given, use type inferred during parsing
488
2.01k
  if (expected_type->main() == DataType::UNKNOWN_DATA) {
489
124
    return CheckExpectedTypeCompatibility(sem_context);
490
124
  }
491
492
  // Ensuring expected type is compatible with parsing/literal type.
493
1.89k
  auto conversion_mode = QLType::GetConversionMode(expected_type->main(), ql_type_->main());
494
1.89k
  if (conversion_mode > QLType::ConversionMode::kFurtherCheck) {
495
21
    return sem_context->Error(this, ErrorCode::DATATYPE_MISMATCH);
496
21
  }
497
498
1.87k
  const MCSharedPtr<MCString>& bindvar_name = sem_context->bindvar_name();
499
500
  // Checking type parameters.
501
1.87k
  switch (expected_type->main()) {
502
222
    case MAP: {
503
222
      if (ql_type_->main() == SET && values_.size() > 0) {
504
10
        return sem_context->Error(this, ErrorCode::DATATYPE_MISMATCH);
505
10
      }
506
507
      // Process keys and values.
508
      // Referencing column in collection is not allowed.
509
212
      SemState sem_state(sem_context);
510
212
      sem_state.set_allowing_column_refs(false);
511
512
212
      const shared_ptr<QLType>& key_type = expected_type->param_type(0);
513
212
      sem_state.SetExprState(
514
212
          key_type, YBColumnSchema::ToInternalDataType(key_type),
515
212
          bindvar_name, nullptr, NullIsAllowed::kFalse);
516
299
      for (auto& key : keys_) {
517
299
        RETURN_NOT_OK(key->Analyze(sem_context));
518
272
        RETURN_NOT_OK(key->CheckRhsExpr(sem_context));
519
272
      }
520
521
183
      const shared_ptr<QLType>& val_type = expected_type->param_type(1);
522
183
      sem_state.SetExprState(
523
183
          val_type, YBColumnSchema::ToInternalDataType(val_type),
524
183
          bindvar_name, nullptr, NullIsAllowed::kFalse);
525
267
      for (auto& value : values_) {
526
267
        RETURN_NOT_OK(value->Analyze(sem_context));
527
247
        RETURN_NOT_OK(value->CheckRhsExpr(sem_context));
528
247
      }
529
530
163
      sem_state.ResetContextState();
531
163
      break;
532
183
    }
533
179
    case SET: {
534
      // Process values.
535
      // Referencing column in collection is not allowed.
536
179
      SemState sem_state(sem_context);
537
179
      sem_state.set_allowing_column_refs(false);
538
539
179
      const shared_ptr<QLType>& val_type = expected_type->param_type(0);
540
179
      sem_state.SetExprState(
541
179
          val_type, YBColumnSchema::ToInternalDataType(val_type),
542
179
          bindvar_name, nullptr, NullIsAllowed::kFalse);
543
287
      for (auto& elem : values_) {
544
287
        RETURN_NOT_OK(elem->Analyze(sem_context));
545
252
        RETURN_NOT_OK(elem->CheckRhsExpr(sem_context));
546
252
      }
547
142
      sem_state.ResetContextState();
548
142
      break;
549
179
    }
550
551
834
    case LIST: {
552
      // Process values.
553
      // Referencing column in collection is not allowed.
554
834
      SemState sem_state(sem_context);
555
834
      sem_state.set_allowing_column_refs(false);
556
557
834
      const shared_ptr<QLType>& val_type = expected_type->param_type(0);
558
      // NULL value in the LIST is allowed for right operand of IN/NOT IN operators only.
559
834
      sem_state.SetExprState(
560
834
          val_type, YBColumnSchema::ToInternalDataType(val_type),
561
834
          bindvar_name, nullptr, NullIsAllowed(is_in_operand()));
562
2.49k
      for (auto& elem : values_) {
563
2.49k
        RETURN_NOT_OK(elem->Analyze(sem_context));
564
2.45k
        RETURN_NOT_OK(elem->CheckRhsExpr(sem_context));
565
2.45k
      }
566
792
      sem_state.ResetContextState();
567
792
      break;
568
834
    }
569
570
222
    case USER_DEFINED_TYPE: {
571
      // Process values.
572
      // Referencing column in collection is not allowed.
573
222
      SemState sem_state(sem_context);
574
222
      sem_state.set_allowing_column_refs(false);
575
576
222
      RETURN_NOT_OK(InitializeUDTValues(expected_type, sem_context));
577
637
      for (size_t i = 0; i < udtype_field_values_.size(); i++) {
578
437
        if (!udtype_field_values_[i]) {
579
          // Skip missing values
580
43
          continue;
581
43
        }
582
        // Each value should have the corresponding type from the UDT
583
394
        const auto& param_type = expected_type->param_type(i);
584
394
        sem_state.SetExprState(param_type,
585
394
                               YBColumnSchema::ToInternalDataType(param_type),
586
394
                               bindvar_name);
587
394
        RETURN_NOT_OK(udtype_field_values_[i]->Analyze(sem_context));
588
386
        RETURN_NOT_OK(udtype_field_values_[i]->CheckRhsExpr(sem_context));
589
386
      }
590
200
      sem_state.ResetContextState();
591
200
      break;
592
208
    }
593
594
414
    case FROZEN: {
595
414
      if (ql_type_->main() == FROZEN) {
596
        // Already analyzed (e.g. for indexes), just check if type matches.
597
31
        if (*ql_type_ != *expected_type) {
598
0
          return sem_context->Error(this, ErrorCode::DATATYPE_MISMATCH);
599
0
        }
600
383
      } else {
601
383
        SemState sem_state(sem_context);
602
383
        sem_state.SetExprState(expected_type->param_type(0),
603
383
                               YBColumnSchema::ToInternalDataType(expected_type->param_type(0)),
604
383
                               bindvar_name);
605
383
        RETURN_NOT_OK(Analyze(sem_context));
606
337
        sem_state.ResetContextState();
607
337
      }
608
368
      break;
609
414
    }
610
611
0
    case TUPLE:
612
0
      return sem_context->Error(this, "Tuple type not supported yet",
613
0
                                ErrorCode::FEATURE_NOT_SUPPORTED);
614
615
0
    default:
616
0
      return sem_context->Error(this, ErrorCode::DATATYPE_MISMATCH);
617
1.66k
  }
618
619
  // Assign correct datatype.
620
1.66k
  ql_type_ = expected_type;
621
1.66k
  internal_type_ = sem_context->expr_expected_internal_type();
622
623
1.66k
  return Status::OK();
624
1.66k
}
625
626
//--------------------------------------------------------------------------------------------------
627
// Logic expressions consist of the following operators.
628
//   ExprOperator::kNot
629
//   ExprOperator::kAND
630
//   ExprOperator::kOR
631
//   ExprOperator::kIsTrue
632
//   ExprOperator::kIsFalse
633
634
33.2k
CHECKED_STATUS PTLogicExpr::SetupSemStateForOp1(SemState *sem_state) {
635
  // Expect "bool" datatype for logic expression.
636
33.2k
  sem_state->SetExprState(QLType::Create(BOOL), InternalType::kBoolValue);
637
638
  // Pass down the state variables for IF clause "if_state".
639
33.2k
  sem_state->CopyPreviousIfState();
640
641
  // If this is OP_AND, we need to pass down the state variables for where clause "where_state".
642
33.2k
  if (ql_op_ == QL_OP_AND) {
643
33.2k
    sem_state->CopyPreviousWhereState();
644
33.2k
  }
645
33.2k
  return Status::OK();
646
33.2k
}
647
648
33.2k
CHECKED_STATUS PTLogicExpr::SetupSemStateForOp2(SemState *sem_state) {
649
  // Expect "bool" datatype for logic expression.
650
33.2k
  sem_state->SetExprState(QLType::Create(BOOL), InternalType::kBoolValue);
651
652
  // Pass down the state variables for IF clause "if_state".
653
33.2k
  sem_state->CopyPreviousIfState();
654
655
  // If this is OP_AND, we need to pass down the state variables for where clause "where_state".
656
33.2k
  if (ql_op_ == QL_OP_AND) {
657
33.1k
    sem_state->CopyPreviousWhereState();
658
33.1k
  }
659
33.2k
  return Status::OK();
660
33.2k
}
661
662
CHECKED_STATUS PTLogicExpr::AnalyzeOperator(SemContext *sem_context,
663
0
                                            PTExpr::SharedPtr op1) {
664
0
  switch (ql_op_) {
665
0
    case QL_OP_NOT:
666
0
      if (op1->ql_type_id() != BOOL) {
667
0
        return sem_context->Error(this, "Only boolean value is allowed in this context",
668
0
                                  ErrorCode::INVALID_DATATYPE);
669
0
      }
670
0
      internal_type_ = yb::InternalType::kBoolValue;
671
0
      break;
672
673
0
    case QL_OP_IS_TRUE: FALLTHROUGH_INTENDED;
674
0
    case QL_OP_IS_FALSE:
675
0
      return sem_context->Error(this, "Operator not supported yet",
676
0
                                ErrorCode::CQL_STATEMENT_INVALID);
677
0
    default:
678
0
      LOG(FATAL) << "Invalid operator";
679
0
  }
680
0
  return Status::OK();
681
0
}
682
683
CHECKED_STATUS PTLogicExpr::AnalyzeOperator(SemContext *sem_context,
684
                                            PTExpr::SharedPtr op1,
685
33.0k
                                            PTExpr::SharedPtr op2) {
686
  // Verify the operators.
687
33.0k
  DCHECK(ql_op_ == QL_OP_AND || ql_op_ == QL_OP_OR);
688
689
  // "op1" and "op2" must have been analyzed before getting here
690
33.0k
  if (op1->ql_type_id() != BOOL) {
691
0
    return sem_context->Error(op1, "Only boolean value is allowed in this context",
692
0
                              ErrorCode::INVALID_DATATYPE);
693
0
  }
694
33.0k
  if (op2->ql_type_id() != BOOL) {
695
0
    return sem_context->Error(op2, "Only boolean value is allowed in this context",
696
0
                              ErrorCode::INVALID_DATATYPE);
697
0
  }
698
699
33.0k
  internal_type_ = yb::InternalType::kBoolValue;
700
33.0k
  return Status::OK();
701
33.0k
}
702
703
//--------------------------------------------------------------------------------------------------
704
// Relations expressions: ==, !=, >, >=, between, ...
705
706
228k
CHECKED_STATUS PTRelationExpr::SetupSemStateForOp1(SemState *sem_state) {
707
  // Pass down the state variables for IF clause "if_state".
708
228k
  sem_state->CopyPreviousIfState();
709
710
  // passing down where state
711
228k
  sem_state->CopyPreviousWhereState();
712
228k
  sem_state->set_allowing_column_refs(true);
713
  // No expectation for operand 1. All types are accepted.
714
228k
  return Status::OK();
715
228k
}
716
717
228k
CHECKED_STATUS PTRelationExpr::SetupSemStateForOp2(SemState *sem_state) {
718
  // The state of operand2 is dependent on operand1.
719
228k
  PTExpr::SharedPtr operand1 = op1();
720
228k
  DCHECK_NOTNULL(operand1.get());
721
228k
  sem_state->set_allowing_column_refs(false);
722
723
228k
  switch (ql_op_) {
724
223k
    case QL_OP_EQUAL: FALLTHROUGH_INTENDED;
725
223k
    case QL_OP_LESS_THAN: FALLTHROUGH_INTENDED;
726
224k
    case QL_OP_LESS_THAN_EQUAL: FALLTHROUGH_INTENDED;
727
225k
    case QL_OP_GREATER_THAN: FALLTHROUGH_INTENDED;
728
226k
    case QL_OP_GREATER_THAN_EQUAL: FALLTHROUGH_INTENDED;
729
226k
    case QL_OP_NOT_EQUAL: FALLTHROUGH_INTENDED;
730
226k
    case QL_OP_EXISTS: FALLTHROUGH_INTENDED;
731
226k
    case QL_OP_NOT_EXISTS: FALLTHROUGH_INTENDED;
732
226k
    case QL_OP_BETWEEN: FALLTHROUGH_INTENDED;
733
226k
    case QL_OP_NOT_BETWEEN: {
734
      // TODO(neil) Indexing processing should be redesigned such that when processing a statement
735
      // against an INDEX table, most of these semantic processing shouldn't be done again as they
736
      // were already done once again the actual table.
737
738
      // Setup for expression column.
739
226k
      if (operand1->index_desc() != nullptr) {
740
        // Operand1 is a index column.
741
75
        sem_state->SetExprState(operand1->ql_type(),
742
75
                                operand1->internal_type(),
743
75
                                operand1->index_name(),
744
75
                                operand1->index_desc());
745
75
        break;
746
75
      }
747
748
      // Setup for table column.
749
226k
      if (operand1->expr_op() == ExprOperator::kRef) {
750
225k
        const PTRef *ref = static_cast<const PTRef *>(operand1.get());
751
225k
        sem_state->SetExprState(ref->ql_type(),
752
225k
                                ref->internal_type(),
753
225k
                                ref->bindvar_name(),
754
225k
                                ref->desc());
755
225k
        break;
756
225k
      }
757
758
      // Setup for other expression.
759
937
      sem_state->SetExprState(operand1->ql_type(), operand1->internal_type());
760
937
      switch (operand1->expr_op()) {
761
172
        case ExprOperator::kBcall: {
762
172
          PTBcall *bcall = static_cast<PTBcall *>(operand1.get());
763
172
          DCHECK_NOTNULL(bcall->name().get());
764
172
          if (strcmp(bcall->name()->c_str(), "token") == 0) {
765
66
            sem_state->set_bindvar_name(PTBindVar::token_bindvar_name());
766
66
          }
767
172
          if (strcmp(bcall->name()->c_str(), "partition_hash") == 0) {
768
30
            sem_state->set_bindvar_name(PTBindVar::partition_hash_bindvar_name());
769
30
          }
770
172
          break;
771
0
        }
772
773
293
        case ExprOperator::kSubColRef: {
774
293
          const PTSubscriptedColumn *ref = static_cast<const PTSubscriptedColumn *>(operand1.get());
775
293
          if (ref->desc()) {
776
221
            sem_state->set_bindvar_name(PTBindVar::coll_bindvar_name(ref->desc()->name()));
777
72
          } else if (!sem_state->is_uncovered_index_select()) {
778
0
            return STATUS(
779
0
                QLError, "Column doesn't exist", Slice(), QLError(ErrorCode::UNDEFINED_COLUMN));
780
0
          } // else - this column is uncovered by the Index, skip checks and return OK.
781
293
          break;
782
293
        }
783
784
343
        case ExprOperator::kJsonOperatorRef: {
785
343
          const PTJsonColumnWithOperators *ref =
786
343
              static_cast<const PTJsonColumnWithOperators*>(operand1.get());
787
343
          if (ref->desc()) {
788
341
            sem_state->set_bindvar_name(PTBindVar::json_bindvar_name(ref->desc()->name()));
789
2
          } else if (!sem_state->is_uncovered_index_select()) {
790
0
            return STATUS(
791
0
                QLError, "Column doesn't exist", Slice(), QLError(ErrorCode::UNDEFINED_COLUMN));
792
0
          } // else - this column is uncovered by the Index, skip checks and return OK.
793
343
          break;
794
343
        }
795
796
0
        default: {} // Use default bindvar name below.
797
937
      }
798
799
808
      break;
800
937
    }
801
802
586
    case QL_OP_IN: FALLTHROUGH_INTENDED;
803
712
    case QL_OP_NOT_IN: {
804
712
      auto ql_type = QLType::CreateTypeList(operand1->ql_type());
805
806
712
      if (operand1->index_desc() != nullptr) {
807
        // Operand1 is a index column.
808
0
        sem_state->SetExprState(operand1->ql_type(),
809
0
                                operand1->internal_type(),
810
0
                                operand1->index_name(),
811
0
                                operand1->index_desc());
812
712
      } else if (operand1->expr_op() == ExprOperator::kRef) {
813
572
        const PTRef *ref = static_cast<const PTRef *>(operand1.get());
814
572
        sem_state->SetExprState(ql_type,
815
572
                                ref->internal_type(),
816
572
                                ref->bindvar_name(),
817
572
                                ref->desc());
818
140
      } else {
819
140
        sem_state->SetExprState(ql_type, operand1->internal_type());
820
140
      }
821
712
      break;
822
586
    }
823
824
0
    default:
825
0
      LOG(FATAL) << "Invalid operator" << int(ql_op_);
826
228k
  }
827
828
228k
  if (!sem_state->bindvar_name()) {
829
290
    sem_state->set_bindvar_name(PTBindVar::default_bindvar_name());
830
290
  }
831
832
228k
  return Status::OK();
833
228k
}
834
835
0
CHECKED_STATUS PTRelationExpr::SetupSemStateForOp3(SemState *sem_state) {
836
  // The states of operand3 is dependent on operand1 in the same way as op2.
837
0
  return SetupSemStateForOp2(sem_state);
838
0
}
839
840
109
CHECKED_STATUS PTRelationExpr::AnalyzeOperator(SemContext *sem_context) {
841
109
  switch (ql_op_) {
842
25
    case QL_OP_EXISTS: FALLTHROUGH_INTENDED;
843
109
    case QL_OP_NOT_EXISTS:
844
109
      return Status::OK();
845
0
    default:
846
0
      LOG(FATAL) << "Invalid operator";
847
109
  }
848
0
  return Status::OK();
849
109
}
850
851
CHECKED_STATUS PTRelationExpr::AnalyzeOperator(SemContext *sem_context,
852
0
                                               PTExpr::SharedPtr op1) {
853
  // "op1" must have been analyzed before getting here
854
0
  switch (ql_op_) {
855
0
    case QL_OP_IS_NULL: FALLTHROUGH_INTENDED;
856
0
    case QL_OP_IS_NOT_NULL:
857
0
      return sem_context->Error(this, "Operator not supported yet",
858
0
                                ErrorCode::CQL_STATEMENT_INVALID);
859
0
    default:
860
0
      LOG(FATAL) << "Invalid operator" << int(ql_op_);
861
0
  }
862
863
0
  return Status::OK();
864
0
}
865
866
CHECKED_STATUS PTRelationExpr::AnalyzeOperator(SemContext *sem_context,
867
                                               PTExpr::SharedPtr op1,
868
227k
                                               PTExpr::SharedPtr op2) {
869
  // "op1" and "op2" must have been analyzed before getting here
870
227k
  switch (ql_op_) {
871
542
    case QL_OP_NOT_EQUAL: FALLTHROUGH_INTENDED;
872
223k
    case QL_OP_EQUAL:
873
223k
      RETURN_NOT_OK(op1->CheckLhsExpr(sem_context));
874
223k
      RETURN_NOT_OK(op2->CheckRhsExpr(sem_context));
875
223k
      RETURN_NOT_OK(CheckEqualityOperands(sem_context, op1, op2));
876
223k
      internal_type_ = yb::InternalType::kBoolValue;
877
223k
      break;
878
895
    case QL_OP_LESS_THAN: FALLTHROUGH_INTENDED;
879
2.43k
    case QL_OP_GREATER_THAN: FALLTHROUGH_INTENDED;
880
2.80k
    case QL_OP_LESS_THAN_EQUAL: FALLTHROUGH_INTENDED;
881
3.25k
    case QL_OP_GREATER_THAN_EQUAL:
882
3.25k
      RETURN_NOT_OK(op1->CheckLhsExpr(sem_context));
883
3.25k
      RETURN_NOT_OK(op2->CheckRhsExpr(sem_context));
884
3.25k
      RETURN_NOT_OK(CheckInequalityOperands(sem_context, op1, op2));
885
3.24k
      internal_type_ = yb::InternalType::kBoolValue;
886
3.24k
      break;
887
888
584
    case QL_OP_IN:
889
708
    case QL_OP_NOT_IN:
890
708
      RETURN_NOT_OK(op1->CheckLhsExpr(sem_context));
891
700
      RETURN_NOT_OK(op2->CheckRhsExpr(sem_context));
892
      // For IN operator, we check compatibility between op1's type and op2's value_type.
893
700
      if (!sem_context->IsComparable(op1->ql_type_id(), op2->ql_type()->values_type()->main())) {
894
42
        return sem_context->Error(this, "Cannot compare values of these datatypes",
895
42
                                  ErrorCode::INCOMPARABLE_DATATYPES);
896
42
      }
897
658
      break;
898
899
0
    default:
900
0
      return sem_context->Error(this, "Operator not supported yet",
901
0
                                ErrorCode::CQL_STATEMENT_INVALID);
902
228k
  }
903
904
  // Collecting scan information if its state is set.
905
228k
  SelectScanInfo *scan_state = sem_context->scan_state();
906
228k
  if (scan_state != nullptr) {
907
    // Add reference to expressions and operators in WHERE clause for indexing analysis.
908
106k
    if (scan_state->analyze_where()) {
909
106k
      if (op1->index_desc()) {
910
0
        RETURN_NOT_OK(scan_state->AddWhereExpr(sem_context, this, op1->index_desc(), op2));
911
912
106k
      } else if (op1->expr_op() == ExprOperator::kRef) {
913
106k
        const PTRef *ref = static_cast<const PTRef *>(op1.get());
914
106k
        RETURN_NOT_OK(scan_state->AddWhereExpr(sem_context, this, ref->desc(), op2));
915
916
462
      } else if (op1->expr_op() == ExprOperator::kSubColRef) {
917
106
        const PTSubscriptedColumn *ref = static_cast<const PTSubscriptedColumn *>(op1.get());
918
106
        RETURN_NOT_OK(scan_state->AddWhereExpr(sem_context, this, ref->desc(), op2, ref->args()));
919
920
356
      } else if (op1->expr_op() == ExprOperator::kJsonOperatorRef) {
921
118
        const PTJsonColumnWithOperators *ref =
922
118
          static_cast<const PTJsonColumnWithOperators*>(op1.get());
923
118
        RETURN_NOT_OK(scan_state->AddWhereExpr(sem_context, this, ref->desc(), op2,
924
118
                                                  ref->operators()));
925
118
      }
926
106k
    }
927
928
    // Add filtering expressions in IF clause for indexing analysis.
929
106k
    if (scan_state->analyze_if()) {
930
206
      if (op1->index_desc() ||
931
206
          op1->expr_op() == ExprOperator::kRef ||
932
114
          op1->expr_op() == ExprOperator::kSubColRef ||
933
206
          op1->expr_op() == ExprOperator::kJsonOperatorRef) {
934
206
        RETURN_NOT_OK(scan_state->AddFilteringExpr(sem_context, this));
935
206
      }
936
206
    }
937
106k
  }
938
939
228k
  WhereExprState *where_state = sem_context->where_state();
940
228k
  if (where_state != nullptr) {
941
    // CheckLhsExpr already checks that this is either kRef or kBcall
942
121k
    DCHECK(op1->index_desc() != nullptr ||
943
121k
           op1->expr_op() == ExprOperator::kRef ||
944
121k
           op1->expr_op() == ExprOperator::kSubColRef ||
945
121k
           op1->expr_op() == ExprOperator::kJsonOperatorRef ||
946
121k
           op1->expr_op() == ExprOperator::kBcall);
947
121k
    if (op1->index_desc()) {
948
75
      return where_state->AnalyzeColumnOp(sem_context, this, op1->index_desc(), op2);
949
121k
    } else if (op1->expr_op() == ExprOperator::kRef) {
950
120k
      const PTRef *ref = static_cast<const PTRef *>(op1.get());
951
120k
      return where_state->AnalyzeColumnOp(sem_context, this, ref->desc(), op2);
952
469
    } else if (op1->expr_op() == ExprOperator::kSubColRef) {
953
176
      const PTSubscriptedColumn *ref = static_cast<const PTSubscriptedColumn *>(op1.get());
954
176
      return where_state->AnalyzeColumnOp(sem_context, this, ref->desc(), op2, ref->args());
955
293
    } else if (op1->expr_op() == ExprOperator::kJsonOperatorRef) {
956
76
      const PTJsonColumnWithOperators *ref =
957
76
          static_cast<const PTJsonColumnWithOperators*>(op1.get());
958
959
76
      return where_state->AnalyzeColumnOp(sem_context, this, ref->desc(), op2, ref->operators());
960
217
    } else if (op1->expr_op() == ExprOperator::kBcall) {
961
94
      const PTBcall *bcall = static_cast<const PTBcall *>(op1.get());
962
94
      if (strcmp(bcall->name()->c_str(), "token") == 0 ||
963
61
          strcmp(bcall->name()->c_str(), "partition_hash") == 0) {
964
48
        const PTToken *token = static_cast<const PTToken *>(bcall);
965
48
        if (token->is_partition_key_ref()) {
966
48
          return where_state->AnalyzePartitionKeyOp(sem_context, this, op2);
967
0
        } else {
968
0
          return sem_context->Error(this,
969
0
                                    "token/partition_hash calls need to reference partition key",
970
0
                                    ErrorCode::FEATURE_NOT_SUPPORTED);
971
0
        }
972
46
      } else if (strcmp(bcall->name()->c_str(), "ttl") == 0 ||
973
38
                 strcmp(bcall->name()->c_str(), "writetime") == 0 ||
974
46
                 strcmp(bcall->name()->c_str(), "cql_cast") == 0) {
975
46
        PTBcall::SharedPtr bcall_shared = std::make_shared<PTBcall>(*bcall);
976
46
        return where_state->AnalyzeColumnFunction(sem_context, this, op2, bcall_shared);
977
0
      } else {
978
0
        return sem_context->Error(loc(), "Builtin call not allowed in where clause",
979
0
                                  ErrorCode::CQL_STATEMENT_INVALID);
980
0
      }
981
107k
    }
982
121k
  }
983
984
107k
  if (sem_context->idx_predicate_state() != nullptr) {
985
180
    DCHECK(op1->index_desc() != nullptr ||
986
180
           op1->expr_op() == ExprOperator::kRef ||
987
180
           op1->expr_op() == ExprOperator::kSubColRef ||
988
180
           op1->expr_op() == ExprOperator::kJsonOperatorRef ||
989
180
           op1->expr_op() == ExprOperator::kBcall);
990
    // TODO(Piyush): Block mutable functions only. Allow all other functions.
991
992
    // Allow only expressions involving columns. Block subscripted/json col+operators.
993
180
    if (op1->expr_op() != ExprOperator::kRef) {
994
3
      return sem_context->Error(this,
995
3
        "Parital index where clause only allows operators on table columns",
996
3
        ErrorCode::FEATURE_NOT_SUPPORTED);
997
3
    }
998
107k
  }
999
1000
107k
  return Status::OK();
1001
107k
}
1002
1003
CHECKED_STATUS PTRelationExpr::AnalyzeOperator(SemContext *sem_context,
1004
                                               PTExpr::SharedPtr op1,
1005
                                               PTExpr::SharedPtr op2,
1006
0
                                               PTExpr::SharedPtr op3) {
1007
  // "op1", "op2", and "op3" must have been analyzed before getting here
1008
0
  switch (ql_op_) {
1009
0
    case QL_OP_BETWEEN: FALLTHROUGH_INTENDED;
1010
0
    case QL_OP_NOT_BETWEEN:
1011
0
      RETURN_NOT_OK(op1->CheckLhsExpr(sem_context));
1012
0
      RETURN_NOT_OK(op2->CheckRhsExpr(sem_context));
1013
0
      RETURN_NOT_OK(op3->CheckRhsExpr(sem_context));
1014
0
      RETURN_NOT_OK(CheckInequalityOperands(sem_context, op1, op2));
1015
0
      RETURN_NOT_OK(CheckInequalityOperands(sem_context, op1, op3));
1016
0
      internal_type_ = yb::InternalType::kBoolValue;
1017
0
      break;
1018
1019
0
    default:
1020
0
      LOG(FATAL) << "Invalid operator " << QLOperator_Name(ql_op_);
1021
0
  }
1022
1023
0
  return Status::OK();
1024
0
}
1025
1026
0
string PTRelationExpr::QLName(QLNameOption option) const {
1027
0
  switch (ql_op_) {
1028
0
    case QL_OP_NOOP:
1029
0
      return "NO OP";
1030
1031
    // Logic operators that take one operand.
1032
0
    case QL_OP_NOT:
1033
0
      return string("NOT ") + op1()->QLName(option);
1034
0
    case QL_OP_IS_TRUE:
1035
0
      return op1()->QLName(option) + "IS TRUE";
1036
0
    case QL_OP_IS_FALSE:
1037
0
      return op1()->QLName(option) + "IS FALSE";
1038
1039
      // Logic operators that take two or more operands.
1040
0
    case QL_OP_AND:
1041
0
      return op1()->QLName(option) + " AND " + op2()->QLName(option);
1042
0
    case QL_OP_OR:
1043
0
      return op1()->QLName(option) + " OR " + op2()->QLName(option);
1044
1045
      // Relation operators that take one operand.
1046
0
    case QL_OP_IS_NULL:
1047
0
      return op1()->QLName(option) + " IS NULL";
1048
0
    case QL_OP_IS_NOT_NULL:
1049
0
      return op1()->QLName(option) + " IS NOT NULL";
1050
1051
      // Relation operators that take two operands.
1052
0
    case QL_OP_EQUAL:
1053
0
      return op1()->QLName(option) + " == " + op2()->QLName(option);
1054
0
    case QL_OP_LESS_THAN:
1055
0
      return op1()->QLName(option) + " < " + op2()->QLName(option);
1056
0
    case QL_OP_LESS_THAN_EQUAL:
1057
0
      return op1()->QLName(option) + " <= " + op2()->QLName(option);
1058
0
    case QL_OP_GREATER_THAN:
1059
0
      return op1()->QLName(option) + " > " + op2()->QLName(option);
1060
0
    case QL_OP_GREATER_THAN_EQUAL:
1061
0
      return op1()->QLName(option) + " >= " + op2()->QLName(option);
1062
0
    case QL_OP_NOT_EQUAL:
1063
0
      return op1()->QLName(option) + " != " + op2()->QLName(option);
1064
1065
0
    case QL_OP_LIKE:
1066
0
      return op1()->QLName(option) + " LIKE " + op2()->QLName(option);
1067
0
    case QL_OP_NOT_LIKE:
1068
0
      return op1()->QLName(option) + " NOT LIKE " +
1069
0
          op2()->QLName(option);
1070
0
    case QL_OP_IN:
1071
0
      return op1()->QLName(option) + " IN " + op2()->QLName(option);
1072
0
    case QL_OP_NOT_IN:
1073
0
      return op1()->QLName(option) + " NOT IN " + op2()->QLName(option);
1074
1075
    // Relation operators that take three operands.
1076
0
    case QL_OP_BETWEEN:
1077
0
      return op1()->QLName(option) + " BETWEEN " +
1078
0
          op2()->QLName(option) + " AND " +
1079
0
          op3()->QLName(option);
1080
0
    case QL_OP_NOT_BETWEEN:
1081
0
      return op1()->QLName(option) + " NOT BETWEEN " +
1082
0
          op2()->QLName(option) + " AND " +
1083
0
          op3()->QLName(option);
1084
1085
    // Operators that take no operand. For use in "if" clause only currently.
1086
0
    case QL_OP_EXISTS:
1087
0
      return "EXISTS";
1088
0
    case QL_OP_NOT_EXISTS:
1089
0
      return "NOT EXISTS";
1090
0
  }
1091
1092
0
  return "expr";
1093
0
}
1094
1095
50
const ColumnDesc *PTExpr::GetColumnDesc(const SemContext *sem_context) {
1096
50
  MCString expr_name(MangledName().c_str(), sem_context->PTempMem());
1097
50
  return GetColumnDesc(sem_context, expr_name, sem_context->current_dml_stmt());
1098
50
}
1099
1100
const ColumnDesc *PTExpr::GetColumnDesc(const SemContext *sem_context,
1101
614k
                                        const MCString& col_name) const {
1102
614k
  if (sem_context->selecting_from_index()) {
1103
    // Mangle column name when selecting from IndexTable.
1104
3.62k
    MCString mangled_name(YcqlName::MangleColumnName(col_name.c_str()).c_str(),
1105
3.62k
                          sem_context->PTempMem());
1106
3.62k
    return GetColumnDesc(sem_context, mangled_name, sem_context->current_dml_stmt());
1107
3.62k
  }
1108
1109
610k
  return GetColumnDesc(sem_context, col_name, sem_context->current_dml_stmt());
1110
610k
}
1111
1112
const ColumnDesc *PTExpr::GetColumnDesc(const SemContext *sem_context,
1113
                                        const MCString& desc_name,
1114
614k
                                        PTDmlStmt *stmt) const {
1115
614k
  SelectScanInfo *scan_state = sem_context->scan_state();
1116
614k
  if (scan_state) {
1117
    // Get column from scan_state when analyze index for scanning.
1118
107k
    return scan_state->GetColumnDesc(sem_context, desc_name);
1119
107k
  }
1120
1121
507k
  if (stmt) {
1122
    // Get column from DML statement when compiling a DML statement.
1123
505k
    return stmt->GetColumnDesc(sem_context, desc_name);
1124
505k
  }
1125
1126
  // Get column from symbol table in context.
1127
2.46k
  return sem_context->GetColumnDesc(desc_name);
1128
2.46k
}
1129
1130
//--------------------------------------------------------------------------------------------------
1131
1132
4.92k
CHECKED_STATUS PTOperatorExpr::SetupSemStateForOp1(SemState *sem_state) {
1133
4.92k
  switch (op_) {
1134
4.92k
    case ExprOperator::kUMinus:
1135
4.92k
    case ExprOperator::kAlias:
1136
4.92k
      sem_state->CopyPreviousStates();
1137
4.92k
      break;
1138
1139
0
    default:
1140
0
      LOG(FATAL) << "Invalid operator " << int(op_);
1141
4.92k
  }
1142
1143
4.92k
  return Status::OK();
1144
4.92k
}
1145
1146
CHECKED_STATUS PTOperatorExpr::AnalyzeOperator(SemContext *sem_context,
1147
4.92k
                                               PTExpr::SharedPtr op1) {
1148
4.92k
  switch (op_) {
1149
4.92k
    case ExprOperator::kUMinus:
1150
      // "op1" must have been analyzed before we get here.
1151
      // Check to make sure that it is allowed in this context.
1152
4.92k
      if (op1->expr_op() != ExprOperator::kConst) {
1153
4
        return sem_context->Error(this, "Only numeric constant is allowed in this context",
1154
4
                                  ErrorCode::FEATURE_NOT_SUPPORTED);
1155
4
      }
1156
4.91k
      if (!QLType::IsNumeric(op1->ql_type_id())) {
1157
0
        return sem_context->Error(this, "Only numeric data type is allowed in this context",
1158
0
                                  ErrorCode::INVALID_DATATYPE);
1159
0
      }
1160
1161
      // Type resolution: (-x) should have the same datatype as (x).
1162
4.91k
      ql_type_ = op1->ql_type();
1163
4.91k
      internal_type_ = op1->internal_type();
1164
4.91k
      break;
1165
1166
0
    default:
1167
0
      LOG(FATAL) << "Invalid operator" << int(op_);
1168
4.92k
  }
1169
1170
4.91k
  return Status::OK();
1171
4.92k
}
1172
1173
//--------------------------------------------------------------------------------------------------
1174
1175
PTRef::PTRef(MemoryContext *memctx,
1176
             YBLocation::SharedPtr loc,
1177
             const PTQualifiedName::SharedPtr& name)
1178
    : PTOperator0(memctx, loc, ExprOperator::kRef, yb::QLOperator::QL_OP_NOOP),
1179
      name_(name),
1180
505k
      desc_(nullptr) {
1181
505k
}
1182
1183
503k
PTRef::~PTRef() {
1184
503k
}
1185
1186
792k
std::string PTRef::QLName(QLNameOption option) const {
1187
792k
  if (option == QLNameOption::kMetadataName) {
1188
    // Should only be called after the descriptor is loaded from the catalog by Analyze().
1189
0
    CHECK(desc_) << "Metadata is not yet loaded to this node";
1190
316
    return desc_->MetadataName();
1191
316
  }
1192
1193
791k
  if (option == QLNameOption::kMangledName) {
1194
16.0k
    return YcqlName::MangleColumnName(name_->QLName());
1195
16.0k
  }
1196
1197
775k
  return name_->QLName();
1198
775k
}
1199
1200
226k
const MCSharedPtr<MCString>& PTRef::bindvar_name() const {
1201
226k
  return name_->bindvar_name();
1202
226k
}
1203
1204
613k
CHECKED_STATUS PTRef::AnalyzeOperator(SemContext *sem_context) {
1205
18.4E
  DCHECK(name_ != nullptr) << "Reference column is not specified";
1206
1207
  // Look for a column descriptor from symbol table.
1208
613k
  RETURN_NOT_OK(name_->Analyze(sem_context));
1209
613k
  if (!name_->IsSimpleName()) {
1210
3
    return sem_context->Error(this, "Qualified name not allowed for column reference",
1211
3
                              ErrorCode::SQL_STATEMENT_INVALID);
1212
3
  }
1213
613k
  desc_ = GetColumnDesc(sem_context, name_->last_name());
1214
613k
  if (desc_ == nullptr) {
1215
    // If this is a nested select from an uncovered index/partial index,
1216
    // ignore column that is uncovered/only in partial index predicate and not in index cols.
1217
106
    LOG(INFO) << "Column " << name_->last_name() << " not found";
1218
106
    return sem_context->IsUncoveredIndexSelect() || sem_context->IsPartialIndexSelect()
1219
80
        ? Status::OK()
1220
26
        : sem_context->Error(this, "Column doesn't exist", ErrorCode::UNDEFINED_COLUMN);
1221
106
  }
1222
1223
  // Type resolution: Ref(x) should have the same datatype as (x).
1224
612k
  internal_type_ = desc_->internal_type();
1225
612k
  ql_type_ = desc_->ql_type();
1226
612k
  return Status::OK();
1227
612k
}
1228
1229
227k
CHECKED_STATUS PTRef::CheckLhsExpr(SemContext *sem_context) {
1230
  // When CQL IF clause is being processed. In that case, disallow reference to primary key columns
1231
  // and counters. No error checking is needed when processing SELECT against INDEX table because
1232
  // we already check it against the UserTable.
1233
227k
  if (sem_context->processing_if_clause() && !sem_context->selecting_from_index()) {
1234
163
    if (desc_->is_primary() && !sem_context->void_primary_key_condition()) {
1235
15
      return sem_context->Error(this, "Primary key column reference is not allowed in if clause",
1236
15
                                ErrorCode::CQL_STATEMENT_INVALID);
1237
15
    }
1238
148
    if (desc_->is_counter()) {
1239
2
      return sem_context->Error(this, "Counter column reference is not allowed in if clause",
1240
2
                                ErrorCode::CQL_STATEMENT_INVALID);
1241
2
    }
1242
227k
  }
1243
1244
  // Only hash/static columns are supported in the where clause of SELECT DISTINCT.
1245
227k
  if (sem_context->where_state() != nullptr) {
1246
120k
    const PTDmlStmt *dml = sem_context->current_dml_stmt();
1247
120k
    if (dml != nullptr && dml->opcode() == TreeNodeOpcode::kPTSelectStmt &&
1248
106k
        down_cast<const PTSelectStmt*>(dml)->distinct() &&
1249
20
        !desc_->is_hash() && !desc_->is_static()) {
1250
3
      return sem_context->Error(this,
1251
3
                                "Non-partition/static column reference is not supported in the "
1252
3
                                "where clause of a SELECT DISTINCT statement",
1253
3
                                ErrorCode::CQL_STATEMENT_INVALID);
1254
3
    }
1255
227k
  }
1256
1257
227k
  return Status::OK();
1258
227k
}
1259
1260
0
void PTRef::PrintSemanticAnalysisResult(SemContext *sem_context) {
1261
0
  VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail";
1262
0
}
1263
1264
PTJsonOperator::PTJsonOperator(MemoryContext *memctx,
1265
                               YBLocation::SharedPtr loc,
1266
                               const JsonOperator& json_operator,
1267
                               const PTExpr::SharedPtr& arg)
1268
    : PTExpr(memctx, loc, ExprOperator::kJsonOperatorRef, yb::QLOperator::QL_OP_NOOP,
1269
             InternalType::kJsonbValue, DataType::JSONB),
1270
      json_operator_(json_operator),
1271
1.61k
      arg_(arg) {
1272
1.61k
}
1273
1274
1.55k
PTJsonOperator::~PTJsonOperator() {
1275
1.55k
}
1276
1277
1.93k
Status PTJsonOperator::Analyze(SemContext *sem_context) {
1278
1.93k
  return arg_->Analyze(sem_context);
1279
1.93k
}
1280
1281
//--------------------------------------------------------------------------------------------------
1282
1283
PTJsonColumnWithOperators::PTJsonColumnWithOperators(MemoryContext *memctx,
1284
                                                     YBLocation::SharedPtr loc,
1285
                                                     const PTQualifiedName::SharedPtr& name,
1286
                                                     const PTExprListNode::SharedPtr& operators)
1287
    : PTOperator0(memctx, loc, ExprOperator::kJsonOperatorRef, yb::QLOperator::QL_OP_NOOP),
1288
      name_(name),
1289
860
      operators_(operators) {
1290
860
}
1291
1292
854
PTJsonColumnWithOperators::~PTJsonColumnWithOperators() {
1293
854
}
1294
1295
1.06k
CHECKED_STATUS PTJsonColumnWithOperators::AnalyzeOperator(SemContext *sem_context) {
1296
  // Look for a column descriptor from symbol table.
1297
1.06k
  RETURN_NOT_OK(name_->Analyze(sem_context));
1298
1.06k
  desc_ = GetColumnDesc(sem_context, name_->last_name());
1299
1.06k
  if (desc_ == nullptr) {
1300
    // If this is a nested select from an uncovered index, ignore column that is uncovered.
1301
3
    return sem_context->IsUncoveredIndexSelect()
1302
2
        ? Status::OK()
1303
1
        : sem_context->Error(this, "Column doesn't exist", ErrorCode::UNDEFINED_COLUMN);
1304
3
  }
1305
1306
1.06k
  SemState sem_state(sem_context);
1307
1308
1.06k
  if (!desc_->ql_type()->IsJson()) {
1309
2
    return sem_context->Error(this, "Column provided is not json data type",
1310
2
                              ErrorCode::CQL_STATEMENT_INVALID);
1311
2
  }
1312
1313
1.06k
  if (operators_->size() == 0) {
1314
0
    return sem_context->Error(this, "No operators provided.",
1315
0
                              ErrorCode::CQL_STATEMENT_INVALID);
1316
0
  }
1317
1318
  // Analyze each operator.
1319
1.06k
  RETURN_NOT_OK(operators_->Analyze(sem_context));
1320
1321
  // Check the last operator to determine type.
1322
1.06k
  auto json_operator = std::dynamic_pointer_cast<PTJsonOperator>(
1323
1.06k
      operators_->node_list().back())->json_operator();
1324
1325
1.06k
  if (json_operator == JsonOperator::JSON_OBJECT) {
1326
142
    ql_type_ = QLType::Create(DataType::JSONB);
1327
142
    internal_type_ = InternalType::kJsonbValue;
1328
921
  } else if (json_operator == JsonOperator::JSON_TEXT) {
1329
921
    ql_type_ = QLType::Create(DataType::STRING);
1330
921
    internal_type_ = InternalType::kStringValue;
1331
0
  } else {
1332
0
    return sem_context->Error(this, "Invalid operator.",
1333
0
                              ErrorCode::CQL_STATEMENT_INVALID);
1334
0
  }
1335
1336
1.06k
  return Status::OK();
1337
1.06k
}
1338
1339
406
CHECKED_STATUS PTJsonColumnWithOperators::CheckLhsExpr(SemContext *sem_context) {
1340
406
  return Status::OK();
1341
406
}
1342
1343
1.95k
std::string PTJsonColumnWithOperators::QLName(QLNameOption option) const {
1344
1.95k
  string qlname;
1345
1.95k
  if (option == QLNameOption::kMetadataName) {
1346
0
    DCHECK(desc_) << "Metadata is not yet loaded to this node";
1347
0
    qlname = desc_->MetadataName();
1348
1.95k
  } else if (option == QLNameOption::kMangledName) {
1349
744
    qlname = YcqlName::MangleColumnName(name_->QLName());
1350
1.20k
  } else {
1351
1.20k
    qlname = name_->QLName();
1352
1.20k
  }
1353
1354
2.87k
  for (PTExpr::SharedPtr expr : operators_->node_list()) {
1355
2.87k
    qlname += expr->QLName(option);
1356
2.87k
  }
1357
1.95k
  return qlname;
1358
1.95k
}
1359
1360
//--------------------------------------------------------------------------------------------------
1361
1362
PTSubscriptedColumn::PTSubscriptedColumn(MemoryContext *memctx,
1363
                                         YBLocation::SharedPtr loc,
1364
                                         const PTQualifiedName::SharedPtr& name,
1365
                                         const PTExprListNode::SharedPtr& args)
1366
    : PTOperator0(memctx, loc, ExprOperator::kSubColRef, yb::QLOperator::QL_OP_NOOP),
1367
      name_(name),
1368
      args_(args),
1369
201
      desc_(nullptr) {
1370
201
}
1371
1372
158
PTSubscriptedColumn::~PTSubscriptedColumn() {
1373
158
}
1374
1375
425
CHECKED_STATUS PTSubscriptedColumn::AnalyzeOperator(SemContext *sem_context) {
1376
1377
  // Check if this refers to the whole table (SELECT *).
1378
425
  if (name_ == nullptr) {
1379
0
    return sem_context->Error(this, "Cannot do type resolution for wildcard reference (SELECT *)",
1380
0
                              ErrorCode::SQL_STATEMENT_INVALID);
1381
0
  }
1382
1383
  // Look for a column descriptor from symbol table.
1384
425
  RETURN_NOT_OK(name_->Analyze(sem_context));
1385
425
  desc_ = GetColumnDesc(sem_context, name_->last_name());
1386
425
  if (desc_ == nullptr) {
1387
    // If this is a nested select from an uncovered index, ignore column that is uncovered.
1388
72
    return sem_context->IsUncoveredIndexSelect()
1389
72
        ? Status::OK()
1390
0
        : sem_context->Error(this, "Column doesn't exist", ErrorCode::UNDEFINED_COLUMN);
1391
72
  }
1392
1393
353
  SemState sem_state(sem_context);
1394
1395
353
  auto curr_ytype = desc_->ql_type();
1396
353
  auto curr_itype = desc_->internal_type();
1397
1398
353
  if (args_ != nullptr) {
1399
353
    for (const auto &arg : args_->node_list()) {
1400
353
      if (curr_ytype->keys_type() == nullptr) {
1401
8
        return sem_context->Error(this, "Columns with elementary types cannot take arguments",
1402
8
                                  ErrorCode::CQL_STATEMENT_INVALID);
1403
8
      }
1404
1405
345
      sem_state.SetExprState(curr_ytype->keys_type(),
1406
345
                             client::YBColumnSchema::ToInternalDataType(curr_ytype->keys_type()));
1407
345
      RETURN_NOT_OK(arg->Analyze(sem_context));
1408
1409
345
      curr_ytype = curr_ytype->values_type();
1410
345
      curr_itype = client::YBColumnSchema::ToInternalDataType(curr_ytype);
1411
345
    }
1412
353
  }
1413
1414
  // Type resolution: Ref(x) should have the same datatype as (x).
1415
345
  ql_type_ = curr_ytype;
1416
345
  internal_type_ = curr_itype;
1417
1418
345
  return Status::OK();
1419
353
}
1420
1421
0
const MCSharedPtr<MCString>& PTSubscriptedColumn::bindvar_name() const {
1422
0
  return name_->bindvar_name();
1423
0
}
1424
1425
409
CHECKED_STATUS PTSubscriptedColumn::CheckLhsExpr(SemContext *sem_context) {
1426
  // If where_state is null, we are processing the IF clause. In that case, disallow reference to
1427
  // primary key columns.
1428
409
  if (sem_context->where_state() == nullptr &&
1429
233
      desc_->is_primary() && !sem_context->void_primary_key_condition()) {
1430
0
    return sem_context->Error(this, "Primary key column reference is not allowed in if expression",
1431
0
                              ErrorCode::CQL_STATEMENT_INVALID);
1432
0
  }
1433
409
  return Status::OK();
1434
409
}
1435
1436
0
void PTSubscriptedColumn::PrintSemanticAnalysisResult(SemContext *sem_context) {
1437
0
  VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail";
1438
0
}
1439
1440
//--------------------------------------------------------------------------------------------------
1441
1442
PTAllColumns::PTAllColumns(MemoryContext *memctx, YBLocation::SharedPtr loc)
1443
    : PTOperator0(memctx, loc, ExprOperator::kRef, yb::QLOperator::QL_OP_NOOP),
1444
157k
      columns_(memctx) {
1445
157k
}
1446
1447
158k
PTAllColumns::~PTAllColumns() {
1448
158k
}
1449
1450
155k
CHECKED_STATUS PTAllColumns::AnalyzeOperator(SemContext *sem_context) {
1451
  // Make sure '*' is used only in 'SELECT *' statement.
1452
155k
  const PTDmlStmt *stmt = sem_context->current_dml_stmt();
1453
155k
  if (stmt == nullptr ||
1454
155k
      stmt->opcode() != TreeNodeOpcode::kPTSelectStmt ||
1455
155k
      static_cast<const PTSelectStmt*>(stmt)->selected_exprs().size() > 1) {
1456
0
    return sem_context->Error(loc(), "Cannot use '*' expression in this context",
1457
0
                              ErrorCode::CQL_STATEMENT_INVALID);
1458
0
  }
1459
1460
155k
  const auto* select_stmt = static_cast<const PTSelectStmt*>(stmt);
1461
155k
  columns_.clear();
1462
155k
  columns_.reserve(select_stmt->column_map().size());
1463
1.72M
  for (const auto& pair : select_stmt->column_map()) {
1464
1.72M
    columns_.emplace_back(pair.second);
1465
1.72M
  }
1466
1467
  // For 'select * ... ' using index only, sort them in the same order as the table columns so that
1468
  // the selected columns are returned in the proper order.
1469
155k
  if (select_stmt->table()->IsIndex()) {
1470
95
    MCUnorderedMap<int, int> map(sem_context->PTempMem()); // Map of column_id -> indexed_column_id
1471
226
    for (const auto& column : select_stmt->table()->index_info().columns()) {
1472
226
      map.emplace(column.column_id, column.indexed_column_id);
1473
226
    }
1474
95
    std::sort(columns_.begin(), columns_.end(),
1475
150
              [&map](const ColumnDesc& a, const ColumnDesc& b) {
1476
150
                return map[a.id()] < map[b.id()];
1477
150
              });
1478
155k
  } else {
1479
155k
    std::sort(columns_.begin(), columns_.end(),
1480
5.17M
              [](const ColumnDesc& a, const ColumnDesc& b) {
1481
5.17M
                return a.id() < b.id();
1482
5.17M
              });
1483
155k
  }
1484
1485
  // Note to server that all column are referenced by this statement.
1486
155k
  sem_context->current_dml_stmt()->AddRefForAllColumns();
1487
1488
  // TODO(Mihnea) See if TUPLE datatype can be used here.
1489
  // '*' should be of TUPLE type, but we use the following workaround for now.
1490
155k
  ql_type_ = QLType::Create(DataType::NULL_VALUE_TYPE);
1491
155k
  internal_type_ = InternalType::kListValue;
1492
155k
  return Status::OK();
1493
155k
}
1494
1495
//--------------------------------------------------------------------------------------------------
1496
1497
PTExprAlias::PTExprAlias(MemoryContext *memctx,
1498
                         YBLocation::SharedPtr loc,
1499
                         const PTExpr::SharedPtr& expr,
1500
                         const MCSharedPtr<MCString>& alias)
1501
    : PTOperator1(memctx, loc, ExprOperator::kAlias, yb::QLOperator::QL_OP_NOOP, expr),
1502
2
      alias_(alias) {
1503
2
}
1504
1505
2
PTExprAlias::~PTExprAlias() {
1506
2
}
1507
1508
2
CHECKED_STATUS PTExprAlias::SetupSemStateForOp1(SemState *sem_state) {
1509
2
  sem_state->set_allowing_aggregate(sem_state->previous_state()->allowing_aggregate());
1510
2
  return Status::OK();
1511
2
}
1512
1513
2
CHECKED_STATUS PTExprAlias::AnalyzeOperator(SemContext *sem_context, PTExpr::SharedPtr op1) {
1514
  // Type resolution: Alias of (x) should have the same datatype as (x).
1515
2
  ql_type_ = op1->ql_type();
1516
2
  internal_type_ = op1->internal_type();
1517
2
  return Status::OK();
1518
2
}
1519
1520
//--------------------------------------------------------------------------------------------------
1521
1522
PTBindVar::PTBindVar(MemoryContext *memctx,
1523
                     YBLocation::SharedPtr loc,
1524
                     const MCSharedPtr<MCString>& name)
1525
    : PTExpr(memctx, loc, ExprOperator::kBindVar),
1526
14.3k
      name_(name) {
1527
14.3k
}
1528
1529
PTBindVar::PTBindVar(MemoryContext *memctx,
1530
                     YBLocation::SharedPtr loc,
1531
                     PTConstVarInt::SharedPtr user_pos)
1532
    : PTExpr(memctx, loc, ExprOperator::kBindVar),
1533
24
      user_pos_(user_pos) {
1534
24
}
1535
1536
9.52k
PTBindVar::~PTBindVar() {
1537
9.52k
}
1538
1539
16.2k
CHECKED_STATUS PTBindVar::Analyze(SemContext *sem_context) {
1540
  // Before traversing the expression, check if this whole expression is actually a column.
1541
16.2k
  if (CheckIndexColumn(sem_context)) {
1542
0
    return Status::OK();
1543
0
  }
1544
1545
16.2k
  RETURN_NOT_OK(CheckOperator(sem_context));
1546
1547
16.2k
  if (name_ == nullptr) {
1548
13.7k
    name_ = sem_context->bindvar_name();
1549
13.7k
  }
1550
1551
16.2k
  if (user_pos_ != nullptr) {
1552
21
    int64_t pos = 0;
1553
21
    if (!user_pos_->ToInt64(&pos, false).ok()) {
1554
1
      return sem_context->Error(this, "Bind position is invalid!",
1555
1
                                ErrorCode::INVALID_ARGUMENTS);
1556
1
    }
1557
1558
20
    if (pos <= 0) {
1559
1
      return sem_context->Error(this, "Bind variable position should be positive!",
1560
1
                                ErrorCode::INVALID_ARGUMENTS);
1561
1
    }
1562
    // Convert from 1 based to 0 based.
1563
19
    set_pos(pos - 1);
1564
19
  }
1565
1566
16.2k
  if (sem_context->expr_expected_ql_type()->main() == DataType::UNKNOWN_DATA) {
1567
    // By default bind variables are compatible with any type.
1568
37
    ql_type_ = QLType::Create(NULL_VALUE_TYPE);
1569
16.2k
  } else {
1570
16.2k
    ql_type_ = sem_context->expr_expected_ql_type();
1571
16.2k
  }
1572
1573
16.2k
  internal_type_ = sem_context->expr_expected_internal_type();
1574
16.2k
  expected_internal_type_ = internal_type_;
1575
16.2k
  hash_col_ = sem_context->hash_col();
1576
16.2k
  if (hash_col_ != nullptr) {
1577
7.19k
    DCHECK(sem_context->current_dml_stmt() != nullptr);
1578
7.19k
    sem_context->current_dml_stmt()->AddHashColumnBindVar(this);
1579
7.19k
  }
1580
1581
16.2k
  return Status::OK();
1582
16.2k
}
1583
1584
0
void PTBindVar::PrintSemanticAnalysisResult(SemContext *sem_context) {
1585
0
  VLOG(3) << "SEMANTIC ANALYSIS RESULT (" << *loc_ << "):\n" << "Not yet avail";
1586
0
}
1587
1588
28
std::string PTBindVar::bcall_arg_bindvar_name(const std::string& bcall_name, size_t arg_position) {
1589
28
  return strings::Substitute("arg$0(system.$1)", arg_position, bcall_name);
1590
28
}
1591
1592
// The name Cassandra uses for binding the collection elements.
1593
221
std::string PTBindVar::coll_bindvar_name(const std::string& col_name) {
1594
221
  return strings::Substitute("value($0)", col_name);
1595
221
}
1596
1597
// The name for binding the JSON attributes.
1598
341
std::string PTBindVar::json_bindvar_name(const std::string& col_name) {
1599
341
  return strings::Substitute("json_attr($0)", col_name);
1600
341
}
1601
1602
}  // namespace ql
1603
}  // namespace yb