YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
4.95M
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
4.95M
  if (ql_expr.has_tscall()) {
26
48
    return static_cast<bfql::TSOpcode>(ql_expr.tscall().opcode());
27
48
  }
28
4.95M
  return bfql::TSOpcode::kScalarInsert;
29
4.95M
}
30
31
//--------------------------------------------------------------------------------------------------
32
33
CHECKED_STATUS QLExprExecutor::EvalExpr(const QLExpressionPB& ql_expr,
34
                                        const QLTableRow& table_row,
35
                                        QLExprResultWriter result_writer,
36
42.0M
                                        const Schema *schema) {
37
42.0M
  switch (ql_expr.expr_case()) {
38
6.06M
    case QLExpressionPB::ExprCase::kValue:
39
6.06M
      result_writer.SetExisting(&ql_expr.value());
40
6.06M
      break;
41
42
35.8M
    case QLExpressionPB::ExprCase::kColumnId:
43
35.8M
      RETURN_NOT_OK(table_row.ReadColumn(ql_expr.column_id(), result_writer));
44
35.8M
      break;
45
46
18.0k
    case QLExpressionPB::ExprCase::kJsonColumn: {
47
18.0k
      QLExprResult temp;
48
18.0k
      const QLJsonColumnOperationsPB& json_ops = ql_expr.json_column();
49
18.0k
      RETURN_NOT_OK(table_row.ReadColumn(json_ops.column_id(), temp.Writer()));
50
18.0k
      if (temp.IsNull()) {
51
217
        result_writer.SetNull();
52
17.8k
      } else {
53
17.8k
        common::Jsonb jsonb;
54
17.8k
        temp.MoveToJsonb(&jsonb);
55
17.8k
        RETURN_NOT_OK(jsonb.ApplyJsonbOperators(json_ops, &result_writer.NewValue()));
56
17.8k
      }
57
18.0k
      break;
58
18.0k
    }
59
60
195
    case QLExpressionPB::ExprCase::kSubscriptedCol:
61
195
      if (table_row.IsEmpty()) {
62
0
        result_writer.SetNull();
63
195
      } else {
64
195
        QLExprResult index_arg;
65
195
        const QLSubscriptedColPB& subcol = ql_expr.subscripted_col();
66
195
        RETURN_NOT_OK(EvalExpr(subcol.subscript_args(0), table_row, index_arg.Writer()));
67
195
        RETURN_NOT_OK(table_row.ReadSubscriptedColumn(subcol, index_arg.Value(), result_writer));
68
195
      }
69
195
      break;
70
71
728
    case QLExpressionPB::ExprCase::kBfcall:
72
728
      return EvalBFCall(ql_expr.bfcall(), table_row, &result_writer.NewValue());
73
74
22.6k
    case QLExpressionPB::ExprCase::kTscall:
75
22.6k
      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
42.0M
  }
85
41.9M
  return Status::OK();
86
42.0M
}
87
88
//--------------------------------------------------------------------------------------------------
89
90
CHECKED_STATUS QLExprExecutor::EvalExpr(QLExpressionPB* ql_expr,
91
                                        const QLTableRow& table_row,
92
6.24M
                                        const Schema *schema) {
93
6.24M
  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
6.24M
  return Status::OK();
99
6.24M
}
100
101
CHECKED_STATUS QLExprExecutor::EvalExpr(const PgsqlExpressionPB& ql_expr,
102
                                        const QLTableRow& table_row,
103
                                        QLExprResultWriter result_writer,
104
240M
                                        const Schema *schema) {
105
240M
  return EvalExpr(ql_expr, &table_row, result_writer, schema);
106
240M
}
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
667k
                                             bool* result) {
176
667k
  QLValue result_pb;
177
667k
  RETURN_NOT_OK(EvalCondition(condition, table_row, &result_pb));
178
667k
  *result = result_pb.bool_value();
179
667k
  return Status::OK();
180
667k
}
181
182
template <class Operands>
183
Result<bool> In(
184
914
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row) {
185
914
  QLExprResult left, right;
186
914
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
187
188
2.34k
  for (const QLValuePB& elem : right.Value().list_value().elems()) {
189
2.34k
    if (!Comparable(elem, left.Value())) {
190
0
       return STATUS(RuntimeError, "values not comparable");
191
0
    }
192
2.34k
    if (elem == left.Value()) {
193
767
      return true;
194
767
    }
195
2.34k
  }
196
197
147
  return false;
198
914
}
_ZN2yb2InIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowE
Line
Count
Source
184
914
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row) {
185
914
  QLExprResult left, right;
186
914
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
187
188
2.34k
  for (const QLValuePB& elem : right.Value().list_value().elems()) {
189
2.34k
    if (!Comparable(elem, left.Value())) {
190
0
       return STATUS(RuntimeError, "values not comparable");
191
0
    }
192
2.34k
    if (elem == left.Value()) {
193
767
      return true;
194
767
    }
195
2.34k
  }
196
197
147
  return false;
198
914
}
Unexecuted instantiation: _ZN2yb2InIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowE
199
200
template <class Operands, class Op>
201
Result<bool> EvalRelationalOp(
202
1.10M
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
1.10M
  QLExprResult left, right;
204
1.10M
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
1.10M
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
1.10M
  return op(left.Value(), right.Value());
209
1.10M
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEENSt3__18equal_toIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
195k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
195k
  QLExprResult left, right;
204
195k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
195k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
195k
  return op(left.Value(), right.Value());
209
195k
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEENSt3__14lessIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
419k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
419k
  QLExprResult left, right;
204
419k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
419k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
419k
  return op(left.Value(), right.Value());
209
419k
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEENSt3__110less_equalIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
28.0k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
28.0k
  QLExprResult left, right;
204
28.0k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
28.0k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
28.0k
  return op(left.Value(), right.Value());
209
28.0k
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEENSt3__17greaterIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
429k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
429k
  QLExprResult left, right;
204
429k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
429k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
429k
  return op(left.Value(), right.Value());
209
429k
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEENSt3__113greater_equalIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
29.2k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
29.2k
  QLExprResult left, right;
204
29.2k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
29.2k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
29.2k
  return op(left.Value(), right.Value());
209
29.2k
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEENSt3__112not_equal_toIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
1.95k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
1.95k
  QLExprResult left, right;
204
1.95k
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
1.95k
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
1.95k
  return op(left.Value(), right.Value());
209
1.95k
}
_ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEENSt3__18equal_toIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Line
Count
Source
202
62
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, const Op& op) {
203
62
  QLExprResult left, right;
204
62
  RETURN_NOT_OK(EvalOperands(executor, operands, table_row, left.Writer(), right.Writer()));
205
62
  if (!Comparable(left.Value(), right.Value())) {
206
0
    return STATUS(RuntimeError, "values not comparable");
207
0
  }
208
62
  return op(left.Value(), right.Value());
209
62
}
Unexecuted instantiation: _ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEENSt3__14lessIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Unexecuted instantiation: _ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEENSt3__110less_equalIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Unexecuted instantiation: _ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEENSt3__17greaterIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Unexecuted instantiation: _ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEENSt3__113greater_equalIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
Unexecuted instantiation: _ZN2yb16EvalRelationalOpIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEENSt3__112not_equal_toIvEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowERKT0_
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: _ZN2yb2IsILb1EN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT0_RKNS_10QLTableRowE
Unexecuted instantiation: _ZN2yb2IsILb0EN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT0_RKNS_10QLTableRowE
Unexecuted instantiation: _ZN2yb2IsILb1EN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT0_RKNS_10QLTableRowE
Unexecuted instantiation: _ZN2yb2IsILb0EN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT0_RKNS_10QLTableRowE
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: _ZN2yb7BetweenIN6google8protobuf16RepeatedPtrFieldINS_14QLExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowE
Unexecuted instantiation: _ZN2yb7BetweenIN6google8protobuf16RepeatedPtrFieldINS_17PgsqlExpressionPBEEEEENS_6ResultIbEEPNS_14QLExprExecutorERKT_RKNS_10QLTableRowE
234
235
CHECKED_STATUS QLExprExecutor::EvalCondition(const QLConditionPB& condition,
236
                                             const QLTableRow& table_row,
237
1.69M
                                             QLValue *result) {
238
1.69M
#define QL_EVALUATE_RELATIONAL_OP(op) \
239
1.10M
  result->set_bool_value(VERIFY_RESULT(EvalRelationalOp(this, operands, table_row, op))); \
240
1.10M
  return Status::OK();
241
242
1.69M
  QLExprResult temp;
243
1.69M
  const auto& operands = condition.operands();
244
1.69M
  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
195k
    case QL_OP_EQUAL:
275
195k
      QL_EVALUATE_RELATIONAL_OP(std::equal_to<>());
276
277
419k
    case QL_OP_LESS_THAN:
278
419k
      QL_EVALUATE_RELATIONAL_OP(std::less<>());
279
280
28.0k
    case QL_OP_LESS_THAN_EQUAL:
281
28.0k
      QL_EVALUATE_RELATIONAL_OP(std::less_equal<>());
282
283
429k
    case QL_OP_GREATER_THAN:
284
429k
      QL_EVALUATE_RELATIONAL_OP(std::greater<>());
285
286
29.2k
    case QL_OP_GREATER_THAN_EQUAL:
287
29.2k
      QL_EVALUATE_RELATIONAL_OP(std::greater_equal<>());
288
289
1.95k
    case QL_OP_NOT_EQUAL:
290
1.95k
      QL_EVALUATE_RELATIONAL_OP(std::not_equal_to<>());
291
292
591k
    case QL_OP_AND:
293
591k
      CHECK_GT(operands.size(), 0);
294
1.02M
      for (const auto &operand : operands) {
295
1.02M
        CHECK_EQ(operand.expr_case(), QLExpressionPB::ExprCase::kCondition);
296
1.02M
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
297
1.02M
        if (!result->bool_value()) {
298
143k
          break;
299
143k
        }
300
1.02M
      }
301
591k
      return Status::OK();
302
303
174
    case QL_OP_OR:
304
174
      CHECK_GT(operands.size(), 0);
305
278
      for (const auto &operand : operands) {
306
278
        CHECK_EQ(operand.expr_case(), QLExpressionPB::ExprCase::kCondition);
307
278
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
308
278
        if (result->bool_value()) {
309
115
          break;
310
115
        }
311
278
      }
312
174
      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
882
    case QL_OP_IN:
334
882
      CHECK_EQ(operands.size(), 2);
335
882
      result->set_bool_value(VERIFY_RESULT(In(this, operands, table_row)));
336
882
      return Status::OK();
337
338
28
    case QL_OP_NOT_IN:
339
28
      CHECK_EQ(operands.size(), 2);
340
28
      result->set_bool_value(!VERIFY_RESULT(In(this, operands, table_row)));
341
28
      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
0
  }
351
352
0
  result->SetNull();
353
0
  return STATUS(RuntimeError, "Internal error: illegal or unknown operator");
354
355
0
#undef QL_EVALUATE_RELATIONAL_OP
356
0
}
357
358
//--------------------------------------------------------------------------------------------------
359
360
10.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
10.7M
  if (ql_expr.has_tscall()) {
363
11.4k
    return static_cast<bfpg::TSOpcode>(ql_expr.tscall().opcode());
364
11.4k
  }
365
10.7M
  return bfpg::TSOpcode::kScalarInsert;
366
10.7M
}
367
368
//--------------------------------------------------------------------------------------------------
369
370
CHECKED_STATUS QLExprExecutor::EvalExpr(const PgsqlExpressionPB& ql_expr,
371
                                        const QLTableRow* table_row,
372
                                        QLExprResultWriter result_writer,
373
240M
                                        const Schema *schema) {
374
240M
  switch (ql_expr.expr_case()) {
375
10.2M
    case PgsqlExpressionPB::ExprCase::kValue:
376
10.2M
      result_writer.SetExisting(&ql_expr.value());
377
10.2M
      break;
378
379
228M
    case PgsqlExpressionPB::ExprCase::kColumnId:
380
228M
      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
1.71M
    case PgsqlExpressionPB::ExprCase::kTscall:
386
1.71M
      return EvalTSCall(ql_expr.tscall(), *table_row, &result_writer.NewValue(), schema);
387
388
33
    case PgsqlExpressionPB::ExprCase::kCondition:
389
33
      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
240M
  }
397
10.2M
  return Status::OK();
398
240M
}
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
95
                                             QLValue *result) {
480
95
#define QL_EVALUATE_RELATIONAL_OP(op)                                                              \
481
62
  result->set_bool_value(VERIFY_RESULT(EvalRelationalOp(this, operands, table_row, op))); \
482
62
  return Status::OK();
483
484
95
  QLExprResult temp;
485
95
  const auto& operands = condition.operands();
486
95
  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
62
    case QL_OP_EQUAL:
518
62
      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
31
    case QL_OP_AND:
536
31
      CHECK_GT(operands.size(), 0);
537
62
      for (const auto &operand : operands) {
538
62
        CHECK_EQ(operand.expr_case(), PgsqlExpressionPB::ExprCase::kCondition);
539
62
        RETURN_NOT_OK(EvalCondition(operand.condition(), table_row, result));
540
62
        if (!result->bool_value()) {
541
0
          break;
542
0
        }
543
62
      }
544
31
      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
2
    case QL_OP_EXISTS:
569
2
      result->set_bool_value(!table_row.IsEmpty());
570
2
      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
0
  }
594
595
0
  result->SetNull();
596
0
  return STATUS(RuntimeError, "Internal error: illegal or unknown operator");
597
598
0
#undef QL_EVALUATE_RELATIONAL_OP
599
0
#undef QL_EVALUATE_BETWEEN
600
0
}
601
602
//--------------------------------------------------------------------------------------------------
603
604
6.27M
const QLTableRow& QLTableRow::empty_row() {
605
6.27M
  static QLTableRow empty_row;
606
6.27M
  return empty_row;
607
6.27M
}
608
609
77.3k
size_t QLTableRow::ColumnCount() const {
610
77.3k
  size_t result = 0;
611
1.30M
  for (auto i : assigned_) {
612
1.30M
    result += i;
613
1.30M
  }
614
77.3k
  return result;
615
77.3k
}
616
617
32.4M
void QLTableRow::Clear() {
618
32.4M
  if (num_assigned_ == 0) {
619
6.55M
    return;
620
6.55M
  }
621
622
25.9M
  memset(assigned_.data(), 0, assigned_.size());
623
25.9M
  num_assigned_ = 0;
624
25.9M
}
625
626
265M
size_t QLTableRow::ColumnIndex(ColumnIdRep col_id) const {
627
265M
  if (col_id < kFirstNonPreallocatedColumnId && col_id >= kFirstColumnIdRep) {
628
162M
    return col_id - kFirstColumnIdRep;
629
162M
  }
630
102M
  const auto& col_iter = column_id_to_index_.find(col_id);
631
102M
  if (col_iter == column_id_to_index_.end()) {
632
4
    return kInvalidIndex;
633
4
  }
634
635
102M
  return col_iter->second;
636
102M
}
637
638
265M
const QLTableColumn* QLTableRow::FindColumn(ColumnIdRep col_id) const {
639
265M
  size_t index = ColumnIndex(col_id);
640
265M
  if (index == kInvalidIndex || index >= assigned_.size() || !assigned_[index]) {
641
15.5k
    return nullptr;
642
15.5k
  }
643
644
265M
  return &values_[index];
645
265M
}
646
647
249M
const QLValuePB* QLTableRow::GetColumn(ColumnIdRep col_id) const {
648
249M
  const auto* column = FindColumn(col_id);
649
249M
  return column ? &column->value : nullptr;
650
249M
}
651
652
249M
CHECKED_STATUS QLTableRow::ReadColumn(ColumnIdRep col_id, QLExprResultWriter result_writer) const {
653
249M
  auto value = GetColumn(col_id);
654
249M
  if (value == nullptr) {
655
2.92k
    result_writer.SetNull();
656
2.92k
    return Status::OK();
657
2.92k
  }
658
659
249M
  result_writer.SetExisting(value);
660
249M
  return Status::OK();
661
249M
}
662
663
CHECKED_STATUS QLTableRow::ReadSubscriptedColumn(const QLSubscriptedColPB& subcol,
664
                                                 const QLValuePB& index_arg,
665
193
                                                 QLExprResultWriter result_writer) const {
666
193
  const auto* value = GetColumn(subcol.column_id());
667
193
  if (!value) {
668
    // Does not exist.
669
0
    result_writer.SetNull();
670
0
    return Status::OK();
671
0
  }
672
673
193
  if (value->has_map_value()) {
674
    // map['key']
675
147
    auto& map = value->map_value();
676
152
    for (int i = 0; i < map.keys_size(); i++) {
677
147
      if (map.keys(i) == index_arg) {
678
142
        result_writer.SetExisting(&map.values(i));
679
142
        return Status::OK();
680
142
      }
681
147
    }
682
46
  } else if (value->has_list_value()) {
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
28
    }
692
24
  }
693
694
28
  result_writer.SetNull();
695
28
  return Status::OK();
696
28
}
697
698
6.75M
Result<const QLTableColumn&> QLTableRow::Column(ColumnIdRep col_id) const {
699
6.75M
  const auto* column = FindColumn(col_id);
700
6.75M
  if (column == nullptr) {
701
    // Does not exist.
702
0
    return STATUS(InternalError, "Column unexpectedly not found in cache");
703
0
  }
704
705
6.75M
  return *column;
706
6.75M
}
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
41
  return Status::OK();
711
41
}
712
713
5.82k
CHECKED_STATUS QLTableRow::GetWriteTime(ColumnIdRep col_id, int64_t *write_time) const {
714
5.82k
  const QLTableColumn& column = VERIFY_RESULT(Column(col_id));
715
0
  DCHECK_NE(QLTableColumn::kUninitializedWriteTime, column.write_time) << "Column id: " << col_id;
716
5.82k
  *write_time = column.write_time;
717
5.82k
  return Status::OK();
718
5.82k
}
719
720
6.77M
CHECKED_STATUS QLTableRow::GetValue(ColumnIdRep col_id, QLValue *column) const {
721
6.77M
  *column = VERIFY_RESULT(Column(col_id)).get().value;
722
6.77M
  return Status::OK();
723
6.77M
}
724
725
6.76M
CHECKED_STATUS QLTableRow::GetValue(const ColumnId& col, QLValue *column) const {
726
6.76M
  return GetValue(col.rep(), column);
727
6.76M
}
728
729
8.95M
boost::optional<const QLValuePB&> QLTableRow::GetValue(ColumnIdRep col_id) const {
730
8.95M
  const auto* column = FindColumn(col_id);
731
8.95M
  if (column) {
732
8.95M
    return column->value;
733
8.95M
  }
734
3.44k
  return boost::none;
735
3.44k
}
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
40.2k
bool QLTableRow::MatchColumn(ColumnIdRep col_id, const QLTableRow& source) const {
751
40.2k
  const auto* this_column = FindColumn(col_id);
752
40.2k
  const auto* source_column = source.FindColumn(col_id);
753
40.2k
  if (this_column && source_column) {
754
30.8k
    return this_column->value == source_column->value;
755
30.8k
  }
756
9.46k
  return !this_column && !source_column;
757
9.46k
}
758
759
27.2M
QLTableColumn& QLTableRow::AppendColumn() {
760
27.2M
  values_.emplace_back();
761
27.2M
  assigned_.push_back(true);
762
27.2M
  ++num_assigned_;
763
27.2M
  return values_.back();
764
27.2M
}
765
766
292M
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id) {
767
292M
  size_t index = col_id;
768
292M
  if (index < kFirstNonPreallocatedColumnId && index >= kFirstColumnIdRep) {
769
188M
    index -= kFirstColumnIdRep;
770
    // We are in directly mapped part. Ensure that vector is big enough.
771
188M
    if (values_.size() <= index) {
772
      // We don't need reserve here, because no allocation would take place.
773
23.4M
      if (values_.size() < index) {
774
45.1k
        values_.resize(index);
775
45.1k
        assigned_.resize(index);
776
45.1k
      }
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
23.4M
      return AppendColumn();
780
23.4M
    }
781
103M
  } 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
103M
    if (values_.size() < kPreallocatedSize) {
785
1.58k
      values_.resize(kPreallocatedSize);
786
1.58k
      assigned_.resize(kPreallocatedSize);
787
1.58k
    }
788
103M
    auto iterator_and_flag = column_id_to_index_.emplace(col_id, values_.size());
789
103M
    if (iterator_and_flag.second) {
790
3.82M
      return AppendColumn();
791
3.82M
    }
792
99.5M
    index = iterator_and_flag.first->second;
793
99.5M
  }
794
795
264M
  if (!assigned_[index]) {
796
249M
    assigned_[index] = true;
797
249M
    ++num_assigned_;
798
249M
  }
799
264M
  return values_[index];
800
292M
}
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
26.5M
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id, const QLValuePB& ql_value) {
807
26.5M
  QLTableColumn& result = AllocColumn(col_id);
808
26.5M
  result.value = ql_value;
809
26.5M
  return result;
810
26.5M
}
811
812
77.3k
QLTableColumn& QLTableRow::AllocColumn(ColumnIdRep col_id, QLValuePB&& ql_value) {
813
77.3k
  QLTableColumn& result = AllocColumn(col_id);
814
77.3k
  result.value = std::move(ql_value);
815
77.3k
  return result;
816
77.3k
}
817
818
419
void QLTableRow::CopyColumn(ColumnIdRep col_id, const QLTableRow& source) {
819
419
  const auto* value = source.FindColumn(col_id);
820
419
  if (value) {
821
419
    AllocColumn(col_id) = *value;
822
419
    return;
823
419
  }
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; ++i) {
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
0
  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++) {
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
351
    } 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
17.8k
void QLExprResult::MoveToJsonb(common::Jsonb* out) {
878
17.8k
  if (existing_value_) {
879
17.8k
    out->Assign(existing_value_->jsonb_value());
880
17.8k
    existing_value_ = nullptr;
881
0
  } else {
882
0
    out->Assign(std::move(*value_.mutable_value()->mutable_jsonb_value()));
883
0
  }
884
17.8k
}
885
886
282M
const QLValuePB& QLExprResult::Value() const {
887
282M
  if (existing_value_) {
888
267M
    return *existing_value_;
889
267M
  }
890
891
15.2M
  return value_.value();
892
15.2M
}
893
894
18.0k
bool QLExprResult::IsNull() const {
895
18.0k
  if (existing_value_) {
896
17.9k
    return yb::IsNull(*existing_value_);
897
17.9k
  }
898
899
89
  return value_.IsNull();
900
89
}
901
902
4.94k
void QLExprResult::MoveTo(QLValuePB* out) {
903
4.94k
  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.94k
}
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
282M
QLExprResultWriter QLExprResult::Writer() {
921
282M
  return QLExprResultWriter(this);
922
282M
}
923
924
3.17k
void QLExprResultWriter::SetNull() {
925
3.17k
  result_->value_.SetNull();
926
3.17k
}
927
928
265M
void QLExprResultWriter::SetExisting(const QLValuePB* existing_value) {
929
265M
  result_->existing_value_ = existing_value;
930
265M
}
931
932
17.0M
QLValue& QLExprResultWriter::NewValue() {
933
17.0M
  return result_->value_;
934
17.0M
}
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
0
                                                        std::to_string(write_time));
940
1
}
941
942
} // namespace yb