YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/yql/pggate/pg_expr.cc
Line
Count
Source (jump to first uncovered line)
1
//--------------------------------------------------------------------------------------------------
2
// Copyright (c) YugaByte, Inc.
3
//
4
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
// in compliance with the License.  You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software distributed under the License
10
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
// or implied.  See the License for the specific language governing permissions and limitations
12
// under the License.
13
//
14
//--------------------------------------------------------------------------------------------------
15
16
#include <unordered_map>
17
18
#include "yb/client/schema.h"
19
#include "yb/common/ql_type.h"
20
#include "yb/common/pg_system_attr.h"
21
#include "yb/yql/pggate/pg_expr.h"
22
#include "yb/yql/pggate/pg_dml.h"
23
#include "yb/yql/pggate/ybc_pg_typedefs.h"
24
#include "yb/util/decimal.h"
25
#include "yb/util/flag_tags.h"
26
#include "yb/util/status_format.h"
27
28
29
DEFINE_test_flag(bool, do_not_add_enum_sort_order, false,
30
                 "Do not add enum type sort order when buidling a constant "
31
                 "for an enum type value. Used to test database upgrade "
32
                 "where we have pre-existing enum type column values that "
33
                 "did not have sort order added.");
34
35
namespace yb {
36
namespace pggate {
37
38
using std::make_shared;
39
using std::placeholders::_1;
40
using std::placeholders::_2;
41
42
namespace {
43
// Collation flags. kCollationMarker ensures the collation byte is non-zero.
44
constexpr uint8_t kDeterministicCollation = 0x01;
45
constexpr uint8_t kCollationMarker = 0x80;
46
47
string MakeCollationEncodedString(
48
2
  const char* value, int64_t bytes, uint8_t collation_flags, const char* sortkey) {
49
50
  // A postgres character value cannot have \0 byte.
51
2
  DCHECK(memchr(value, '\0', bytes) == nullptr);
52
53
  // We need to build a collation encoded string to include both the
54
  // collation sortkey and the original character value.
55
2
  string collstr;
56
2
  collstr.reserve(2 + strlen(sortkey) + 1 + bytes);
57
58
  // We set the first byte to '\0' which indicates that collstr is
59
  // collation encoded. We also put the collation flags byte in case
60
  // it is of any use in the future.
61
2
  collstr.append(1, '\0');
62
2
  static_assert(sizeof(collation_flags) == 1, "invalid size");
63
2
  collstr.append(1, collation_flags);
64
65
  // Add the sort key. This will appends a copy of sortkey. The sortkey itself
66
  // was allocated using palloc and therefore will be freed automatically at
67
  // the end of each transaction.
68
2
  collstr.append(sortkey);
69
70
  // Append a \0 byte which acts as a separator between sort key and the
71
  // original value.
72
2
  collstr.append(1, '\0');
73
74
  // Add the original value.
75
2
  collstr.append(value, bytes);
76
77
2
  return collstr;
78
2
}
79
80
} // namespace
81
82
//--------------------------------------------------------------------------------------------------
83
// Mapping Postgres operator names to YugaByte opcodes.
84
// When constructing expresions, Postgres layer will pass the operator name.
85
const std::unordered_map<string, PgExpr::Opcode> kOperatorNames = {
86
  { "!", PgExpr::Opcode::PG_EXPR_NOT },
87
  { "not", PgExpr::Opcode::PG_EXPR_NOT },
88
  { "=", PgExpr::Opcode::PG_EXPR_EQ },
89
  { "<>", PgExpr::Opcode::PG_EXPR_NE },
90
  { "!=", PgExpr::Opcode::PG_EXPR_NE },
91
  { ">", PgExpr::Opcode::PG_EXPR_GT },
92
  { ">=", PgExpr::Opcode::PG_EXPR_GE },
93
  { "<", PgExpr::Opcode::PG_EXPR_LT },
94
  { "<=", PgExpr::Opcode::PG_EXPR_LE },
95
96
  { "avg", PgExpr::Opcode::PG_EXPR_AVG },
97
  { "sum", PgExpr::Opcode::PG_EXPR_SUM },
98
  { "count", PgExpr::Opcode::PG_EXPR_COUNT },
99
  { "max", PgExpr::Opcode::PG_EXPR_MAX },
100
  { "min", PgExpr::Opcode::PG_EXPR_MIN },
101
  { "eval_expr_call", PgExpr::Opcode::PG_EXPR_EVAL_EXPR_CALL }
102
};
103
104
PgExpr::PgExpr(Opcode opcode,
105
               const YBCPgTypeEntity *type_entity,
106
               bool collate_is_valid_non_c,
107
               const PgTypeAttrs *type_attrs)
108
    : opcode_(opcode), type_entity_(type_entity),
109
      collate_is_valid_non_c_(collate_is_valid_non_c),
110
62.3M
      type_attrs_(type_attrs ? *type_attrs : PgTypeAttrs({0})) {
111
62.3M
  DCHECK
(type_entity_) << "Datatype of result must be specified for expression"2.17k
;
112
62.3M
  DCHECK(type_entity_->yb_type != YB_YQL_DATA_TYPE_NOT_SUPPORTED &&
113
1.75k
         type_entity_->yb_type != YB_YQL_DATA_TYPE_UNKNOWN_DATA &&
114
1.75k
         type_entity_->yb_type != YB_YQL_DATA_TYPE_NULL_VALUE_TYPE)
115
1.75k
    << "Invalid datatype for YSQL expressions";
116
18.4E
  DCHECK(type_entity_->datum_to_yb) << "Conversion from datum to YB format not defined";
117
18.4E
  DCHECK(type_entity_->yb_to_datum) << "Conversion from YB to datum format not defined";
118
62.3M
}
119
120
22.8k
Status PgExpr::CheckOperatorName(const char *name) {
121
22.8k
  auto iter = kOperatorNames.find(name);
122
22.8k
  if (iter == kOperatorNames.end()) {
123
0
    return STATUS_SUBSTITUTE(InvalidArgument, "Wrong operator name: $0", name);
124
0
  }
125
22.8k
  return Status::OK();
126
22.8k
}
127
128
22.8k
PgExpr::Opcode PgExpr::NameToOpcode(const char *name) {
129
22.8k
  auto iter = kOperatorNames.find(name);
130
18.4E
  DCHECK(iter != kOperatorNames.end()) << "Wrong operator name: " << name;
131
22.8k
  return iter->second;
132
22.8k
}
133
134
22.8k
bfpg::TSOpcode PgExpr::PGOpcodeToTSOpcode(const PgExpr::Opcode opcode) {
135
22.8k
  switch (opcode) {
136
6.01k
    case Opcode::PG_EXPR_COUNT:
137
6.01k
      return bfpg::TSOpcode::kCount;
138
139
32
    case Opcode::PG_EXPR_MAX:
140
32
      return bfpg::TSOpcode::kMax;
141
142
26
    case Opcode::PG_EXPR_MIN:
143
26
      return bfpg::TSOpcode::kMin;
144
145
16.8k
    case Opcode::PG_EXPR_EVAL_EXPR_CALL:
146
16.8k
      return bfpg::TSOpcode::kPgEvalExprCall;
147
148
0
    default:
149
0
      LOG(DFATAL) << "No supported TSOpcode for PG opcode: " << static_cast<int32_t>(opcode);
150
0
      return bfpg::TSOpcode::kNoOp;
151
22.8k
  }
152
22.8k
}
153
154
9
bfpg::TSOpcode PgExpr::OperandTypeToSumTSOpcode(InternalType type) {
155
9
  switch (type) {
156
0
    case InternalType::kInt8Value:
157
0
      return bfpg::TSOpcode::kSumInt8;
158
159
0
    case InternalType::kInt16Value:
160
0
      return bfpg::TSOpcode::kSumInt16;
161
162
5
    case InternalType::kInt32Value:
163
5
      return bfpg::TSOpcode::kSumInt32;
164
165
2
    case InternalType::kInt64Value:
166
2
      return bfpg::TSOpcode::kSumInt64;
167
168
0
    case InternalType::kFloatValue:
169
0
      return bfpg::TSOpcode::kSumFloat;
170
171
2
    case InternalType::kDoubleValue:
172
2
      return bfpg::TSOpcode::kSumDouble;
173
174
0
    default:
175
0
      LOG(DFATAL) << "No supported Sum TSOpcode for operand type: " << static_cast<int32_t>(type);
176
0
      return bfpg::TSOpcode::kNoOp;
177
9
  }
178
9
}
179
180
3.71M
Status PgExpr::PrepareForRead(PgDml *pg_stmt, PgsqlExpressionPB *expr_pb) {
181
  // For expression that doesn't need to be setup and prepared at construction time.
182
3.71M
  return Status::OK();
183
3.71M
}
184
185
22.3M
Status PgExpr::Eval(PgsqlExpressionPB *expr_pb) {
186
  // Expressions that are neither bind_variable nor constant don't need to be updated.
187
  // Only values for bind variables and constants need to be updated in the SQL requests.
188
22.3M
  return Status::OK();
189
22.3M
}
190
191
0
Status PgExpr::Eval(QLValuePB *result) {
192
  // Expressions that are neither bind_variable nor constant don't need to be updated.
193
  // Only values for bind variables and constants need to be updated in the SQL requests.
194
0
  return Status::OK();
195
0
}
196
197
void PgExpr::TranslateText(Slice *yb_cursor, const PgWireDataHeader& header, int index,
198
                           const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
199
38.8M
                           PgTuple *pg_tuple) {
200
38.8M
  if (header.is_null()) {
201
901k
    return pg_tuple->WriteNull(index, header);
202
901k
  }
203
204
  // Get data from RPC buffer.
205
37.9M
  int64_t data_size;
206
37.9M
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
207
37.9M
  yb_cursor->remove_prefix(read_size);
208
209
  // Expects data from DocDB matches the following format.
210
  // - Right trim spaces for CHAR type. This should be done by DocDB when evaluate SELECTed or
211
  //   RETURNed expression. Note that currently, Postgres layer (and not DocDB) evaluate
212
  //   expressions, so DocDB doesn't trim for CHAR type.
213
  // - NULL terminated string. This should be done by DocDB when serializing.
214
  // - Text size == strlen(). When sending data over the network, RPC layer would use the actual
215
  //   size of data being serialized including the '\0' character. This is not necessarily be the
216
  //   length of a string.
217
  // Find strlen() of STRING by right-trimming all '\0' characters.
218
37.9M
  const char* text = yb_cursor->cdata();
219
37.9M
  int64_t text_len = data_size - 1;
220
221
37.9M
  DCHECK(text_len >= 0 && text[text_len] == '\0' && (text_len == 0 || text[text_len - 1] != '\0'))
222
447
    << "Data received from DocDB does not have expected format";
223
224
37.9M
  pg_tuple->WriteDatum(index, type_entity->yb_to_datum(text, text_len, type_attrs));
225
37.9M
  yb_cursor->remove_prefix(data_size);
226
37.9M
}
227
228
void PgExpr::TranslateCollateText(
229
    Slice *yb_cursor, const PgWireDataHeader& header, int index,
230
296
    const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs, PgTuple *pg_tuple) {
231
296
  if (header.is_null()) {
232
0
    return pg_tuple->WriteNull(index, header);
233
0
  }
234
235
  // Get data from RPC buffer.
236
296
  int64_t data_size;
237
296
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
238
296
  yb_cursor->remove_prefix(read_size);
239
240
  // See comments in PgExpr::TranslateText.
241
296
  const char* text = yb_cursor->cdata();
242
296
  int64_t text_len = data_size - 1;
243
244
296
  DCHECK(text_len >= 0 && text[text_len] == '\0')
245
0
    << "Data received from DocDB does not have expected format";
246
296
  const bool is_original_value = (text_len == 0 || text[0] != '\0');
247
296
  if (is_original_value) {
248
    // This means that we have done storage space optimization to only store the
249
    // original value for non-key columns.
250
296
    pg_tuple->WriteDatum(index, type_entity->yb_to_datum(text, text_len, type_attrs));
251
296
  } else {
252
    // This is a collation encoded string, we need to fetch the original value.
253
0
    CHECK_GE(text_len, 3);
254
0
    uint8_t collation_flags = text[1];
255
0
    CHECK_EQ(collation_flags, kCollationMarker | kDeterministicCollation);
256
    // Skip the collation and sortkey get the original character value.
257
0
    const char *p = static_cast<const char*>(memchr(text + 2, '\0', text_len - 2));
258
0
    CHECK(p);
259
0
    ++p;
260
0
    const char* end = text + text_len;
261
0
    CHECK_LE(p, end);
262
0
    pg_tuple->WriteDatum(index, type_entity->yb_to_datum(p, end - p, type_attrs));
263
0
  }
264
296
  yb_cursor->remove_prefix(data_size);
265
296
}
266
267
void PgExpr::TranslateBinary(Slice *yb_cursor, const PgWireDataHeader& header, int index,
268
                             const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
269
68.7M
                             PgTuple *pg_tuple) {
270
68.7M
  if (header.is_null()) {
271
62.6M
    return pg_tuple->WriteNull(index, header);
272
62.6M
  }
273
6.04M
  int64_t data_size;
274
6.04M
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
275
6.04M
  yb_cursor->remove_prefix(read_size);
276
277
6.04M
  pg_tuple->WriteDatum(index, type_entity->yb_to_datum(yb_cursor->data(), data_size, type_attrs));
278
6.04M
  yb_cursor->remove_prefix(data_size);
279
6.04M
}
280
281
282
// Expects a serialized string representation of YB Decimal.
283
void PgExpr::TranslateDecimal(Slice *yb_cursor, const PgWireDataHeader& header, int index,
284
                              const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
285
8.33k
                              PgTuple *pg_tuple) {
286
8.33k
  if (header.is_null()) {
287
39
    return pg_tuple->WriteNull(index, header);
288
39
  }
289
290
  // Get the value size.
291
8.29k
  int64_t data_size;
292
8.29k
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
293
8.29k
  yb_cursor->remove_prefix(read_size);
294
295
  // Read the decimal value from Protobuf and decode it to internal format.
296
8.29k
  std::string serialized_decimal;
297
8.29k
  read_size = PgDocData::ReadString(yb_cursor, &serialized_decimal, data_size);
298
8.29k
  yb_cursor->remove_prefix(read_size);
299
8.29k
  util::Decimal yb_decimal;
300
8.29k
  if (!yb_decimal.DecodeFromComparable(serialized_decimal).ok()) {
301
0
    LOG(FATAL) << "Failed to deserialize DECIMAL from " << serialized_decimal;
302
0
    return;
303
0
  }
304
305
  // Translate to decimal format and write to datum.
306
8.29k
  auto plaintext = yb_decimal.ToString();
307
8.29k
  pg_tuple->WriteDatum(index, type_entity->yb_to_datum(plaintext.c_str(), data_size, type_attrs));
308
8.29k
}
309
310
//--------------------------------------------------------------------------------------------------
311
// Translating system columns.
312
void PgExpr::TranslateSysCol(Slice *yb_cursor, const PgWireDataHeader& header, PgTuple *pg_tuple,
313
43.2M
                             uint8_t **pgbuf) {
314
43.2M
  *pgbuf = nullptr;
315
43.2M
  if (header.is_null()) {
316
0
    return;
317
0
  }
318
319
43.2M
  int64_t data_size;
320
43.2M
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
321
43.2M
  yb_cursor->remove_prefix(read_size);
322
323
43.2M
  pg_tuple->Write(pgbuf, header, yb_cursor->data(), data_size);
324
43.2M
  yb_cursor->remove_prefix(data_size);
325
43.2M
}
326
327
void PgExpr::TranslateData(Slice *yb_cursor, const PgWireDataHeader& header, int index,
328
649M
                           PgTuple *pg_tuple) const {
329
649M
  CHECK
(translate_data_) << "Data format translation is not provided"17.3k
;
330
649M
  translate_data_(yb_cursor, header, index, type_entity_, &type_attrs_, pg_tuple);
331
649M
}
332
333
bool PgExpr::TranslateNumberHelper(
334
    const PgWireDataHeader& header, int index, const YBCPgTypeEntity *type_entity,
335
490M
    PgTuple *pg_tuple) {
336
490M
  if (header.is_null()) {
337
62.1k
    pg_tuple->WriteNull(index, header);
338
62.1k
    return true;
339
62.1k
  }
340
341
18.4E
  DCHECK(type_entity) << "Type entity not provided";
342
18.4E
  DCHECK(type_entity->yb_to_datum) << "Type entity converter not provided";
343
490M
  return false;
344
490M
}
345
346
void PgExpr::TranslateCtid(Slice *yb_cursor, const PgWireDataHeader& header, int index,
347
                           const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
348
0
                           PgTuple *pg_tuple) {
349
0
  TranslateSysCol<uint64_t>(yb_cursor, header, &pg_tuple->syscols()->ctid);
350
0
}
351
352
void PgExpr::TranslateOid(Slice *yb_cursor, const PgWireDataHeader& header, int index,
353
                          const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
354
8.12M
                          PgTuple *pg_tuple) {
355
8.12M
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->oid);
356
8.12M
}
357
358
void PgExpr::TranslateTableoid(Slice *yb_cursor, const PgWireDataHeader& header, int index,
359
                               const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
360
0
                               PgTuple *pg_tuple) {
361
0
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->tableoid);
362
0
}
363
364
void PgExpr::TranslateXmin(Slice *yb_cursor, const PgWireDataHeader& header, int index,
365
                           const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
366
0
                           PgTuple *pg_tuple) {
367
0
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->xmin);
368
0
}
369
370
void PgExpr::TranslateCmin(Slice *yb_cursor, const PgWireDataHeader& header, int index,
371
                           const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
372
0
                           PgTuple *pg_tuple) {
373
0
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->cmin);
374
0
}
375
376
void PgExpr::TranslateXmax(Slice *yb_cursor, const PgWireDataHeader& header, int index,
377
                           const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
378
0
                           PgTuple *pg_tuple) {
379
0
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->xmax);
380
0
}
381
382
void PgExpr::TranslateCmax(Slice *yb_cursor, const PgWireDataHeader& header, int index,
383
                           const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
384
0
                           PgTuple *pg_tuple) {
385
0
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->cmax);
386
0
}
387
388
void PgExpr::TranslateYBCtid(Slice *yb_cursor, const PgWireDataHeader& header, int index,
389
                             const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
390
40.7M
                             PgTuple *pg_tuple) {
391
40.7M
  TranslateSysCol(yb_cursor, header, pg_tuple, &pg_tuple->syscols()->ybctid);
392
40.7M
}
393
394
void PgExpr::TranslateYBBasectid(Slice *yb_cursor, const PgWireDataHeader& header, int index,
395
                                 const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
396
2.45M
                                 PgTuple *pg_tuple) {
397
2.45M
  TranslateSysCol(yb_cursor, header, pg_tuple, &pg_tuple->syscols()->ybbasectid);
398
2.45M
}
399
400
71.1M
InternalType PgExpr::internal_type() const {
401
71.1M
  DCHECK
(type_entity_) << "Type entity is not set up"1.05k
;
402
71.1M
  return client::YBColumnSchema::ToInternalDataType(
403
71.1M
      QLType::Create(static_cast<DataType>(type_entity_->yb_type)));
404
71.1M
}
405
406
11.9k
int PgExpr::get_pg_typid() const {
407
11.9k
  return type_entity_->type_oid;
408
11.9k
}
409
410
11.9k
int PgExpr::get_pg_typmod() const {
411
11.9k
  return type_attrs_.typmod;
412
11.9k
}
413
414
11.9k
int PgExpr::get_pg_collid() const {
415
  // We do not support collations in DocDB, in future a field should be added to set, store and
416
  // pass around a collation id. For now, return a dummy value.
417
  // TODO
418
11.9k
  return 0;  /* InvalidOid */
419
11.9k
}
420
421
59.6M
void PgExpr::InitializeTranslateData() {
422
59.6M
  switch (type_entity_->yb_type) {
423
2.28M
    case YB_YQL_DATA_TYPE_INT8:
424
2.28M
      translate_data_ = TranslateNumber<int8_t>;
425
2.28M
      break;
426
427
1.26M
    case YB_YQL_DATA_TYPE_INT16:
428
1.26M
      translate_data_ = TranslateNumber<int16_t>;
429
1.26M
      break;
430
431
21.1M
    case YB_YQL_DATA_TYPE_INT32:
432
21.1M
      translate_data_ = TranslateNumber<int32_t>;
433
21.1M
      break;
434
435
970k
    case YB_YQL_DATA_TYPE_INT64:
436
970k
      translate_data_ = TranslateNumber<int64_t>;
437
970k
      break;
438
439
9.55M
    case YB_YQL_DATA_TYPE_UINT32:
440
9.55M
      translate_data_ = TranslateNumber<uint32_t>;
441
9.55M
      break;
442
443
4.36k
    case YB_YQL_DATA_TYPE_UINT64:
444
4.36k
      translate_data_ = TranslateNumber<uint64_t>;
445
4.36k
      break;
446
447
9.14M
    case YB_YQL_DATA_TYPE_STRING:
448
9.14M
      if (collate_is_valid_non_c_) {
449
110
        translate_data_ = TranslateCollateText;
450
9.14M
      } else {
451
9.14M
        translate_data_ = TranslateText;
452
9.14M
      }
453
9.14M
      break;
454
455
4.36M
    case YB_YQL_DATA_TYPE_BOOL:
456
4.36M
      translate_data_ = TranslateNumber<bool>;
457
4.36M
      break;
458
459
322k
    case YB_YQL_DATA_TYPE_FLOAT:
460
322k
      translate_data_ = TranslateNumber<float>;
461
322k
      break;
462
463
438k
    case YB_YQL_DATA_TYPE_DOUBLE:
464
438k
      translate_data_ = TranslateNumber<double>;
465
438k
      break;
466
467
10.1M
    case YB_YQL_DATA_TYPE_BINARY:
468
10.1M
      translate_data_ = TranslateBinary;
469
10.1M
      break;
470
471
0
    case YB_YQL_DATA_TYPE_TIMESTAMP:
472
0
      translate_data_ = TranslateNumber<int64_t>;
473
0
      break;
474
475
8.79k
    case YB_YQL_DATA_TYPE_DECIMAL:
476
8.79k
      translate_data_ = TranslateDecimal;
477
8.79k
      break;
478
479
1.38k
    case YB_YQL_DATA_TYPE_GIN_NULL:
480
1.38k
      translate_data_ = TranslateNumber<uint8_t>;
481
1.38k
      break;
482
483
0
    YB_PG_UNSUPPORTED_TYPES_IN_SWITCH:
484
0
    YB_PG_INVALID_TYPES_IN_SWITCH:
485
0
      LOG(DFATAL) << "Internal error: unsupported type " << type_entity_->yb_type;
486
59.6M
  }
487
59.6M
}
488
489
//--------------------------------------------------------------------------------------------------
490
491
PgConstant::PgConstant(const YBCPgTypeEntity *type_entity,
492
                       bool collate_is_valid_non_c,
493
                       const char *collation_sortkey,
494
                       uint64_t datum,
495
                       bool is_null,
496
                       PgExpr::Opcode opcode)
497
    : PgExpr(opcode, type_entity, collate_is_valid_non_c),
498
39.9M
      collation_sortkey_(collation_sortkey) {
499
500
39.9M
  switch (type_entity_->yb_type) {
501
411k
    case YB_YQL_DATA_TYPE_INT8:
502
411k
      if (!is_null) {
503
411k
        int8_t value;
504
411k
        type_entity_->datum_to_yb(datum, &value, nullptr);
505
411k
        ql_value_.set_int8_value(value);
506
411k
      }
507
411k
      break;
508
509
264k
    case YB_YQL_DATA_TYPE_INT16:
510
264k
      if (!is_null) {
511
264k
        int16_t value;
512
264k
        type_entity_->datum_to_yb(datum, &value, nullptr);
513
264k
        ql_value_.set_int16_value(value);
514
264k
      }
515
264k
      break;
516
517
19.1M
    case YB_YQL_DATA_TYPE_INT32:
518
19.1M
      if (!is_null) {
519
18.3M
        int32_t value;
520
18.3M
        type_entity_->datum_to_yb(datum, &value, nullptr);
521
18.3M
        ql_value_.set_int32_value(value);
522
18.3M
      }
523
19.1M
      break;
524
525
464k
    case YB_YQL_DATA_TYPE_INT64:
526
464k
      if (!is_null) {
527
462k
        int64_t value;
528
462k
        if (PREDICT_TRUE(!FLAGS_TEST_do_not_add_enum_sort_order)) {
529
462k
          type_entity_->datum_to_yb(datum, &value, nullptr);
530
462k
        } else {
531
          // pass &value as the third argument to tell datum_to_yb not
532
          // to add sort order to datum.
533
17
          type_entity_->datum_to_yb(datum, &value, &value);
534
17
        }
535
462k
        ql_value_.set_int64_value(value);
536
462k
      }
537
464k
      break;
538
539
3.47M
    case YB_YQL_DATA_TYPE_UINT32:
540
3.47M
      if (!is_null) {
541
3.47M
        uint32_t value;
542
3.47M
        type_entity_->datum_to_yb(datum, &value, nullptr);
543
3.47M
        ql_value_.set_uint32_value(value);
544
3.47M
      }
545
3.47M
      break;
546
547
38
    case YB_YQL_DATA_TYPE_UINT64:
548
38
      if (!is_null) {
549
38
        uint64_t value;
550
38
        type_entity_->datum_to_yb(datum, &value, nullptr);
551
38
        ql_value_.set_uint64_value(value);
552
38
      }
553
38
      break;
554
555
7.23M
    case YB_YQL_DATA_TYPE_STRING:
556
7.23M
      if (!is_null) {
557
6.95M
        char *value;
558
6.95M
        int64_t bytes = type_entity_->datum_fixed_size;
559
6.95M
        type_entity_->datum_to_yb(datum, &value, &bytes);
560
6.95M
        if (collate_is_valid_non_c_) {
561
2
          CHECK(collation_sortkey_);
562
          // Once YSQL supports non-deterministic collations, we need to compute
563
          // the deterministic attribute properly.
564
2
          string collstr = MakeCollationEncodedString(value, bytes,
565
2
            kCollationMarker | kDeterministicCollation, collation_sortkey_);
566
2
          ql_value_.set_string_value(std::move(collstr));
567
6.95M
        } else {
568
6.95M
          CHECK(!collation_sortkey_);
569
6.95M
          ql_value_.set_string_value(value, bytes);
570
6.95M
        }
571
6.95M
      }
572
7.23M
      break;
573
574
641k
    case YB_YQL_DATA_TYPE_BOOL:
575
641k
      if (!is_null) {
576
641k
        bool value;
577
641k
        type_entity_->datum_to_yb(datum, &value, nullptr);
578
641k
        ql_value_.set_bool_value(value);
579
641k
      }
580
641k
      break;
581
582
35.3k
    case YB_YQL_DATA_TYPE_FLOAT:
583
35.3k
      if (!is_null) {
584
35.3k
        float value;
585
35.3k
        type_entity_->datum_to_yb(datum, &value, nullptr);
586
35.3k
        ql_value_.set_float_value(value);
587
35.3k
      }
588
35.3k
      break;
589
590
438k
    case YB_YQL_DATA_TYPE_DOUBLE:
591
438k
      if (!is_null) {
592
437k
        double value;
593
437k
        type_entity_->datum_to_yb(datum, &value, nullptr);
594
437k
        ql_value_.set_double_value(value);
595
437k
      }
596
438k
      break;
597
598
7.87M
    case YB_YQL_DATA_TYPE_BINARY:
599
7.87M
      if (!is_null) {
600
7.30M
        uint8_t *value;
601
7.30M
        int64_t bytes = type_entity_->datum_fixed_size;
602
7.30M
        type_entity_->datum_to_yb(datum, &value, &bytes);
603
7.30M
        ql_value_.set_binary_value(value, bytes);
604
7.30M
      }
605
7.87M
      break;
606
607
0
    case YB_YQL_DATA_TYPE_TIMESTAMP:
608
0
      if (!is_null) {
609
0
        int64_t value;
610
0
        type_entity_->datum_to_yb(datum, &value, nullptr);
611
0
        ql_value_.set_int64_value(value);
612
0
      }
613
0
      break;
614
615
4.62k
    case YB_YQL_DATA_TYPE_DECIMAL:
616
4.62k
      if (!is_null) {
617
4.61k
        char* plaintext;
618
        // Calls YBCDatumToDecimalText in yb_type.c
619
4.61k
        type_entity_->datum_to_yb(datum, &plaintext, nullptr);
620
4.61k
        util::Decimal yb_decimal(plaintext);
621
4.61k
        ql_value_.set_decimal_value(yb_decimal.EncodeToComparable());
622
4.61k
      }
623
4.62k
      break;
624
625
1.38k
    case YB_YQL_DATA_TYPE_GIN_NULL:
626
1.38k
      CHECK
(is_null) << "gin null type should be marked null"0
;
627
1.38k
      uint8_t value;
628
1.38k
      type_entity_->datum_to_yb(datum, &value, nullptr);
629
1.38k
      ql_value_.set_gin_null_value(value);
630
1.38k
      break;
631
632
0
    YB_PG_UNSUPPORTED_TYPES_IN_SWITCH:
633
0
    YB_PG_INVALID_TYPES_IN_SWITCH:
634
0
      LOG(DFATAL) << "Internal error: unsupported type " << type_entity_->yb_type;
635
39.9M
  }
636
637
39.9M
  InitializeTranslateData();
638
39.9M
}
639
640
PgConstant::PgConstant(const YBCPgTypeEntity *type_entity,
641
                       bool collate_is_valid_non_c,
642
                       PgDatumKind datum_kind,
643
                       PgExpr::Opcode opcode)
644
50
    : PgExpr(opcode, type_entity, collate_is_valid_non_c), collation_sortkey_(nullptr) {
645
50
  switch (datum_kind) {
646
0
    case PgDatumKind::YB_YQL_DATUM_STANDARD_VALUE:
647
      // Leave the result as NULL.
648
0
      break;
649
3
    case PgDatumKind::YB_YQL_DATUM_LIMIT_MAX:
650
3
      ql_value_.set_virtual_value(QLVirtualValuePB::LIMIT_MAX);
651
3
      break;
652
47
    case PgDatumKind::YB_YQL_DATUM_LIMIT_MIN:
653
47
      ql_value_.set_virtual_value(QLVirtualValuePB::LIMIT_MIN);
654
47
      break;
655
50
  }
656
50
  InitializeTranslateData();
657
50
}
658
659
0
void PgConstant::UpdateConstant(int8_t value, bool is_null) {
660
0
  if (is_null) {
661
0
    ql_value_.Clear();
662
0
  } else {
663
0
    ql_value_.set_int8_value(value);
664
0
  }
665
0
}
666
667
43
void PgConstant::UpdateConstant(int16_t value, bool is_null) {
668
43
  if (is_null) {
669
0
    ql_value_.Clear();
670
43
  } else {
671
43
    ql_value_.set_int16_value(value);
672
43
  }
673
43
}
674
675
111
void PgConstant::UpdateConstant(int32_t value, bool is_null) {
676
111
  if (is_null) {
677
0
    ql_value_.Clear();
678
111
  } else {
679
111
    ql_value_.set_int32_value(value);
680
111
  }
681
111
}
682
683
1.02k
void PgConstant::UpdateConstant(int64_t value, bool is_null) {
684
1.02k
  if (is_null) {
685
0
    ql_value_.Clear();
686
1.02k
  } else {
687
1.02k
    ql_value_.set_int64_value(value);
688
1.02k
  }
689
1.02k
}
690
691
43
void PgConstant::UpdateConstant(float value, bool is_null) {
692
43
  if (is_null) {
693
0
    ql_value_.Clear();
694
43
  } else {
695
43
    ql_value_.set_float_value(value);
696
43
  }
697
43
}
698
699
0
void PgConstant::UpdateConstant(double value, bool is_null) {
700
0
  if (is_null) {
701
0
    ql_value_.Clear();
702
0
  } else {
703
0
    ql_value_.set_double_value(value);
704
0
  }
705
0
}
706
707
2.00k
void PgConstant::UpdateConstant(const char *value, bool is_null) {
708
2.00k
  if (is_null) {
709
0
    ql_value_.Clear();
710
2.00k
  } else {
711
    // Currently this is only used in C++ test code. In the future if this
712
    // is used in production code we need to consider collation encoding.
713
2.00k
    CHECK(!collate_is_valid_non_c_);
714
2.00k
    ql_value_.set_string_value(value);
715
2.00k
  }
716
2.00k
}
717
718
36
void PgConstant::UpdateConstant(const void *value, size_t bytes, bool is_null) {
719
36
  if (is_null) {
720
0
    ql_value_.Clear();
721
36
  } else {
722
    // Currently this is only used in C++ test code. In the future if this
723
    // is used in production code we need to consider collation encoding.
724
36
    CHECK(!collate_is_valid_non_c_);
725
36
    ql_value_.set_binary_value(value, bytes);
726
36
  }
727
36
}
728
729
34.8M
Status PgConstant::Eval(PgsqlExpressionPB *expr_pb) {
730
34.8M
  QLValuePB *result = expr_pb->mutable_value();
731
34.8M
  *result = ql_value_;
732
34.8M
  return Status::OK();
733
34.8M
}
734
735
5.10M
Status PgConstant::Eval(QLValuePB *result) {
736
5.10M
  CHECK(result != nullptr);
737
5.10M
  *result = ql_value_;
738
5.10M
  return Status::OK();
739
5.10M
}
740
741
//--------------------------------------------------------------------------------------------------
742
743
PgColumnRef::PgColumnRef(int attr_num,
744
                         const YBCPgTypeEntity *type_entity,
745
                         bool collate_is_valid_non_c,
746
                         const PgTypeAttrs *type_attrs)
747
    : PgExpr(PgExpr::Opcode::PG_EXPR_COLREF, type_entity,
748
22.3M
             collate_is_valid_non_c, type_attrs), attr_num_(attr_num) {
749
750
22.3M
  if (attr_num_ < 0) {
751
    // Setup system columns.
752
2.68M
    switch (attr_num_) {
753
0
      case static_cast<int>(PgSystemAttrNum::kSelfItemPointer):
754
0
        translate_data_ = TranslateCtid;
755
0
        break;
756
748k
      case static_cast<int>(PgSystemAttrNum::kObjectId):
757
748k
        translate_data_ = TranslateOid;
758
748k
        break;
759
0
      case static_cast<int>(PgSystemAttrNum::kMinTransactionId):
760
0
        translate_data_ = TranslateXmin;
761
0
        break;
762
0
      case static_cast<int>(PgSystemAttrNum::kMinCommandId):
763
0
        translate_data_ = TranslateCmin;
764
0
        break;
765
0
      case static_cast<int>(PgSystemAttrNum::kMaxTransactionId):
766
0
        translate_data_ = TranslateXmax;
767
0
        break;
768
0
      case static_cast<int>(PgSystemAttrNum::kMaxCommandId):
769
0
        translate_data_ = TranslateCmax;
770
0
        break;
771
0
      case static_cast<int>(PgSystemAttrNum::kTableOid):
772
0
        translate_data_ = TranslateTableoid;
773
0
        break;
774
1.38M
      case static_cast<int>(PgSystemAttrNum::kYBTupleId):
775
1.38M
        translate_data_ = TranslateYBCtid;
776
1.38M
        break;
777
552k
      case static_cast<int>(PgSystemAttrNum::kYBIdxBaseTupleId):
778
552k
        translate_data_ = TranslateYBBasectid;
779
552k
        break;
780
2.68M
    }
781
19.6M
  } else {
782
    // Setup regular columns.
783
19.6M
    InitializeTranslateData();
784
19.6M
  }
785
22.3M
}
786
787
22.0M
bool PgColumnRef::is_ybbasetid() const {
788
22.0M
  return attr_num_ == static_cast<int>(PgSystemAttrNum::kYBIdxBaseTupleId);
789
22.0M
}
790
791
22.3M
Status PgColumnRef::PrepareForRead(PgDml *pg_stmt, PgsqlExpressionPB *expr_pb) {
792
22.3M
  RETURN_NOT_OK(pg_stmt->PrepareColumnForRead(attr_num_, expr_pb));
793
22.3M
  return Status::OK();
794
22.3M
}
795
796
//--------------------------------------------------------------------------------------------------
797
798
PgOperator::PgOperator(const char *opname,
799
                       const YBCPgTypeEntity *type_entity,
800
                       bool collate_is_valid_non_c)
801
    : PgExpr(NameToOpcode(opname), type_entity, collate_is_valid_non_c),
802
22.8k
      opname_(opname) {
803
22.8k
  InitializeTranslateData();
804
22.8k
}
805
806
22.8k
void PgOperator::AppendArg(PgExpr *arg) {
807
22.8k
  args_.push_back(arg);
808
22.8k
}
809
810
22.8k
Status PgOperator::PrepareForRead(PgDml *pg_stmt, PgsqlExpressionPB *expr_pb) {
811
22.8k
  PgsqlBCallPB *tscall = expr_pb->mutable_tscall();
812
22.8k
  bfpg::TSOpcode tsopcode;
813
22.8k
  if (opcode_ == Opcode::PG_EXPR_SUM) {
814
    // SUM is special case as it has input type of the operand column but output
815
    // type of a larger similar type (e.g. INT64 for integers).
816
9
    tsopcode = OperandTypeToSumTSOpcode(args_.front()->internal_type());
817
22.8k
  } else {
818
22.8k
    tsopcode = PGOpcodeToTSOpcode(opcode_);
819
22.8k
  }
820
22.8k
  tscall->set_opcode(static_cast<int32_t>(tsopcode));
821
22.8k
  for (const auto& arg : args_) {
822
22.8k
    PgsqlExpressionPB *op = tscall->add_operands();
823
22.8k
    RETURN_NOT_OK(arg->PrepareForRead(pg_stmt, op));
824
22.8k
    RETURN_NOT_OK(arg->Eval(op));
825
22.8k
  }
826
22.8k
  return Status::OK();
827
22.8k
}
828
829
}  // namespace pggate
830
}  // namespace yb