YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
0
  const char* value, int64_t bytes, uint8_t collation_flags, const char* sortkey) {
49
50
  // A postgres character value cannot have \0 byte.
51
0
  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
0
  string collstr;
56
0
  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
0
  collstr.append(1, '\0');
62
0
  static_assert(sizeof(collation_flags) == 1, "invalid size");
63
0
  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
0
  collstr.append(sortkey);
69
70
  // Append a \0 byte which acts as a separator between sort key and the
71
  // original value.
72
0
  collstr.append(1, '\0');
73
74
  // Add the original value.
75
0
  collstr.append(value, bytes);
76
77
0
  return collstr;
78
0
}
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
21.2M
      type_attrs_(type_attrs ? *type_attrs : PgTypeAttrs({0})) {
111
320
  DCHECK(type_entity_) << "Datatype of result must be specified for expression";
112
18.4E
  DCHECK(type_entity_->yb_type != YB_YQL_DATA_TYPE_NOT_SUPPORTED &&
113
18.4E
         type_entity_->yb_type != YB_YQL_DATA_TYPE_UNKNOWN_DATA &&
114
18.4E
         type_entity_->yb_type != YB_YQL_DATA_TYPE_NULL_VALUE_TYPE)
115
18.4E
    << "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
21.2M
}
119
120
5.98k
Status PgExpr::CheckOperatorName(const char *name) {
121
5.98k
  auto iter = kOperatorNames.find(name);
122
5.98k
  if (iter == kOperatorNames.end()) {
123
0
    return STATUS_SUBSTITUTE(InvalidArgument, "Wrong operator name: $0", name);
124
0
  }
125
5.98k
  return Status::OK();
126
5.98k
}
127
128
5.98k
PgExpr::Opcode PgExpr::NameToOpcode(const char *name) {
129
5.98k
  auto iter = kOperatorNames.find(name);
130
0
  DCHECK(iter != kOperatorNames.end()) << "Wrong operator name: " << name;
131
5.98k
  return iter->second;
132
5.98k
}
133
134
5.97k
bfpg::TSOpcode PgExpr::PGOpcodeToTSOpcode(const PgExpr::Opcode opcode) {
135
5.97k
  switch (opcode) {
136
153
    case Opcode::PG_EXPR_COUNT:
137
153
      return bfpg::TSOpcode::kCount;
138
139
31
    case Opcode::PG_EXPR_MAX:
140
31
      return bfpg::TSOpcode::kMax;
141
142
21
    case Opcode::PG_EXPR_MIN:
143
21
      return bfpg::TSOpcode::kMin;
144
145
5.76k
    case Opcode::PG_EXPR_EVAL_EXPR_CALL:
146
5.76k
      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
5.97k
  }
152
5.97k
}
153
154
16
bfpg::TSOpcode PgExpr::OperandTypeToSumTSOpcode(InternalType type) {
155
16
  switch (type) {
156
0
    case InternalType::kInt8Value:
157
0
      return bfpg::TSOpcode::kSumInt8;
158
159
2
    case InternalType::kInt16Value:
160
2
      return bfpg::TSOpcode::kSumInt16;
161
162
6
    case InternalType::kInt32Value:
163
6
      return bfpg::TSOpcode::kSumInt32;
164
165
4
    case InternalType::kInt64Value:
166
4
      return bfpg::TSOpcode::kSumInt64;
167
168
2
    case InternalType::kFloatValue:
169
2
      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
16
  }
178
16
}
179
180
1.58M
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
1.58M
  return Status::OK();
183
1.58M
}
184
185
7.55M
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
7.55M
  return Status::OK();
189
7.55M
}
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
14.0M
                           PgTuple *pg_tuple) {
200
14.0M
  if (header.is_null()) {
201
202k
    return pg_tuple->WriteNull(index, header);
202
202k
  }
203
204
  // Get data from RPC buffer.
205
13.8M
  int64_t data_size;
206
13.8M
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
207
13.8M
  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
13.8M
  const char* text = yb_cursor->cdata();
219
13.8M
  int64_t text_len = data_size - 1;
220
221
246
  DCHECK(text_len >= 0 && text[text_len] == '\0' && (text_len == 0 || text[text_len - 1] != '\0'))
222
246
    << "Data received from DocDB does not have expected format";
223
224
13.8M
  pg_tuple->WriteDatum(index, type_entity->yb_to_datum(text, text_len, type_attrs));
225
13.8M
  yb_cursor->remove_prefix(data_size);
226
13.8M
}
227
228
void PgExpr::TranslateCollateText(
229
    Slice *yb_cursor, const PgWireDataHeader& header, int index,
230
9
    const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs, PgTuple *pg_tuple) {
231
9
  if (header.is_null()) {
232
6
    return pg_tuple->WriteNull(index, header);
233
6
  }
234
235
  // Get data from RPC buffer.
236
3
  int64_t data_size;
237
3
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
238
3
  yb_cursor->remove_prefix(read_size);
239
240
  // See comments in PgExpr::TranslateText.
241
3
  const char* text = yb_cursor->cdata();
242
3
  int64_t text_len = data_size - 1;
243
244
0
  DCHECK(text_len >= 0 && text[text_len] == '\0')
245
0
    << "Data received from DocDB does not have expected format";
246
3
  const bool is_original_value = (text_len == 0 || text[0] != '\0');
247
3
  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
3
    pg_tuple->WriteDatum(index, type_entity->yb_to_datum(text, text_len, type_attrs));
251
0
  } 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
3
  yb_cursor->remove_prefix(data_size);
265
3
}
266
267
void PgExpr::TranslateBinary(Slice *yb_cursor, const PgWireDataHeader& header, int index,
268
                             const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
269
22.5M
                             PgTuple *pg_tuple) {
270
22.5M
  if (header.is_null()) {
271
20.5M
    return pg_tuple->WriteNull(index, header);
272
20.5M
  }
273
1.93M
  int64_t data_size;
274
1.93M
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
275
1.93M
  yb_cursor->remove_prefix(read_size);
276
277
1.93M
  pg_tuple->WriteDatum(index, type_entity->yb_to_datum(yb_cursor->data(), data_size, type_attrs));
278
1.93M
  yb_cursor->remove_prefix(data_size);
279
1.93M
}
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.15k
                              PgTuple *pg_tuple) {
286
8.15k
  if (header.is_null()) {
287
0
    return pg_tuple->WriteNull(index, header);
288
0
  }
289
290
  // Get the value size.
291
8.15k
  int64_t data_size;
292
8.15k
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
293
8.15k
  yb_cursor->remove_prefix(read_size);
294
295
  // Read the decimal value from Protobuf and decode it to internal format.
296
8.15k
  std::string serialized_decimal;
297
8.15k
  read_size = PgDocData::ReadString(yb_cursor, &serialized_decimal, data_size);
298
8.15k
  yb_cursor->remove_prefix(read_size);
299
8.15k
  util::Decimal yb_decimal;
300
8.15k
  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.15k
  auto plaintext = yb_decimal.ToString();
307
8.15k
  pg_tuple->WriteDatum(index, type_entity->yb_to_datum(plaintext.c_str(), data_size, type_attrs));
308
8.15k
}
309
310
//--------------------------------------------------------------------------------------------------
311
// Translating system columns.
312
void PgExpr::TranslateSysCol(Slice *yb_cursor, const PgWireDataHeader& header, PgTuple *pg_tuple,
313
16.3M
                             uint8_t **pgbuf) {
314
16.3M
  *pgbuf = nullptr;
315
16.3M
  if (header.is_null()) {
316
0
    return;
317
0
  }
318
319
16.3M
  int64_t data_size;
320
16.3M
  size_t read_size = PgDocData::ReadNumber(yb_cursor, &data_size);
321
16.3M
  yb_cursor->remove_prefix(read_size);
322
323
16.3M
  pg_tuple->Write(pgbuf, header, yb_cursor->data(), data_size);
324
16.3M
  yb_cursor->remove_prefix(data_size);
325
16.3M
}
326
327
void PgExpr::TranslateData(Slice *yb_cursor, const PgWireDataHeader& header, int index,
328
227M
                           PgTuple *pg_tuple) const {
329
18.4E
  CHECK(translate_data_) << "Data format translation is not provided";
330
227M
  translate_data_(yb_cursor, header, index, type_entity_, &type_attrs_, pg_tuple);
331
227M
}
332
333
bool PgExpr::TranslateNumberHelper(
334
    const PgWireDataHeader& header, int index, const YBCPgTypeEntity *type_entity,
335
172M
    PgTuple *pg_tuple) {
336
172M
  if (header.is_null()) {
337
26.5k
    pg_tuple->WriteNull(index, header);
338
26.5k
    return true;
339
26.5k
  }
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
172M
  return false;
344
172M
}
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
2.42M
                          PgTuple *pg_tuple) {
355
2.42M
  TranslateSysCol<uint32_t>(yb_cursor, header, &pg_tuple->syscols()->oid);
356
2.42M
}
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
15.1M
                             PgTuple *pg_tuple) {
391
15.1M
  TranslateSysCol(yb_cursor, header, pg_tuple, &pg_tuple->syscols()->ybctid);
392
15.1M
}
393
394
void PgExpr::TranslateYBBasectid(Slice *yb_cursor, const PgWireDataHeader& header, int index,
395
                                 const YBCPgTypeEntity *type_entity, const PgTypeAttrs *type_attrs,
396
1.17M
                                 PgTuple *pg_tuple) {
397
1.17M
  TranslateSysCol(yb_cursor, header, pg_tuple, &pg_tuple->syscols()->ybbasectid);
398
1.17M
}
399
400
23.3M
InternalType PgExpr::internal_type() const {
401
64
  DCHECK(type_entity_) << "Type entity is not set up";
402
23.3M
  return client::YBColumnSchema::ToInternalDataType(
403
23.3M
      QLType::Create(static_cast<DataType>(type_entity_->yb_type)));
404
23.3M
}
405
406
3.93k
int PgExpr::get_pg_typid() const {
407
3.93k
  return type_entity_->type_oid;
408
3.93k
}
409
410
3.93k
int PgExpr::get_pg_typmod() const {
411
3.93k
  return type_attrs_.typmod;
412
3.93k
}
413
414
3.93k
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
3.93k
  return 0;  /* InvalidOid */
419
3.93k
}
420
421
20.2M
void PgExpr::InitializeTranslateData() {
422
20.2M
  switch (type_entity_->yb_type) {
423
692k
    case YB_YQL_DATA_TYPE_INT8:
424
692k
      translate_data_ = TranslateNumber<int8_t>;
425
692k
      break;
426
427
386k
    case YB_YQL_DATA_TYPE_INT16:
428
386k
      translate_data_ = TranslateNumber<int16_t>;
429
386k
      break;
430
431
8.70M
    case YB_YQL_DATA_TYPE_INT32:
432
8.70M
      translate_data_ = TranslateNumber<int32_t>;
433
8.70M
      break;
434
435
724k
    case YB_YQL_DATA_TYPE_INT64:
436
724k
      translate_data_ = TranslateNumber<int64_t>;
437
724k
      break;
438
439
2.93M
    case YB_YQL_DATA_TYPE_UINT32:
440
2.93M
      translate_data_ = TranslateNumber<uint32_t>;
441
2.93M
      break;
442
443
1.24k
    case YB_YQL_DATA_TYPE_UINT64:
444
1.24k
      translate_data_ = TranslateNumber<uint64_t>;
445
1.24k
      break;
446
447
2.05M
    case YB_YQL_DATA_TYPE_STRING:
448
2.05M
      if (collate_is_valid_non_c_) {
449
5
        translate_data_ = TranslateCollateText;
450
2.05M
      } else {
451
2.05M
        translate_data_ = TranslateText;
452
2.05M
      }
453
2.05M
      break;
454
455
1.33M
    case YB_YQL_DATA_TYPE_BOOL:
456
1.33M
      translate_data_ = TranslateNumber<bool>;
457
1.33M
      break;
458
459
91.9k
    case YB_YQL_DATA_TYPE_FLOAT:
460
91.9k
      translate_data_ = TranslateNumber<float>;
461
91.9k
      break;
462
463
342k
    case YB_YQL_DATA_TYPE_DOUBLE:
464
342k
      translate_data_ = TranslateNumber<double>;
465
342k
      break;
466
467
3.00M
    case YB_YQL_DATA_TYPE_BINARY:
468
3.00M
      translate_data_ = TranslateBinary;
469
3.00M
      break;
470
471
0
    case YB_YQL_DATA_TYPE_TIMESTAMP:
472
0
      translate_data_ = TranslateNumber<int64_t>;
473
0
      break;
474
475
11.7k
    case YB_YQL_DATA_TYPE_DECIMAL:
476
11.7k
      translate_data_ = TranslateDecimal;
477
11.7k
      break;
478
479
117
    case YB_YQL_DATA_TYPE_GIN_NULL:
480
117
      translate_data_ = TranslateNumber<uint8_t>;
481
117
      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
20.2M
  }
487
20.2M
}
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
13.6M
      collation_sortkey_(collation_sortkey) {
499
500
13.6M
  switch (type_entity_->yb_type) {
501
108k
    case YB_YQL_DATA_TYPE_INT8:
502
108k
      if (!is_null) {
503
108k
        int8_t value;
504
108k
        type_entity_->datum_to_yb(datum, &value, nullptr);
505
108k
        ql_value_.set_int8_value(value);
506
108k
      }
507
108k
      break;
508
509
72.6k
    case YB_YQL_DATA_TYPE_INT16:
510
72.6k
      if (!is_null) {
511
72.6k
        int16_t value;
512
72.6k
        type_entity_->datum_to_yb(datum, &value, nullptr);
513
72.6k
        ql_value_.set_int16_value(value);
514
72.6k
      }
515
72.6k
      break;
516
517
7.91M
    case YB_YQL_DATA_TYPE_INT32:
518
7.91M
      if (!is_null) {
519
7.51M
        int32_t value;
520
7.51M
        type_entity_->datum_to_yb(datum, &value, nullptr);
521
7.51M
        ql_value_.set_int32_value(value);
522
7.51M
      }
523
7.91M
      break;
524
525
346k
    case YB_YQL_DATA_TYPE_INT64:
526
346k
      if (!is_null) {
527
345k
        int64_t value;
528
345k
        if (PREDICT_TRUE(!FLAGS_TEST_do_not_add_enum_sort_order)) {
529
345k
          type_entity_->datum_to_yb(datum, &value, nullptr);
530
0
        } else {
531
          // pass &value as the third argument to tell datum_to_yb not
532
          // to add sort order to datum.
533
0
          type_entity_->datum_to_yb(datum, &value, &value);
534
0
        }
535
345k
        ql_value_.set_int64_value(value);
536
345k
      }
537
346k
      break;
538
539
1.00M
    case YB_YQL_DATA_TYPE_UINT32:
540
1.00M
      if (!is_null) {
541
1.00M
        uint32_t value;
542
1.00M
        type_entity_->datum_to_yb(datum, &value, nullptr);
543
1.00M
        ql_value_.set_uint32_value(value);
544
1.00M
      }
545
1.00M
      break;
546
547
0
    case YB_YQL_DATA_TYPE_UINT64:
548
0
      if (!is_null) {
549
0
        uint64_t value;
550
0
        type_entity_->datum_to_yb(datum, &value, nullptr);
551
0
        ql_value_.set_uint64_value(value);
552
0
      }
553
0
      break;
554
555
1.37M
    case YB_YQL_DATA_TYPE_STRING:
556
1.37M
      if (!is_null) {
557
1.34M
        char *value;
558
1.34M
        int64_t bytes = type_entity_->datum_fixed_size;
559
1.34M
        type_entity_->datum_to_yb(datum, &value, &bytes);
560
1.34M
        if (collate_is_valid_non_c_) {
561
0
          CHECK(collation_sortkey_);
562
          // Once YSQL supports non-deterministic collations, we need to compute
563
          // the deterministic attribute properly.
564
0
          string collstr = MakeCollationEncodedString(value, bytes,
565
0
            kCollationMarker | kDeterministicCollation, collation_sortkey_);
566
0
          ql_value_.set_string_value(std::move(collstr));
567
1.34M
        } else {
568
1.34M
          CHECK(!collation_sortkey_);
569
1.34M
          ql_value_.set_string_value(value, bytes);
570
1.34M
        }
571
1.34M
      }
572
1.37M
      break;
573
574
168k
    case YB_YQL_DATA_TYPE_BOOL:
575
168k
      if (!is_null) {
576
168k
        bool value;
577
168k
        type_entity_->datum_to_yb(datum, &value, nullptr);
578
168k
        ql_value_.set_bool_value(value);
579
168k
      }
580
168k
      break;
581
582
7.06k
    case YB_YQL_DATA_TYPE_FLOAT:
583
7.06k
      if (!is_null) {
584
7.06k
        float value;
585
7.06k
        type_entity_->datum_to_yb(datum, &value, nullptr);
586
7.06k
        ql_value_.set_float_value(value);
587
7.06k
      }
588
7.06k
      break;
589
590
342k
    case YB_YQL_DATA_TYPE_DOUBLE:
591
342k
      if (!is_null) {
592
342k
        double value;
593
342k
        type_entity_->datum_to_yb(datum, &value, nullptr);
594
342k
        ql_value_.set_double_value(value);
595
342k
      }
596
342k
      break;
597
598
2.30M
    case YB_YQL_DATA_TYPE_BINARY:
599
2.30M
      if (!is_null) {
600
2.14M
        uint8_t *value;
601
2.14M
        int64_t bytes = type_entity_->datum_fixed_size;
602
2.14M
        type_entity_->datum_to_yb(datum, &value, &bytes);
603
2.14M
        ql_value_.set_binary_value(value, bytes);
604
2.14M
      }
605
2.30M
      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.23k
    case YB_YQL_DATA_TYPE_DECIMAL:
616
4.23k
      if (!is_null) {
617
4.23k
        char* plaintext;
618
        // Calls YBCDatumToDecimalText in yb_type.c
619
4.23k
        type_entity_->datum_to_yb(datum, &plaintext, nullptr);
620
4.23k
        util::Decimal yb_decimal(plaintext);
621
4.23k
        ql_value_.set_decimal_value(yb_decimal.EncodeToComparable());
622
4.23k
      }
623
4.23k
      break;
624
625
117
    case YB_YQL_DATA_TYPE_GIN_NULL:
626
0
      CHECK(is_null) << "gin null type should be marked null";
627
117
      uint8_t value;
628
117
      type_entity_->datum_to_yb(datum, &value, nullptr);
629
117
      ql_value_.set_gin_null_value(value);
630
117
      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
13.6M
  }
636
637
13.6M
  InitializeTranslateData();
638
13.6M
}
639
640
PgConstant::PgConstant(const YBCPgTypeEntity *type_entity,
641
                       bool collate_is_valid_non_c,
642
                       PgDatumKind datum_kind,
643
                       PgExpr::Opcode opcode)
644
8
    : PgExpr(opcode, type_entity, collate_is_valid_non_c), collation_sortkey_(nullptr) {
645
8
  switch (datum_kind) {
646
0
    case PgDatumKind::YB_YQL_DATUM_STANDARD_VALUE:
647
      // Leave the result as NULL.
648
0
      break;
649
0
    case PgDatumKind::YB_YQL_DATUM_LIMIT_MAX:
650
0
      ql_value_.set_virtual_value(QLVirtualValuePB::LIMIT_MAX);
651
0
      break;
652
8
    case PgDatumKind::YB_YQL_DATUM_LIMIT_MIN:
653
8
      ql_value_.set_virtual_value(QLVirtualValuePB::LIMIT_MIN);
654
8
      break;
655
8
  }
656
8
  InitializeTranslateData();
657
8
}
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
0
void PgConstant::UpdateConstant(int16_t value, bool is_null) {
668
0
  if (is_null) {
669
0
    ql_value_.Clear();
670
0
  } else {
671
0
    ql_value_.set_int16_value(value);
672
0
  }
673
0
}
674
675
0
void PgConstant::UpdateConstant(int32_t value, bool is_null) {
676
0
  if (is_null) {
677
0
    ql_value_.Clear();
678
0
  } else {
679
0
    ql_value_.set_int32_value(value);
680
0
  }
681
0
}
682
683
0
void PgConstant::UpdateConstant(int64_t value, bool is_null) {
684
0
  if (is_null) {
685
0
    ql_value_.Clear();
686
0
  } else {
687
0
    ql_value_.set_int64_value(value);
688
0
  }
689
0
}
690
691
0
void PgConstant::UpdateConstant(float value, bool is_null) {
692
0
  if (is_null) {
693
0
    ql_value_.Clear();
694
0
  } else {
695
0
    ql_value_.set_float_value(value);
696
0
  }
697
0
}
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
0
void PgConstant::UpdateConstant(const char *value, bool is_null) {
708
0
  if (is_null) {
709
0
    ql_value_.Clear();
710
0
  } 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
0
    CHECK(!collate_is_valid_non_c_);
714
0
    ql_value_.set_string_value(value);
715
0
  }
716
0
}
717
718
0
void PgConstant::UpdateConstant(const void *value, size_t bytes, bool is_null) {
719
0
  if (is_null) {
720
0
    ql_value_.Clear();
721
0
  } 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
0
    CHECK(!collate_is_valid_non_c_);
725
0
    ql_value_.set_binary_value(value, bytes);
726
0
  }
727
0
}
728
729
11.3M
Status PgConstant::Eval(PgsqlExpressionPB *expr_pb) {
730
11.3M
  QLValuePB *result = expr_pb->mutable_value();
731
11.3M
  *result = ql_value_;
732
11.3M
  return Status::OK();
733
11.3M
}
734
735
2.31M
Status PgConstant::Eval(QLValuePB *result) {
736
2.31M
  CHECK(result != nullptr);
737
2.31M
  *result = ql_value_;
738
2.31M
  return Status::OK();
739
2.31M
}
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
7.55M
             collate_is_valid_non_c, type_attrs), attr_num_(attr_num) {
749
750
7.55M
  if (attr_num_ < 0) {
751
    // Setup system columns.
752
916k
    switch (attr_num_) {
753
0
      case static_cast<int>(PgSystemAttrNum::kSelfItemPointer):
754
0
        translate_data_ = TranslateCtid;
755
0
        break;
756
226k
      case static_cast<int>(PgSystemAttrNum::kObjectId):
757
226k
        translate_data_ = TranslateOid;
758
226k
        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
493k
      case static_cast<int>(PgSystemAttrNum::kYBTupleId):
775
493k
        translate_data_ = TranslateYBCtid;
776
493k
        break;
777
195k
      case static_cast<int>(PgSystemAttrNum::kYBIdxBaseTupleId):
778
195k
        translate_data_ = TranslateYBBasectid;
779
195k
        break;
780
6.63M
    }
781
6.63M
  } else {
782
    // Setup regular columns.
783
6.63M
    InitializeTranslateData();
784
6.63M
  }
785
7.55M
}
786
787
7.41M
bool PgColumnRef::is_ybbasetid() const {
788
7.41M
  return attr_num_ == static_cast<int>(PgSystemAttrNum::kYBIdxBaseTupleId);
789
7.41M
}
790
791
7.54M
Status PgColumnRef::PrepareForRead(PgDml *pg_stmt, PgsqlExpressionPB *expr_pb) {
792
7.54M
  RETURN_NOT_OK(pg_stmt->PrepareColumnForRead(attr_num_, expr_pb));
793
7.54M
  return Status::OK();
794
7.54M
}
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
5.98k
      opname_(opname) {
803
5.98k
  InitializeTranslateData();
804
5.98k
}
805
806
5.98k
void PgOperator::AppendArg(PgExpr *arg) {
807
5.98k
  args_.push_back(arg);
808
5.98k
}
809
810
5.98k
Status PgOperator::PrepareForRead(PgDml *pg_stmt, PgsqlExpressionPB *expr_pb) {
811
5.98k
  PgsqlBCallPB *tscall = expr_pb->mutable_tscall();
812
5.98k
  bfpg::TSOpcode tsopcode;
813
5.98k
  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
16
    tsopcode = OperandTypeToSumTSOpcode(args_.front()->internal_type());
817
5.97k
  } else {
818
5.97k
    tsopcode = PGOpcodeToTSOpcode(opcode_);
819
5.97k
  }
820
5.98k
  tscall->set_opcode(static_cast<int32_t>(tsopcode));
821
5.98k
  for (const auto& arg : args_) {
822
5.98k
    PgsqlExpressionPB *op = tscall->add_operands();
823
5.98k
    RETURN_NOT_OK(arg->PrepareForRead(pg_stmt, op));
824
5.98k
    RETURN_NOT_OK(arg->Eval(op));
825
5.98k
  }
826
5.98k
  return Status::OK();
827
5.98k
}
828
829
}  // namespace pggate
830
}  // namespace yb