YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/common/ql_expr.cc
Line
Count
Source (jump to first uncovered line)
1
//--------------------------------------------------------------------------------------------------
2
// Copyright (c) YugaByte, Inc.
3
//--------------------------------------------------------------------------------------------------
4
5
#include "yb/common/ql_expr.h"
6
7
#include "yb/common/jsonb.h"
8
#include "yb/common/pgsql_protocol.pb.h"
9
#include "yb/common/ql_bfunc.h"
10
#include "yb/common/ql_value.h"
11
#include "yb/common/schema.h"
12
13
#include "yb/util/result.h"
14
15
namespace yb {
16
17
namespace {
18
19
constexpr size_t kInvalidIndex = std::numeric_limits<size_t>::max();
20
21
}
22
23
6.73M
bfql::TSOpcode QLExprExecutor::GetTSWriteInstruction(const QLExpressionPB& ql_expr) const {
24
  // "kSubDocInsert" instructs the tablet server to insert a new value or replace an existing value.
25
6.73M
  if (ql_expr.has_tscall()) {
26
48
    return static_cast<bfql::TSOpcode>(ql_expr.tscall().opcode());
27
48
  }
28
6.73M
  return bfql::TSOpcode::kScalarInsert;
29
6.73M
}
30
31
//--------------------------------------------------------------------------------------------------
32
33
CHECKED_STATUS QLExprExecutor::EvalExpr(const QLExpressionPB& ql_expr,
34
                                        const QLTableRow& table_row,
35
                                        QLExprResultWriter result_writer,
36
54.3M
                                        const Schema *schema) {
37
54.3M
  switch (ql_expr.expr_case()) {
38
7.86M
    case QLExpressionPB::ExprCase::kValue:
39
7.86M
      result_writer.SetExisting(&ql_expr.value());
40
7.86M
      break;
41
42
46.3M
    case QLExpressionPB::ExprCase::kColumnId:
43
46.3M
      RETURN_NOT_OK(table_row.ReadColumn(ql_expr.column_id(), result_writer));
44
46.3M
      break;
45
46
46.3M
    case QLExpressionPB::ExprCase::kJsonColumn: {
47
18.2k
      QLExprResult temp;
48
18.2k
      const QLJsonColumnOperationsPB& json_ops = ql_expr.json_column();
49
18.2k
      RETURN_NOT_OK(table_row.ReadColumn(json_ops.column_id(), temp.Writer()));
50
18.2k
      if (temp.IsNull()) {
51
217
        result_writer.SetNull();
52
18.0k
      } else {
53
18.0k
        common::Jsonb jsonb;
54
18.0k
        temp.MoveToJsonb(&jsonb);
55
18.0k
        RETURN_NOT_OK(jsonb.ApplyJsonbOperators(json_ops, &result_writer.NewValue()));
56
18.0k
      }
57
18.2k
      break;
58
18.2k
    }
59
60
18.2k
    case QLExpressionPB::ExprCase::kSubscriptedCol:
61
194
      if (table_row.IsEmpty()) {
62
0
        result_writer.SetNull();
63
194
      } else {
64
194
        QLExprResult index_arg;
65
194
        const QLSubscriptedColPB& subcol = ql_expr.subscripted_col();
66
194
        RETURN_NOT_OK(EvalExpr(subcol.subscript_args(0), table_row, index_arg.Writer()));
67
194
        RETURN_NOT_OK(table_row.ReadSubscriptedColumn(subcol, index_arg.Value(), result_writer));
68
194
      }
69
194
      break;
70
71
728
    case QLExpressionPB::ExprCase::kBfcall:
72
728
      return EvalBFCall(ql_expr.bfcall(), table_row, &result_writer.NewValue());
73
74
20.7k
    case QLExpressionPB::ExprCase::kTscall:
75
20.7k
      return EvalTSCall(ql_expr.tscall(), table_row, &result_writer.NewValue(), schema);
76
77
0
    case QLExpressionPB::ExprCase::kCondition:
78
0
      return EvalCondition(ql_expr.condition(), table_row, &result_writer.NewValue());
79
80
0
    case QLExpressionPB::ExprCase::kBocall: FALLTHROUGH_INTENDED;
81
0
    case QLExpressionPB::ExprCase::kBindId: FALLTHROUGH_INTENDED;
82
1
    case QLExpressionPB::ExprCase::EXPR_NOT_SET:
83
1
      result_writer.SetNull();
84
54.3M
  }
85
54.2M
  return Status::OK();
86
54.3M
}
87
88
//--------------------------------------------------------------------------------------------------
89
90
CHECKED_STATUS QLExprExecutor::EvalExpr(QLExpressionPB* ql_expr,
91
                                        const QLTableRow& table_row,
92
11.2M
                                        const Schema *schema) {
93
11.2M
  if (!ql_expr->has_value()) {
94
22
    QLExprResult temp;
95
22
    RETURN_NOT_OK(EvalExpr(*ql_expr, table_row, temp.Writer(), schema));
96
22
    temp.MoveTo(ql_expr->mutable_value());
97
22
  }
98
11.2M
  return Status::OK();
99
11.2M
}
100
101
CHECKED_STATUS QLExprExecutor::EvalExpr(const PgsqlExpressionPB& ql_expr,
102
                                        const QLTableRow& table_row,
103
                                        QLExprResultWriter result_writer,
104
707M
                                        const Schema *schema) {
105
707M
  return EvalExpr(ql_expr, &table_row, result_writer, schema);
106
707M
}
107
108
//--------------------------------------------------------------------------------------------------
109
110
CHECKED_STATUS QLExprExecutor::ReadExprValue(const QLExpressionPB& ql_expr,
111
                                             const QLTableRow& table_row,
112
0
                                             QLExprResultWriter result_writer) {
113
0
  if (ql_expr.expr_case() == QLExpressionPB::ExprCase::kTscall) {
114
0
    return ReadTSCallValue(ql_expr.tscall(), table_row, result_writer);
115
0
  } else {
116
0
    return EvalExpr(ql_expr, table_row, result_writer);
117
0
  }
118
0
}
119
120
//--------------------------------------------------------------------------------------------------
121
122
CHECKED_STATUS QLExprExecutor::EvalBFCall(const QLBCallPB& bfcall,
123
                                          const QLTableRow& table_row,
124
728
                                          QLValue *result) {
125
  // TODO(neil)
126
  // - Use TSOpode for collection expression if only TabletServer can execute.
127
  // OR
128
  // - Introduce BuiltinOperator in addition to builtin function. Use builtin operators for all
129
  //   special operations including collection operations. That way, we don't need special cases.
130
131
  // Special cases: for collection operations of the form "cref = cref +/- <value>" we avoid
132
  // reading column cref and instead tell doc writer to modify it in-place.
133
  //   "AddMapMap"
134
  //   "AddSetSet"
135
  //   "SubMapSet"
136
  //   "SubSetSet"
137
  //   "AddListList"
138
  //   "SubListList"
139
140
728
  const bfql::BFOpcode bf_opcode = static_cast<bfql::BFOpcode>(bfcall.opcode());
141
  // First evaluate the arguments.
142
728
  vector<QLValue> args(bfcall.operands().size());
143
728
  int arg_index = 0;
144
728
  QLExprResult temp;
145
787
  for (auto operand : bfcall.operands()) {
146
787
    RETURN_NOT_OK(EvalExpr(operand, table_row, temp.Writer()));
147
783
    temp.MoveTo(args[arg_index++].mutable_value());
148
783
  }
149
150
  // Execute the builtin call associated with the given opcode.
151
724
  return QLBfunc::Exec(bf_opcode, &args, result);
152
728
}
153
154
//--------------------------------------------------------------------------------------------------
155
156
CHECKED_STATUS QLExprExecutor::EvalTSCall(const QLBCallPB& ql_expr,
157
                                          const QLTableRow& table_row,
158
                                          QLValue *result,
159
0
                                          const Schema *schema) {
160
0
  result->SetNull();
161
0
  return STATUS(RuntimeError, "Only tablet server can execute this operator");
162
0
}
163
164
CHECKED_STATUS QLExprExecutor::ReadTSCallValue(const QLBCallPB& ql_expr,
165
                                               const QLTableRow& table_row,
166
0
                                               QLExprResultWriter result_writer) {
167
0
  result_writer.SetNull();
168
0
  return STATUS(RuntimeError, "Only tablet server can execute this operator");
169
0
}
170
171
//--------------------------------------------------------------------------------------------------
172
173
CHECKED_STATUS QLExprExecutor::EvalCondition(const QLConditionPB& condition,
174
                                             const QLTableRow& table_row,
175
670k
                                             bool* result) {
176
670k
  QLValue result_pb;
177
670k
  RETURN_NOT_OK(EvalCondition(condition, table_row, &result_pb));
178
670k
  *result = result_pb.bool_value();
179
670k
  return Status::OK();
180
670k
}
181
182
template <class Operands>
183
Result<bool> In(
184
933
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row) {
185
933
  QLExprResult left, right;
186
933
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
187
188
2.38k
  
for (const QLValuePB& elem : right.Value().list_value().elems())933
{
189
2.38k
    if (!Comparable(elem, left.Value())) {
190
0
       return STATUS(RuntimeError, "values not comparable");
191
0
    }
192
2.38k
    if (elem == left.Value()) {
193
784
      return true;
194
784
    }
195
2.38k
  }
196
197
149
  return false;
198
933
}
yb::Result<bool> yb::In<google::protobuf::RepeatedPtrField<yb::QLExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&)
Line
Count
Source
184
933
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row) {
185
933
  QLExprResult left, right;
186
933
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
187
188
2.38k
  
for (const QLValuePB& elem : right.Value().list_value().elems())933
{
189
2.38k
    if (!Comparable(elem, left.Value())) {
190
0
       return STATUS(RuntimeError, "values not comparable");
191
0
    }
192
2.38k
    if (elem == left.Value()) {
193
784
      return true;
194
784
    }
195
2.38k
  }
196
197
149
  return false;
198
933
}
Unexecuted instantiation: yb::Result<bool> yb::In<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&)
199
200
template <class Operands, class Op>
201
Result<bool> EvalRelationalOp(
202
1.12M
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
1.12M
  QLExprResult left, right;
204
1.12M
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
1.12M
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
1.12M
  return op(left.Value(), right.Value());
209
1.12M
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, std::__1::equal_to<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, std::__1::equal_to<void> const&)
Line
Count
Source
202
184k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
184k
  QLExprResult left, right;
204
184k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
184k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
184k
  return op(left.Value(), right.Value());
209
184k
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, std::__1::less<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, std::__1::less<void> const&)
Line
Count
Source
202
434k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
434k
  QLExprResult left, right;
204
434k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
434k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
434k
  return op(left.Value(), right.Value());
209
434k
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, std::__1::less_equal<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, std::__1::less_equal<void> const&)
Line
Count
Source
202
28.1k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
28.1k
  QLExprResult left, right;
204
28.1k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
28.1k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
28.1k
  return op(left.Value(), right.Value());
209
28.1k
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, std::__1::greater<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, std::__1::greater<void> const&)
Line
Count
Source
202
444k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
444k
  QLExprResult left, right;
204
444k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
444k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
444k
  return op(left.Value(), right.Value());
209
444k
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, std::__1::greater_equal<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, std::__1::greater_equal<void> const&)
Line
Count
Source
202
29.3k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
29.3k
  QLExprResult left, right;
204
29.3k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
29.3k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
29.3k
  return op(left.Value(), right.Value());
209
29.3k
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, std::__1::not_equal_to<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, std::__1::not_equal_to<void> const&)
Line
Count
Source
202
2.01k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
2.01k
  QLExprResult left, right;
204
2.01k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
2.01k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
2.01k
  return op(left.Value(), right.Value());
209
2.01k
}
yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, std::__1::equal_to<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, std::__1::equal_to<void> const&)
Line
Count
Source
202
5.90k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
5.90k
  QLExprResult left, right;
204
5.90k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
5.90k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
5.90k
  return op(left.Value(), right.Value());
209
5.90k
}
Unexecuted instantiation: yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, std::__1::less<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, std::__1::less<void> const&)
Unexecuted instantiation: yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, std::__1::less_equal<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, std::__1::less_equal<void> const&)
Unexecuted instantiation: yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, std::__1::greater<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, std::__1::greater<void> const&)
Unexecuted instantiation: yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, std::__1::greater_equal<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, std::__1::greater_equal<void> const&)
Unexecuted instantiation: yb::Result<bool> yb::EvalRelationalOp<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, std::__1::not_equal_to<void> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, std::__1::not_equal_to<void> const&)
210
211
template<bool Value, class Operands>
212
Result<bool> Is(
213
0
  QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row) {
214
0
  QLExprResult temp;
215
0
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, temp.Writer()));
216
0
  if (temp.Value().value_case() != InternalType::kBoolValue) {
217
0
    return STATUS(RuntimeError, "not a bool value");
218
0
  }
219
0
  return !IsNull(temp.Value()) && temp.Value().bool_value() == Value;
220
0
}
Unexecuted instantiation: yb::Result<bool> yb::Is<true, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&)
Unexecuted instantiation: yb::Result<bool> yb::Is<false, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&)
Unexecuted instantiation: yb::Result<bool> yb::Is<true, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&)
Unexecuted instantiation: yb::Result<bool> yb::Is<false, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&)
221
222
template<class Operands>
223
Result<bool> Between(
224
0
  QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row) {
225
0
  CHECK_EQ(operands.size(), 3);
226
0
  QLExprResult temp, lower, upper;
227
0
  RETURN_NOT_OK(EvalOperands(
228
0
       executor, operands, table_row, temp.Writer(), lower.Writer(), upper.Writer()));
229
0
  if (!Comparable(temp.Value(), lower.Value()) || !Comparable(temp.Value(), upper.Value())) {
230
0
    return STATUS(RuntimeError, "values not comparable");
231
0
  }
232
0
  return temp.Value() >= lower.Value() && temp.Value() <= upper.Value();
233
0
}
Unexecuted instantiation: yb::Result<bool> yb::Between<google::protobuf::RepeatedPtrField<yb::QLExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&)
Unexecuted instantiation: yb::Result<bool> yb::Between<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&)
234
235
CHECKED_STATUS QLExprExecutor::EvalCondition(const QLConditionPB& condition,
236
                                             const QLTableRow& table_row,
237
1.73M
                                             QLValue *result) {
238
1.73M
#define QL_EVALUATE_RELATIONAL_OP(op) \
239
1.73M
  
result->set_bool_value(1.12M
VERIFY_RESULT1.12M
(EvalRelationalOp(this, operands, table_row, op))); \
240
1.12M
  return Status::OK();
241
242
1.73M
  QLExprResult temp;
243
1.73M
  const auto& operands = condition.operands();
244
1.73M
  switch (condition.op()) {
245
0
    case QL_OP_NOT: {
246
0
      CHECK_EQ(operands.size(), 1);
247
0
      CHECK_EQ(operands.Get(0).expr_case(), QLExpressionPB::ExprCase::kCondition);
248
0
      QLValue sub_result;
249
0
      RETURN_NOT_OK(EvalCondition(operands.Get(0).condition(), table_row, &sub_result));
250
0
      result->set_bool_value(!sub_result.bool_value());
251
0
      return Status::OK();
252
0
    }
253
254
0
    case QL_OP_IS_NULL:
255
0
      CHECK_EQ(operands.size(), 1);
256
0
      RETURN_NOT_OK(EvalExpr(operands.Get(0), table_row, temp.Writer()));
257
0
      result->set_bool_value(IsNull(temp.Value()));
258
0
      return Status::OK();
259
260
0
    case QL_OP_IS_NOT_NULL:
261
0
      CHECK_EQ(operands.size(), 1);
262
0
      RETURN_NOT_OK(EvalExpr(operands.Get(0), table_row, temp.Writer()));
263
0
      result->set_bool_value(!IsNull(temp.Value()));
264
0
      return Status::OK();
265
266
0
    case QL_OP_IS_TRUE:
267
0
      result->set_bool_value(VERIFY_RESULT(Is<true>(this, operands, table_row)));
268
0
      return Status::OK();
269
270
0
    case QL_OP_IS_FALSE:
271
0
      result->set_bool_value(VERIFY_RESULT(Is<false>(this, operands, table_row)));
272
0
      return Status::OK();
273
274
184k
    case QL_OP_EQUAL:
275
184k
      QL_EVALUATE_RELATIONAL_OP(std::equal_to<>());
276
277
433k
    case QL_OP_LESS_THAN:
278
433k
      QL_EVALUATE_RELATIONAL_OP(std::less<>());
279
280
28.1k
    case QL_OP_LESS_THAN_EQUAL:
281
28.1k
      QL_EVALUATE_RELATIONAL_OP(std::less_equal<>());
282
283
444k
    case QL_OP_GREATER_THAN:
284
444k
      QL_EVALUATE_RELATIONAL_OP(std::greater<>());
285
286
29.3k
    case QL_OP_GREATER_THAN_EQUAL:
287
29.3k
      QL_EVALUATE_RELATIONAL_OP(std::greater_equal<>());
288
289
2.01k
    case QL_OP_NOT_EQUAL:
290
2.01k
      QL_EVALUATE_RELATIONAL_OP(std::not_equal_to<>());
291
292
608k
    case QL_OP_AND:
293
608k
      CHECK_GT(operands.size(), 0);
294
1.06M
      for (const auto &operand : operands) {
295
1.06M
        CHECK_EQ(operand.expr_case(), QLExpressionPB::ExprCase::kCondition);
296
1.06M
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
297
1.06M
        if (!result->bool_value()) {
298
143k
          break;
299
143k
        }
300
1.06M
      }
301
608k
      return Status::OK();
302
303
209
    case QL_OP_OR:
304
209
      CHECK_GT(operands.size(), 0);
305
333
      for (const auto &operand : operands) {
306
333
        CHECK_EQ(operand.expr_case(), QLExpressionPB::ExprCase::kCondition);
307
333
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
308
333
        if (result->bool_value()) {
309
130
          break;
310
130
        }
311
333
      }
312
209
      return Status::OK();
313
314
0
    case QL_OP_BETWEEN:
315
0
      result->set_bool_value(VERIFY_RESULT(Between(this, operands, table_row)));
316
0
      return Status::OK();
317
318
0
    case QL_OP_NOT_BETWEEN:
319
0
      result->set_bool_value(!VERIFY_RESULT(Between(this, operands, table_row)));
320
0
      return Status::OK();
321
322
    // When a row exists, the primary key columns are always populated in the row (value-map) by
323
    // DocRowwiseIterator and only when it exists. Therefore, the row exists if and only if
324
    // the row (value-map) is not empty.
325
24
    case QL_OP_EXISTS:
326
24
      result->set_bool_value(!table_row.IsEmpty());
327
24
      return Status::OK();
328
329
70
    case QL_OP_NOT_EXISTS:
330
70
      result->set_bool_value(table_row.IsEmpty());
331
70
      return Status::OK();
332
333
877
    case QL_OP_IN:
334
877
      CHECK_EQ(operands.size(), 2);
335
877
      result->set_bool_value(VERIFY_RESULT(In(this, operands, table_row)));
336
0
      return Status::OK();
337
338
52
    case QL_OP_NOT_IN:
339
52
      CHECK_EQ(operands.size(), 2);
340
52
      result->set_bool_value(!VERIFY_RESULT(In(this, operands, table_row)));
341
0
      return Status::OK();
342
343
0
    case QL_OP_LIKE: FALLTHROUGH_INTENDED;
344
0
    case QL_OP_NOT_LIKE:
345
0
      LOG(ERROR) << "Internal error: illegal or unknown operator " << condition.op();
346
0
      break;
347
348
0
    case QL_OP_NOOP:
349
0
      break;
350
1.73M
  }
351
352
0
  result->SetNull();
353
0
  return STATUS(RuntimeError, "Internal error: illegal or unknown operator");
354
355
1.73M
#undef QL_EVALUATE_RELATIONAL_OP
356
1.73M
}
357
358
//--------------------------------------------------------------------------------------------------
359
360
49.7M
bfpg::TSOpcode QLExprExecutor::GetTSWriteInstruction(const PgsqlExpressionPB& ql_expr) const {
361
  // "kSubDocInsert" instructs the tablet server to insert a new value or replace an existing value.
362
49.7M
  if (ql_expr.has_tscall()) {
363
33.5k
    return static_cast<bfpg::TSOpcode>(ql_expr.tscall().opcode());
364
33.5k
  }
365
49.7M
  return bfpg::TSOpcode::kScalarInsert;
366
49.7M
}
367
368
//--------------------------------------------------------------------------------------------------
369
370
CHECKED_STATUS QLExprExecutor::EvalExpr(const PgsqlExpressionPB& ql_expr,
371
                                        const QLTableRow* table_row,
372
                                        QLExprResultWriter result_writer,
373
707M
                                        const Schema *schema) {
374
707M
  switch (ql_expr.expr_case()) {
375
47.8M
    case PgsqlExpressionPB::ExprCase::kValue:
376
47.8M
      result_writer.SetExisting(&ql_expr.value());
377
47.8M
      break;
378
379
656M
    case PgsqlExpressionPB::ExprCase::kColumnId:
380
656M
      return EvalColumnRef(ql_expr.column_id(), table_row, result_writer);
381
382
0
    case PgsqlExpressionPB::ExprCase::kBfcall:
383
0
      return EvalBFCall(ql_expr.bfcall(), *table_row, &result_writer.NewValue());
384
385
3.14M
    case PgsqlExpressionPB::ExprCase::kTscall:
386
3.14M
      return EvalTSCall(ql_expr.tscall(), *table_row, &result_writer.NewValue(), schema);
387
388
2.97k
    case PgsqlExpressionPB::ExprCase::kCondition:
389
2.97k
      return EvalCondition(ql_expr.condition(), *table_row, &result_writer.NewValue());
390
391
0
    case PgsqlExpressionPB::ExprCase::kBocall: FALLTHROUGH_INTENDED;
392
0
    case PgsqlExpressionPB::ExprCase::kBindId: FALLTHROUGH_INTENDED;
393
0
    case PgsqlExpressionPB::ExprCase::kAliasId: FALLTHROUGH_INTENDED;
394
0
    case PgsqlExpressionPB::ExprCase::EXPR_NOT_SET:
395
0
      result_writer.SetNull();
396
707M
  }
397
47.8M
  return Status::OK();
398
707M
}
399
400
//--------------------------------------------------------------------------------------------------
401
402
CHECKED_STATUS QLExprExecutor::ReadExprValue(const PgsqlExpressionPB& ql_expr,
403
                                             const QLTableRow& table_row,
404
0
                                             QLExprResultWriter result_writer) {
405
0
  if (ql_expr.expr_case() == PgsqlExpressionPB::ExprCase::kTscall) {
406
0
    return ReadTSCallValue(ql_expr.tscall(), table_row, result_writer);
407
0
  } else {
408
0
    return EvalExpr(ql_expr, table_row, result_writer);
409
0
  }
410
0
}
411
412
//--------------------------------------------------------------------------------------------------
413
414
CHECKED_STATUS QLExprExecutor::EvalColumnRef(ColumnIdRep col_id,
415
                                             const QLTableRow* table_row,
416
0
                                             QLExprResultWriter result_writer) {
417
0
  if (table_row == nullptr) {
418
0
    result_writer.SetNull();
419
0
  } else {
420
0
    RETURN_NOT_OK(table_row->ReadColumn(col_id, result_writer));
421
0
  }
422
0
  return Status::OK();
423
0
}
424
425
//--------------------------------------------------------------------------------------------------
426
427
CHECKED_STATUS QLExprExecutor::EvalBFCall(const PgsqlBCallPB& bfcall,
428
                                          const QLTableRow& table_row,
429
0
                                          QLValue *result) {
430
  // TODO(neil)
431
  // - Use TSOpode for collection expression if only TabletServer can execute.
432
  // OR
433
  // - Introduce BuiltinOperator in addition to builtin function. Use builtin operators for all
434
  //   special operations including collection operations. That way, we don't need special cases.
435
436
  // First, evaluate the arguments.
437
0
  vector<QLValue> args(bfcall.operands().size());
438
0
  int arg_index = 0;
439
0
  QLExprResult temp;
440
0
  for (auto operand : bfcall.operands()) {
441
0
    RETURN_NOT_OK(EvalExpr(operand, &table_row, temp.Writer()));
442
0
    temp.MoveTo(args[arg_index++].mutable_value());
443
0
  }
444
445
  // Now, execute the builtin call associated with the given opcode.
446
0
  return PgsqlBfunc::Exec(static_cast<bfpg::BFOpcode>(bfcall.opcode()), &args, result);
447
0
}
448
449
//--------------------------------------------------------------------------------------------------
450
451
CHECKED_STATUS QLExprExecutor::EvalTSCall(const PgsqlBCallPB& ql_expr,
452
                                          const QLTableRow& table_row,
453
                                          QLValue *result,
454
0
                                          const Schema *schema) {
455
0
  result->SetNull();
456
0
  return STATUS(RuntimeError, "Only tablet server can execute this operator");
457
0
}
458
459
CHECKED_STATUS QLExprExecutor::ReadTSCallValue(const PgsqlBCallPB& ql_expr,
460
                                               const QLTableRow& table_row,
461
0
                                               QLExprResultWriter result_writer) {
462
0
  result_writer.SetNull();
463
0
  return STATUS(RuntimeError, "Only tablet server can execute this operator");
464
0
}
465
466
//--------------------------------------------------------------------------------------------------
467
468
CHECKED_STATUS QLExprExecutor::EvalCondition(const PgsqlConditionPB& condition,
469
                                             const QLTableRow& table_row,
470
0
                                             bool* result) {
471
0
  QLValue result_pb;
472
0
  RETURN_NOT_OK(EvalCondition(condition, table_row, &result_pb));
473
0
  *result = result_pb.bool_value();
474
0
  return Status::OK();
475
0
}
476
477
CHECKED_STATUS QLExprExecutor::EvalCondition(const PgsqlConditionPB& condition,
478
                                             const QLTableRow& table_row,
479
8.87k
                                             QLValue *result) {
480
8.87k
#define QL_EVALUATE_RELATIONAL_OP(op)                                                              \
481
8.87k
  
result->set_bool_value(5.90k
VERIFY_RESULT5.90k
(EvalRelationalOp(this, operands, table_row, op))); \
482
5.90k
  return Status::OK();
483
484
8.87k
  QLExprResult temp;
485
8.87k
  const auto& operands = condition.operands();
486
8.87k
  switch (condition.op()) {
487
0
    case QL_OP_NOT: {
488
0
      CHECK_EQ(operands.size(), 1);
489
0
      CHECK_EQ(operands.Get(0).expr_case(), PgsqlExpressionPB::ExprCase::kCondition);
490
0
      QLValue sub_result;
491
0
      RETURN_NOT_OK(EvalCondition(operands.Get(0).condition(), table_row, &sub_result));
492
0
      result->set_bool_value(!sub_result.bool_value());
493
0
      return Status::OK();
494
0
    }
495
496
0
    case QL_OP_IS_NULL:
497
0
      CHECK_EQ(operands.size(), 1);
498
0
      RETURN_NOT_OK(EvalExpr(operands.Get(0), table_row, temp.Writer()));
499
0
      result->set_bool_value(IsNull(temp.Value()));
500
0
      return Status::OK();
501
502
0
    case QL_OP_IS_NOT_NULL:
503
0
      CHECK_EQ(operands.size(), 1);
504
0
      RETURN_NOT_OK(EvalExpr(operands.Get(0), table_row, temp.Writer()));
505
0
      result->set_bool_value(!IsNull(temp.Value()));
506
0
      return Status::OK();
507
508
0
    case QL_OP_IS_TRUE:
509
0
      result->set_bool_value(VERIFY_RESULT(Is<true>(this, operands, table_row)));
510
0
      return Status::OK();
511
512
0
    case QL_OP_IS_FALSE: {
513
0
      result->set_bool_value(VERIFY_RESULT(Is<false>(this, operands, table_row)));
514
0
      return Status::OK();
515
0
    }
516
517
5.90k
    case QL_OP_EQUAL:
518
5.90k
      QL_EVALUATE_RELATIONAL_OP(std::equal_to<>());
519
520
0
    case QL_OP_LESS_THAN:
521
0
      QL_EVALUATE_RELATIONAL_OP(std::less<>());
522
523
0
    case QL_OP_LESS_THAN_EQUAL:
524
0
      QL_EVALUATE_RELATIONAL_OP(std::less_equal<>());
525
526
0
    case QL_OP_GREATER_THAN:
527
0
      QL_EVALUATE_RELATIONAL_OP(std::greater<>());
528
529
0
    case QL_OP_GREATER_THAN_EQUAL:
530
0
      QL_EVALUATE_RELATIONAL_OP(std::greater_equal<>());
531
532
0
    case QL_OP_NOT_EQUAL:
533
0
      QL_EVALUATE_RELATIONAL_OP(std::not_equal_to<>());
534
535
2.95k
    case QL_OP_AND:
536
2.95k
      CHECK_GT(operands.size(), 0);
537
5.90k
      for (const auto &operand : operands) {
538
5.90k
        CHECK_EQ(operand.expr_case(), PgsqlExpressionPB::ExprCase::kCondition);
539
5.90k
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
540
5.90k
        if (!result->bool_value()) {
541
0
          break;
542
0
        }
543
5.90k
      }
544
2.95k
      return Status::OK();
545
546
0
    case QL_OP_OR:
547
0
      CHECK_GT(operands.size(), 0);
548
0
      for (const auto &operand : operands) {
549
0
        CHECK_EQ(operand.expr_case(), PgsqlExpressionPB::ExprCase::kCondition);
550
0
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
551
0
        if (result->bool_value()) {
552
0
          break;
553
0
        }
554
0
      }
555
0
      return Status::OK();
556
557
0
    case QL_OP_BETWEEN:
558
0
      result->set_bool_value(VERIFY_RESULT(Between(this, operands, table_row)));
559
0
      return Status::OK();
560
561
0
    case QL_OP_NOT_BETWEEN:
562
0
      result->set_bool_value(!VERIFY_RESULT(Between(this, operands, table_row)));
563
0
      return Status::OK();
564
565
      // When a row exists, the primary key columns are always populated in the row (value-map) by
566
      // DocRowwiseIterator and only when it exists. Therefore, the row exists if and only if
567
      // the row (value-map) is not empty.
568
29
    case QL_OP_EXISTS:
569
29
      result->set_bool_value(!table_row.IsEmpty());
570
29
      return Status::OK();
571
572
0
    case QL_OP_NOT_EXISTS:
573
0
      result->set_bool_value(table_row.IsEmpty());
574
0
      return Status::OK();
575
576
0
    case QL_OP_IN:
577
0
      CHECK_EQ(operands.size(), 2);
578
0
      result->set_bool_value(VERIFY_RESULT(In(this, operands, table_row)));
579
0
      break;
580
581
0
    case QL_OP_NOT_IN:
582
0
      CHECK_EQ(operands.size(), 2);
583
0
      result->set_bool_value(!VERIFY_RESULT(In(this, operands, table_row)));
584
0
      break;
585
586
0
    case QL_OP_LIKE: FALLTHROUGH_INTENDED;
587
0
    case QL_OP_NOT_LIKE:
588
0
      LOG(ERROR) << "Internal error: illegal or unknown operator " << condition.op();
589
0
      break;
590
591
0
    case QL_OP_NOOP:
592
0
      break;
593
8.87k
  }
594
595
0
  result->SetNull();
596
0
  return STATUS(RuntimeError, "Internal error: illegal or unknown operator");
597
598
8.87k
#undef QL_EVALUATE_RELATIONAL_OP
599
8.87k
#undef QL_EVALUATE_BETWEEN
600
8.87k
}
601
602
//--------------------------------------------------------------------------------------------------
603
604
11.3M
const QLTableRow& QLTableRow::empty_row() {
605
11.3M
  static QLTableRow empty_row;
606
11.3M
  return empty_row;
607
11.3M
}
608
609
125k
size_t QLTableRow::ColumnCount() const {
610
125k
  size_t result = 0;
611
1.83M
  for (auto i : assigned_) {
612
1.83M
    result += i;
613
1.83M
  }
614
125k
  return result;
615
125k
}
616
617
75.2M
void QLTableRow::Clear() {
618
75.2M
  if (num_assigned_ == 0) {
619
14.5M
    return;
620
14.5M
  }
621
622
60.6M
  memset(assigned_.data(), 0, assigned_.size());
623
60.6M
  num_assigned_ = 0;
624
60.6M
}
625
626
720M
size_t QLTableRow::ColumnIndex(ColumnIdRep col_id) const {
627
720M
  if (col_id < kFirstNonPreallocatedColumnId && 
col_id >= kFirstColumnIdRep405M
) {
628
405M
    return col_id - kFirstColumnIdRep;
629
405M
  }
630
314M
  const auto& col_iter = column_id_to_index_.find(col_id);
631
314M
  if (col_iter == column_id_to_index_.end()) {
632
4
    return kInvalidIndex;
633
4
  }
634
635
314M
  return col_iter->second;
636
314M
}
637
638
720M
const QLTableColumn* QLTableRow::FindColumn(ColumnIdRep col_id) const {
639
720M
  size_t index = ColumnIndex(col_id);
640
720M
  if (
index == kInvalidIndex720M
|| index >= assigned_.size() ||
!assigned_[index]719M
) {
641
15.6k
    return nullptr;
642
15.6k
  }
643
644
720M
  return &values_[index];
645
720M
}
646
647
662M
const QLValuePB* QLTableRow::GetColumn(ColumnIdRep col_id) const {
648
662M
  const auto* column = FindColumn(col_id);
649
662M
  return column ? 
&column->value662M
:
nullptr174k
;
650
662M
}
651
652
662M
CHECKED_STATUS QLTableRow::ReadColumn(ColumnIdRep col_id, QLExprResultWriter result_writer) const {
653
662M
  auto value = GetColumn(col_id);
654
662M
  if (value == nullptr) {
655
2.95k
    result_writer.SetNull();
656
2.95k
    return Status::OK();
657
2.95k
  }
658
659
662M
  result_writer.SetExisting(value);
660
662M
  return Status::OK();
661
662M
}
662
663
CHECKED_STATUS QLTableRow::ReadSubscriptedColumn(const QLSubscriptedColPB& subcol,
664
                                                 const QLValuePB& index_arg,
665
192
                                                 QLExprResultWriter result_writer) const {
666
192
  const auto* value = GetColumn(subcol.column_id());
667
192
  if (!value) {
668
    // Does not exist.
669
0
    result_writer.SetNull();
670
0
    return Status::OK();
671
0
  }
672
673
192
  if (value->has_map_value()) {
674
    // map['key']
675
147
    auto& map = value->map_value();
676
148
    for (int i = 0; i < map.keys_size(); 
i++1
) {
677
147
      if (map.keys(i) == index_arg) {
678
146
        result_writer.SetExisting(&map.values(i));
679
146
        return Status::OK();
680
146
      }
681
147
    }
682
147
  } else 
if (45
value->has_list_value()45
) {
683
    // list[index]
684
24
    auto& list = value->list_value();
685
24
    if (index_arg.has_int32_value()) {
686
24
      int list_index = index_arg.int32_value();
687
24
      if (list_index >= 0 && list_index < list.elems_size()) {
688
23
        result_writer.SetExisting(&list.elems(list_index));
689
23
        return Status::OK();
690
23
      }
691
24
    }
692
24
  }
693
694
23
  result_writer.SetNull();
695
23
  return Status::OK();
696
192
}
697
698
7.16M
Result<const QLTableColumn&> QLTableRow::Column(ColumnIdRep col_id) const {
699
7.16M
  const auto* column = FindColumn(col_id);
700
7.16M
  if (column == nullptr) {
701
    // Does not exist.
702
0
    return STATUS(InternalError, "Column unexpectedly not found in cache");
703
0
  }
704
705
7.16M
  return *column;
706
7.16M
}
707
708
41
CHECKED_STATUS QLTableRow::GetTTL(ColumnIdRep col_id, int64_t *ttl_seconds) const {
709
41
  *ttl_seconds = VERIFY_RESULT(Column(col_id)).get().ttl_seconds;
710
0
  return Status::OK();
711
41
}
712
713
5.52k
CHECKED_STATUS QLTableRow::GetWriteTime(ColumnIdRep col_id, int64_t *write_time) const {
714
5.52k
  const QLTableColumn& column = VERIFY_RESULT(Column(col_id));
715
0
  DCHECK_NE(QLTableColumn::kUninitializedWriteTime, column.write_time) << "Column id: " << col_id;
716
5.52k
  *write_time = column.write_time;
717
5.52k
  return Status::OK();
718
5.52k
}
719
720
7.16M
CHECKED_STATUS QLTableRow::GetValue(ColumnIdRep col_id, QLValue *column) const {
721
7.16M
  *column = VERIFY_RESULT(Column(col_id)).get().value;
722
0
  return Status::OK();
723
7.16M
}
724
725
7.16M
CHECKED_STATUS QLTableRow::GetValue(const ColumnId& col, QLValue *column) const {
726
7.16M
  return GetValue(col.rep(), column);
727
7.16M
}
728
729
49.9M
boost::optional<const QLValuePB&> QLTableRow::GetValue(ColumnIdRep col_id) const {
730
49.9M
  const auto* column = FindColumn(col_id);
731
49.9M
  if (column) {
732
49.9M
    return column->value;
733
49.9M
  }
734
7.39k
  return boost::none;
735
49.9M
}
736
737
337
bool QLTableRow::IsColumnSpecified(ColumnIdRep col_id) const {
738
337
  size_t index = ColumnIndex(col_id);
739
337
  if (index == kInvalidIndex) {
740
0
    LOG(DFATAL) << "Checking whether unknown column is specified: " << col_id;
741
0
    return false;
742
0
  }
743
337
  return assigned_[index];
744
337
}
745
746
39
void QLTableRow::MarkTombstoned(ColumnIdRep col_id) {
747
39
  AllocColumn(col_id).value.Clear();
748
39
}
749
750
41.2k
bool QLTableRow::MatchColumn(ColumnIdRep col_id, const QLTableRow& source) const {
751
41.2k
  const auto* this_column = FindColumn(col_id);
752
41.2k
  const auto* source_column = source.FindColumn(col_id);
753
41.3k
  if (
this_column41.2k
&& source_column) {
754
31.8k
    return this_column->value == source_column->value;
755
31.8k
  }
756
9.47k
  return !this_column && 
!source_column10
;
757
41.2k
}
758
759
56.4M
QLTableColumn& QLTableRow::AppendColumn() {
760
56.4M
  values_.emplace_back();
761
56.4M
  assigned_.push_back(true);
762
56.4M
  ++num_assigned_;
763
56.4M
  return values_.back();
764
56.4M
}
765
766
774M
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id) {
767
774M
  size_t index = col_id;
768
774M
  if (index < kFirstNonPreallocatedColumnId && 
index >= kFirstColumnIdRep460M
) {
769
459M
    index -= kFirstColumnIdRep;
770
    // We are in directly mapped part. Ensure that vector is big enough.
771
459M
    if (values_.size() <= index) {
772
      // We don't need reserve here, because no allocation would take place.
773
46.0M
      if (values_.size() < index) {
774
66.8k
        values_.resize(index);
775
66.8k
        assigned_.resize(index);
776
66.8k
      }
777
      // This column was not yet allocated, so allocate it. Also vector has `col_id` size, so
778
      // new column will be added at `col_id` position.
779
46.0M
      return AppendColumn();
780
46.0M
    }
781
459M
  } else {
782
    // We are in part that is mapped using `column_id_to_index_`, so need to allocate at least
783
    // part that is mapped directly, to avoid index overlapping.
784
314M
    if (values_.size() < kPreallocatedSize) {
785
205k
      values_.resize(kPreallocatedSize);
786
205k
      assigned_.resize(kPreallocatedSize);
787
205k
    }
788
314M
    auto iterator_and_flag = column_id_to_index_.emplace(col_id, values_.size());
789
314M
    if (iterator_and_flag.second) {
790
10.4M
      return AppendColumn();
791
10.4M
    }
792
304M
    index = iterator_and_flag.first->second;
793
304M
  }
794
795
718M
  if (!assigned_[index]) {
796
664M
    assigned_[index] = true;
797
664M
    ++num_assigned_;
798
664M
  }
799
718M
  return values_[index];
800
774M
}
801
802
21.4M
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id, const QLValue& ql_value) {
803
21.4M
  return AllocColumn(col_id, ql_value.value());
804
21.4M
}
805
806
28.7M
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id, const QLValuePB& ql_value) {
807
28.7M
  QLTableColumn& result = AllocColumn(col_id);
808
28.7M
  result.value = ql_value;
809
28.7M
  return result;
810
28.7M
}
811
812
77.1k
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id, QLValuePB&& ql_value) {
813
77.1k
  QLTableColumn& result = AllocColumn(col_id);
814
77.1k
  result.value = std::move(ql_value);
815
77.1k
  return result;
816
77.1k
}
817
818
413
void QLTableRow::CopyColumn(ColumnIdRep col_id, const QLTableRow& source) {
819
413
  const auto* value = source.FindColumn(col_id);
820
413
  if (value) {
821
413
    AllocColumn(col_id) = *value;
822
413
    return;
823
413
  }
824
825
0
  auto index = ColumnIndex(col_id);
826
0
  if (index == kInvalidIndex) {
827
0
    return;
828
0
  }
829
0
  if (assigned_[index]) {
830
0
    assigned_[index] = false;
831
0
    --num_assigned_;
832
0
  }
833
0
}
834
835
1
std::string QLTableRow::ToString() const {
836
1
  std::string ret("{ ");
837
838
2
  for (size_t i = 0; i != kPreallocatedSize; 
++i1
) {
839
2
    if (i >= values_.size()) {
840
1
      break;
841
1
    }
842
1
    if (!assigned_[i]) {
843
0
      continue;
844
0
    }
845
1
    ret.append(Format("$0 => $1 ", i + kFirstColumnIdRep, values_[i]));
846
1
  }
847
848
1
  for (auto p : column_id_to_index_) {
849
0
    if (!assigned_[p.second]) {
850
0
      continue;
851
0
    }
852
853
0
    ret.append(Format("$0 => $1 ", p.first, values_[p.second]));
854
0
  }
855
856
1
  ret.append("}");
857
1
  return ret;
858
1
}
859
860
5.16k
std::string QLTableRow::ToString(const Schema& schema) const {
861
5.16k
  std::string ret;
862
5.16k
  ret.append("{ ");
863
864
20.6k
  for (size_t col_idx = 0; col_idx < schema.num_columns(); 
col_idx++15.4k
) {
865
15.4k
    const auto* value = GetColumn(schema.column_id(col_idx));
866
15.4k
    if (value && value->value_case() != QLValuePB::VALUE_NOT_SET) {
867
15.1k
      ret += value->ShortDebugString();
868
15.1k
    } else {
869
351
      ret += "null";
870
351
    }
871
15.4k
    ret += ' ';
872
15.4k
  }
873
5.16k
  ret.append("}");
874
5.16k
  return ret;
875
5.16k
}
876
877
18.0k
void QLExprResult::MoveToJsonb(common::Jsonb* out) {
878
18.0k
  if (existing_value_) {
879
18.0k
    out->Assign(existing_value_->jsonb_value());
880
18.0k
    existing_value_ = nullptr;
881
18.0k
  } else {
882
0
    out->Assign(std::move(*value_.mutable_value()->mutable_jsonb_value()));
883
0
  }
884
18.0k
}
885
886
760M
const QLValuePB& QLExprResult::Value() const {
887
760M
  if (existing_value_) {
888
719M
    return *existing_value_;
889
719M
  }
890
891
41.1M
  return value_.value();
892
760M
}
893
894
18.2k
bool QLExprResult::IsNull() const {
895
18.2k
  if (existing_value_) {
896
18.1k
    return yb::IsNull(*existing_value_);
897
18.1k
  }
898
899
89
  return value_.IsNull();
900
18.2k
}
901
902
4.95k
void QLExprResult::MoveTo(QLValuePB* out) {
903
4.95k
  if (existing_value_) {
904
537
    *out = *existing_value_;
905
537
    existing_value_ = nullptr;
906
4.41k
  } else {
907
4.41k
    value_.mutable_value()->Swap(out);
908
4.41k
  }
909
4.95k
}
910
911
22
QLValue& QLExprResult::ForceNewValue() {
912
22
  if (existing_value_) {
913
11
    value_ = *existing_value_;
914
11
    existing_value_ = nullptr;
915
11
  }
916
917
22
  return value_;
918
22
}
919
920
761M
QLExprResultWriter QLExprResult::Writer() {
921
761M
  return QLExprResultWriter(this);
922
761M
}
923
924
3.19k
void QLExprResultWriter::SetNull() {
925
3.19k
  result_->value_.SetNull();
926
3.19k
}
927
928
717M
void QLExprResultWriter::SetExisting(const QLValuePB* existing_value) {
929
717M
  result_->existing_value_ = existing_value;
930
717M
}
931
932
44.4M
QLValue& QLExprResultWriter::NewValue() {
933
44.4M
  return result_->value_;
934
44.4M
}
935
936
1
std::string QLTableColumn::ToString() const {
937
1
  return Format("{ value: $0 ttl_seconds: $1 write_time: $2 }", value, ttl_seconds,
938
1
                write_time == kUninitializedWriteTime ? "kUninitializedWriteTime":
939
1
                                                        
std::to_string(write_time)0
);
940
1
}
941
942
} // namespace yb