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.h
Line
Count
Source (jump to first uncovered line)
1
//--------------------------------------------------------------------------------------------------
2
// Copyright (c) YugaByte, Inc.
3
//
4
// This module defines the ResultSet that YQL database returns to a query request.
5
//--------------------------------------------------------------------------------------------------
6
7
#ifndef YB_COMMON_QL_EXPR_H_
8
#define YB_COMMON_QL_EXPR_H_
9
10
#include <boost/container/small_vector.hpp>
11
12
#include <boost/optional/optional.hpp>
13
14
#include "yb/bfql/tserver_opcodes.h"
15
#include "yb/bfpg/tserver_opcodes.h"
16
17
#include "yb/common/common_fwd.h"
18
#include "yb/common/column_id.h"
19
#include "yb/common/ql_value.h"
20
21
#include "yb/gutil/casts.h"
22
23
24
#include "yb/util/status.h"
25
#include "yb/util/status_format.h"
26
27
namespace yb {
28
29
// TODO(neil)
30
// - This should be maping directly from "int32_t" to QLValue.
31
//   using ValueMap = std::unordered_map<int32_t, const QLValuePB>;
32
// - We should use shared_ptr for this map as we might multi-threading the execution process.
33
34
// DocDB is using this map, so its code has to be updated before we can change this.
35
// Slowing down our execution by calling constructor each time is not desired.
36
37
// Map for easy lookup of column values of a row by the column id. This map is used in tserver
38
// for saving the column values of a selected row to evaluate the WHERE and IF clauses. Since
39
// we use the clauses in protobuf to evaluate, we will maintain the column values in QLValuePB
40
// also to avoid conversion to and from QLValue.
41
struct QLTableColumn {
42
  static constexpr int64_t kUninitializedWriteTime = std::numeric_limits<int64_t>::min();
43
44
  QLValuePB value;
45
  int64_t ttl_seconds = 0;
46
  int64_t write_time = kUninitializedWriteTime;
47
48
  std::string ToString() const;
49
};
50
51
class QLExprResultWriter;
52
53
class QLExprResult {
54
 public:
55
  const QLValuePB& Value() const;
56
57
  void MoveToJsonb(common::Jsonb* out);
58
59
  void MoveTo(QLValuePB* out);
60
61
  QLValue& ForceNewValue();
62
63
  QLExprResultWriter Writer();
64
65
  bool IsNull() const;
66
67
 private:
68
  friend class QLExprResultWriter;
69
70
  QLValue value_;
71
  const QLValuePB* existing_value_ = nullptr;
72
};
73
74
class QLExprResultWriter {
75
 public:
76
761M
  explicit QLExprResultWriter(QLExprResult* result) : result_(result) {
77
761M
    result_->existing_value_ = nullptr;
78
761M
  }
79
80
  void SetNull();
81
82
  void SetExisting(const QLValuePB* existing_value);
83
84
  QLValue& NewValue();
85
 private:
86
  QLExprResult* result_;
87
};
88
89
class QLTableRow {
90
 public:
91
  // Public types.
92
  typedef std::shared_ptr<QLTableRow> SharedPtr;
93
  typedef std::shared_ptr<const QLTableRow> SharedPtrConst;
94
95
  static const QLTableRow& empty_row();
96
97
  // Check if row is empty (no column).
98
11.0M
  bool IsEmpty() const { return num_assigned_ == 0; }
99
100
  // Get column count.
101
  size_t ColumnCount() const;
102
103
  // Clear the row.
104
  void Clear();
105
106
  // Compare column value between two rows.
107
  bool MatchColumn(ColumnIdRep col_id, const QLTableRow& source) const;
108
41.3k
  bool MatchColumn(const ColumnId& col, const QLTableRow& source) const {
109
41.3k
    return MatchColumn(col.rep(), source);
110
41.3k
  }
111
112
  // Allocate column in a map to cache its value, ttl, and writetime.
113
  QLTableColumn& AllocColumn(ColumnIdRep col_id);
114
745M
  QLTableColumn& AllocColumn(const ColumnId& col) { return AllocColumn(col.rep()); }
115
116
  QLTableColumn& AllocColumn(ColumnIdRep col_id, const QLValue& ql_value);
117
21.4M
  QLTableColumn& AllocColumn(const ColumnId& col, const QLValue& ql_value) {
118
21.4M
    return AllocColumn(col.rep(), ql_value);
119
21.4M
  }
120
  QLTableColumn& AllocColumn(ColumnIdRep col_id, const QLValuePB& ql_value);
121
7.30M
  QLTableColumn& AllocColumn(const ColumnId& col, const QLValuePB& ql_value) {
122
7.30M
    return AllocColumn(col.rep(), ql_value);
123
7.30M
  }
124
125
  QLTableColumn& AllocColumn(ColumnIdRep col_id, QLValuePB&& ql_value);
126
  QLTableColumn& AllocColumn(const ColumnId& col, QLValuePB&& ql_value) {
127
    return AllocColumn(col.rep(), std::move(ql_value));
128
  }
129
130
  // Copy column-value from 'source' to the 'col_id' entry in the cached column-map.
131
  void CopyColumn(ColumnIdRep col_id, const QLTableRow& source);
132
413
  void CopyColumn(const ColumnId& col, const QLTableRow& source) {
133
413
    return CopyColumn(col.rep(), source);
134
413
  }
135
136
  // Get a column TTL.
137
  CHECKED_STATUS GetTTL(ColumnIdRep col_id, int64_t *ttl_seconds) const;
138
139
  // Get a column WriteTime.
140
  CHECKED_STATUS GetWriteTime(ColumnIdRep col_id, int64_t *write_time) const;
141
142
  // Copy the column value of the given ID to output parameter "column".
143
  CHECKED_STATUS GetValue(ColumnIdRep col_id, QLValue *column) const;
144
  CHECKED_STATUS GetValue(const ColumnId& col, QLValue *column) const;
145
  boost::optional<const QLValuePB&> GetValue(ColumnIdRep col_id) const;
146
49.9M
  boost::optional<const QLValuePB&> GetValue(const ColumnId& col) const {
147
49.9M
    return GetValue(col.rep());
148
49.9M
  }
149
150
  // Predicate if given column is specified in the row.
151
  // NOTE: This returns true if column is specified even when its value is NULL.
152
  bool IsColumnSpecified(ColumnIdRep col_id) const;
153
154
  // Clear the column value.
155
  void MarkTombstoned(ColumnIdRep col_id);
156
39
  void MarkTombstoned(const ColumnId& col) {
157
39
    return MarkTombstoned(col.rep());
158
39
  }
159
160
  // Get the column value in PB format.
161
  CHECKED_STATUS ReadColumn(ColumnIdRep col_id, QLExprResultWriter result_writer) const;
162
  const QLValuePB* GetColumn(ColumnIdRep col_id) const;
163
  CHECKED_STATUS ReadSubscriptedColumn(const QLSubscriptedColPB& subcol,
164
                                       const QLValuePB& index,
165
                                       QLExprResultWriter result_writer) const;
166
167
  // For testing only (no status check).
168
  const QLTableColumn& TestValue(ColumnIdRep col_id) const {
169
    return *FindColumn(col_id);
170
  }
171
  const QLTableColumn& TestValue(const ColumnId& col) const {
172
    return *FindColumn(col.rep());
173
  }
174
175
  std::string ToString() const;
176
  std::string ToString(const Schema& schema) const;
177
178
 private:
179
  // Return kInvalidIndex when column index is unknown.
180
  size_t ColumnIndex(ColumnIdRep col_id) const;
181
  const QLTableColumn* FindColumn(ColumnIdRep col_id) const;
182
  Result<const QLTableColumn&> Column(ColumnIdRep col_id) const;
183
  // Appends new entry to values_ and assigned_ fields.
184
  QLTableColumn& AppendColumn();
185
186
  // Map from column id to index in values_ and assigned_ vectors.
187
  // For columns from [kFirstColumnId; kFirstColumnId + kPreallocatedSize) we don't use
188
  // this field and map them directly.
189
  // I.e. column with id kFirstColumnId will have index 0 etc.
190
  // We are using unsigned int as map value and std::numeric_limits<size_t>::max() as invalid
191
  // column.
192
  // This way, the compiler would understand that this invalid value could never be stored in the
193
  // map and optimize away the comparison with it when inlining the ColumnIndex function call.
194
  std::unordered_map<ColumnIdRep, unsigned int> column_id_to_index_;
195
196
  static constexpr size_t kPreallocatedSize = 8;
197
  static constexpr ColumnIdRep kFirstNonPreallocatedColumnId =
198
      kFirstColumnIdRep + static_cast<ColumnIdRep>(kPreallocatedSize);
199
200
  // The two following vectors will be of the same size.
201
  // We use separate fields to achieve the following features:
202
  // 1) Fast way to cleanup row, just by setting assigned to false with one call.
203
  // 2) Avoid destroying values_, so they would be able to reuse allocated storage during row reuse.
204
  boost::container::small_vector<QLTableColumn, kPreallocatedSize> values_;
205
  boost::container::small_vector<bool, kPreallocatedSize> assigned_;
206
  size_t num_assigned_ = 0;
207
};
208
209
class QLExprExecutor {
210
 public:
211
  // Public types.
212
  typedef std::shared_ptr<QLExprExecutor> SharedPtr;
213
  typedef std::shared_ptr<const QLExprExecutor> SharedPtrConst;
214
215
  // Constructor.
216
  // TODO(neil) Investigate to see if constructor should save some parameters as members since
217
  // we pass the same parameter over & over again when calling function recursively.
218
50.5M
  QLExprExecutor() { }
219
50.5M
  virtual ~QLExprExecutor() { }
220
221
  //------------------------------------------------------------------------------------------------
222
  // CQL Support.
223
224
  // Get TServer opcode.
225
  yb::bfql::TSOpcode GetTSWriteInstruction(const QLExpressionPB& ql_expr) const;
226
227
  // Evaluate the given QLExpressionPB.
228
  CHECKED_STATUS EvalExpr(const QLExpressionPB& ql_expr,
229
                          const QLTableRow& table_row,
230
                          QLExprResultWriter result_writer,
231
                          const Schema *schema = nullptr);
232
233
  // Evaluate the given QLExpressionPB (if needed) and replace its content with the result.
234
  CHECKED_STATUS EvalExpr(QLExpressionPB* ql_expr,
235
                          const QLTableRow& table_row,
236
                          const Schema *schema = nullptr);
237
238
  // Read evaluated value from an expression. This is only useful for aggregate function.
239
  CHECKED_STATUS ReadExprValue(const QLExpressionPB& ql_expr,
240
                               const QLTableRow& table_row,
241
                               QLExprResultWriter result_writer);
242
243
  // Evaluate column reference.
244
  virtual CHECKED_STATUS EvalColumnRef(ColumnIdRep col_id,
245
                                       const QLTableRow* table_row,
246
                                       QLExprResultWriter result_writer);
247
248
  // Evaluate call to regular builtin operator.
249
  virtual CHECKED_STATUS EvalBFCall(const QLBCallPB& ql_expr,
250
                                    const QLTableRow& table_row,
251
                                    QLValue *result);
252
253
  // Evaluate call to tablet-server builtin operator.
254
  virtual CHECKED_STATUS EvalTSCall(const QLBCallPB& ql_expr,
255
                                    const QLTableRow& table_row,
256
                                    QLValue *result,
257
                                    const Schema *schema = nullptr);
258
259
  virtual CHECKED_STATUS ReadTSCallValue(const QLBCallPB& ql_expr,
260
                                         const QLTableRow& table_row,
261
                                         QLExprResultWriter result_writer);
262
263
  // Evaluate a boolean condition for the given row.
264
  virtual CHECKED_STATUS EvalCondition(const QLConditionPB& condition,
265
                                       const QLTableRow& table_row,
266
                                       bool* result);
267
  virtual CHECKED_STATUS EvalCondition(const QLConditionPB& condition,
268
                                       const QLTableRow& table_row,
269
                                       QLValue *result);
270
271
  //------------------------------------------------------------------------------------------------
272
  // PGSQL Support.
273
274
  // Get TServer opcode.
275
  yb::bfpg::TSOpcode GetTSWriteInstruction(const PgsqlExpressionPB& ql_expr) const;
276
277
  // Evaluate the given QLExpressionPB.
278
  CHECKED_STATUS EvalExpr(const PgsqlExpressionPB& ql_expr,
279
                          const QLTableRow* table_row,
280
                          QLExprResultWriter result_writer,
281
                          const Schema *schema = nullptr);
282
283
  CHECKED_STATUS EvalExpr(const PgsqlExpressionPB& ql_expr,
284
                          const QLTableRow& table_row,
285
                          QLExprResultWriter result_writer,
286
                          const Schema *schema = nullptr);
287
288
  CHECKED_STATUS EvalExpr(const PgsqlExpressionPB& ql_expr,
289
                          const QLTableRow& table_row,
290
                          QLValuePB* result,
291
                          const Schema *schema = nullptr);
292
293
  // Read evaluated value from an expression. This is only useful for aggregate function.
294
  CHECKED_STATUS ReadExprValue(const PgsqlExpressionPB& ql_expr,
295
                               const QLTableRow& table_row,
296
                               QLExprResultWriter result_writer);
297
298
  // Evaluate call to regular builtin operator.
299
  virtual CHECKED_STATUS EvalBFCall(const PgsqlBCallPB& ql_expr,
300
                                    const QLTableRow& table_row,
301
                                    QLValue *result);
302
303
  // Evaluate call to tablet-server builtin operator.
304
  virtual CHECKED_STATUS EvalTSCall(const PgsqlBCallPB& ql_expr,
305
                                    const QLTableRow& table_row,
306
                                    QLValue *result,
307
                                    const Schema *schema = nullptr);
308
309
  virtual CHECKED_STATUS ReadTSCallValue(const PgsqlBCallPB& ql_expr,
310
                                         const QLTableRow& table_row,
311
                                         QLExprResultWriter result_writer);
312
313
  // Evaluate a boolean condition for the given row.
314
  virtual CHECKED_STATUS EvalCondition(const PgsqlConditionPB& condition,
315
                                       const QLTableRow& table_row,
316
                                       bool* result);
317
  virtual CHECKED_STATUS EvalCondition(const PgsqlConditionPB& condition,
318
                                       const QLTableRow& table_row,
319
                                       QLValue *result);
320
};
321
322
template <class Operands>
323
CHECKED_STATUS EvalOperandsHelper(
324
1.12M
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, int index) {
325
1.12M
  return Status::OK();
326
1.12M
}
yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::QLExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, int)
Line
Count
Source
324
1.12M
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, int index) {
325
1.12M
  return Status::OK();
326
1.12M
}
yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, int)
Line
Count
Source
324
5.90k
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, int index) {
325
5.90k
  return Status::OK();
326
5.90k
}
327
328
template <class Operands, class... Args>
329
CHECKED_STATUS EvalOperandsHelper(
330
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row, int index,
331
2.25M
    QLExprResultWriter arg0, Args&&... args) {
332
2.25M
  RETURN_NOT_OK(executor->EvalExpr(operands[index], table_row, arg0));
333
2.25M
  return EvalOperandsHelper(executor, operands, table_row, index + 1, std::forward<Args>(args)...);
334
2.25M
}
yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::QLExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, int, yb::QLExprResultWriter)
Line
Count
Source
331
1.12M
    QLExprResultWriter arg0, Args&&... args) {
332
1.12M
  RETURN_NOT_OK(executor->EvalExpr(operands[index], table_row, arg0));
333
1.12M
  return EvalOperandsHelper(executor, operands, table_row, index + 1, std::forward<Args>(args)...);
334
1.12M
}
yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, int, yb::QLExprResultWriter, yb::QLExprResultWriter&&)
Line
Count
Source
331
1.12M
    QLExprResultWriter arg0, Args&&... args) {
332
1.12M
  RETURN_NOT_OK(executor->EvalExpr(operands[index], table_row, arg0));
333
1.12M
  return EvalOperandsHelper(executor, operands, table_row, index + 1, std::forward<Args>(args)...);
334
1.12M
}
Unexecuted instantiation: yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, yb::QLExprResultWriter, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, int, yb::QLExprResultWriter, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&)
yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> >(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, int, yb::QLExprResultWriter)
Line
Count
Source
331
5.90k
    QLExprResultWriter arg0, Args&&... args) {
332
5.90k
  RETURN_NOT_OK(executor->EvalExpr(operands[index], table_row, arg0));
333
5.90k
  return EvalOperandsHelper(executor, operands, table_row, index + 1, std::forward<Args>(args)...);
334
5.90k
}
yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, int, yb::QLExprResultWriter, yb::QLExprResultWriter&&)
Line
Count
Source
331
5.90k
    QLExprResultWriter arg0, Args&&... args) {
332
5.90k
  RETURN_NOT_OK(executor->EvalExpr(operands[index], table_row, arg0));
333
5.90k
  return EvalOperandsHelper(executor, operands, table_row, index + 1, std::forward<Args>(args)...);
334
5.90k
}
Unexecuted instantiation: yb::Status yb::EvalOperandsHelper<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, yb::QLExprResultWriter, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, int, yb::QLExprResultWriter, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&)
335
336
template <class Operands, class... Args>
337
CHECKED_STATUS EvalOperands(
338
    QLExprExecutor* executor, const Operands& operands, const QLTableRow& table_row,
339
1.12M
    Args&&... args) {
340
1.12M
  if (operands.size() != sizeof...(Args)) {
341
0
    return STATUS_FORMAT(InvalidArgument, "Wrong number of arguments, $0 expected but $1 found",
342
0
                         sizeof...(Args), operands.size());
343
0
  }
344
345
1.12M
  return EvalOperandsHelper(executor, operands, table_row, 0, std::forward<Args>(args)...);
346
1.12M
}
Unexecuted instantiation: yb::Status yb::EvalOperands<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, yb::QLExprResultWriter&&)
yb::Status yb::EvalOperands<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, yb::QLExprResultWriter, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&)
Line
Count
Source
339
1.12M
    Args&&... args) {
340
1.12M
  if (operands.size() != sizeof...(Args)) {
341
0
    return STATUS_FORMAT(InvalidArgument, "Wrong number of arguments, $0 expected but $1 found",
342
0
                         sizeof...(Args), operands.size());
343
0
  }
344
345
1.12M
  return EvalOperandsHelper(executor, operands, table_row, 0, std::forward<Args>(args)...);
346
1.12M
}
Unexecuted instantiation: yb::Status yb::EvalOperands<google::protobuf::RepeatedPtrField<yb::QLExpressionPB>, yb::QLExprResultWriter, yb::QLExprResultWriter, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::QLExpressionPB> const&, yb::QLTableRow const&, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&)
Unexecuted instantiation: yb::Status yb::EvalOperands<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, yb::QLExprResultWriter&&)
yb::Status yb::EvalOperands<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, yb::QLExprResultWriter, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&)
Line
Count
Source
339
5.90k
    Args&&... args) {
340
5.90k
  if (operands.size() != sizeof...(Args)) {
341
0
    return STATUS_FORMAT(InvalidArgument, "Wrong number of arguments, $0 expected but $1 found",
342
0
                         sizeof...(Args), operands.size());
343
0
  }
344
345
5.90k
  return EvalOperandsHelper(executor, operands, table_row, 0, std::forward<Args>(args)...);
346
5.90k
}
Unexecuted instantiation: yb::Status yb::EvalOperands<google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB>, yb::QLExprResultWriter, yb::QLExprResultWriter, yb::QLExprResultWriter>(yb::QLExprExecutor*, google::protobuf::RepeatedPtrField<yb::PgsqlExpressionPB> const&, yb::QLTableRow const&, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&, yb::QLExprResultWriter&&)
347
348
} // namespace yb
349
350
#endif // YB_COMMON_QL_EXPR_H_