YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/Users/deen/code/yugabyte-db/src/yb/common/schema.h
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
//
18
// The following only applies to changes made to this file as part of YugaByte development.
19
//
20
// Portions Copyright (c) YugaByte, Inc.
21
//
22
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
23
// in compliance with the License.  You may obtain a copy of the License at
24
//
25
// http://www.apache.org/licenses/LICENSE-2.0
26
//
27
// Unless required by applicable law or agreed to in writing, software distributed under the License
28
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
29
// or implied.  See the License for the specific language governing permissions and limitations
30
// under the License.
31
//
32
#ifndef YB_COMMON_SCHEMA_H
33
#define YB_COMMON_SCHEMA_H
34
35
#include <functional>
36
#include <memory>
37
#include <string>
38
#include <unordered_map>
39
#include <unordered_set>
40
#include <utility>
41
#include <vector>
42
43
#include <boost/optional/optional.hpp>
44
45
#include <glog/logging.h>
46
47
#include "yb/common/common_fwd.h"
48
#include "yb/common/column_id.h"
49
#include "yb/common/common_types.pb.h"
50
#include "yb/common/entity_ids_types.h"
51
#include "yb/common/hybrid_time.h"
52
#include "yb/common/id_mapping.h"
53
#include "yb/common/types.h"
54
55
#include "yb/gutil/stl_util.h"
56
57
#include "yb/util/memory/arena_fwd.h"
58
#include "yb/util/status.h"
59
#include "yb/util/uuid.h"
60
61
// Check that two schemas are equal, yielding a useful error message in the case that
62
// they are not.
63
#define DCHECK_SCHEMA_EQ(s1, s2) \
64
17
  do { \
65
0
    DCHECK((s1).Equals((s2))) << "Schema " << (s1).ToString() \
66
0
                              << " does not match " << (s2).ToString(); \
67
17
  } while (0);
68
69
#define DCHECK_KEY_PROJECTION_SCHEMA_EQ(s1, s2) \
70
3
  do { \
71
0
    DCHECK((s1).KeyEquals((s2))) << "Key-Projection Schema " \
72
0
                                 << (s1).ToString() << " does not match " \
73
0
                                 << (s2).ToString(); \
74
3
  } while (0);
75
76
namespace yb {
77
78
class DeletedColumnPB;
79
80
// Struct for storing information about deleted columns for cleanup.
81
struct DeletedColumn {
82
  ColumnId id;
83
  HybridTime ht;
84
85
657
  DeletedColumn() { }
86
87
963
  DeletedColumn(ColumnId id_, HybridTime ht_) : id(id_), ht(ht_) {}
88
89
  static CHECKED_STATUS FromPB(const DeletedColumnPB& col, DeletedColumn* ret);
90
  void CopyToPB(DeletedColumnPB* pb) const;
91
};
92
93
// The schema for a given column.
94
//
95
// Holds the data type as well as information about nullability & column name.
96
// In the future, it may hold information about annotations, etc.
97
class ColumnSchema {
98
 public:
99
  // Component comparators for combining in custom comparators.
100
74.1k
  static bool CompName(const ColumnSchema &a, const ColumnSchema &b) {
101
74.1k
    return a.name_ == b.name_;
102
74.1k
  }
103
104
753k
  static bool CompNullable(const ColumnSchema &a, const ColumnSchema &b) {
105
753k
    return a.is_nullable_ == b.is_nullable_;
106
753k
  }
107
108
752k
  static bool CompHashKey(const ColumnSchema &a, const ColumnSchema &b) {
109
752k
    return a.is_hash_key_ == b.is_hash_key_;
110
752k
  }
111
112
752k
  static bool CompSortingType(const ColumnSchema &a, const ColumnSchema &b) {
113
752k
    return a.sorting_type_ == b.sorting_type_;
114
752k
  }
115
116
  static bool CompTypeInfo(const ColumnSchema &a, const ColumnSchema &b);
117
118
0
  static bool CompOrder(const ColumnSchema &a, const ColumnSchema &b) {
119
0
    return a.order_ == b.order_;
120
0
  }
121
122
  // Combined comparators.
123
753k
  static bool CompareType(const ColumnSchema &a, const ColumnSchema &b) {
124
753k
    return CompNullable(a, b) && CompHashKey(a, b) &&
125
752k
        CompSortingType(a, b) && CompTypeInfo(a, b);
126
753k
  }
127
128
74.1k
  static bool CompareByDefault(const ColumnSchema &a, const ColumnSchema &b) {
129
74.1k
    return CompareType(a, b) && CompName(a, b);
130
74.1k
  }
131
132
  // name: column name
133
  // type: column type (e.g. UINT8, INT32, STRING, MAP<INT32, STRING> ...)
134
  // is_nullable: true if a row value can be null
135
  // is_hash_key: true if a column's hash value can be used for partitioning.
136
  //
137
  // Example:
138
  //   ColumnSchema col_a("a", UINT32)
139
  //   ColumnSchema col_b("b", STRING, true);
140
  //   uint32_t default_i32 = -15;
141
  //   ColumnSchema col_c("c", INT32, false, &default_i32);
142
  //   Slice default_str("Hello");
143
  //   ColumnSchema col_d("d", STRING, false, &default_str);
144
  ColumnSchema(std::string name,
145
               const std::shared_ptr<QLType>& type,
146
               bool is_nullable = false,
147
               bool is_hash_key = false,
148
               bool is_static = false,
149
               bool is_counter = false,
150
               int32_t order = 0,
151
               SortingType sorting_type = SortingType::kNotSpecified,
152
               int32_t pg_type_oid = 0 /*kInvalidOid*/)
153
      : name_(std::move(name)),
154
        type_(type),
155
        is_nullable_(is_nullable),
156
        is_hash_key_(is_hash_key),
157
        is_static_(is_static),
158
        is_counter_(is_counter),
159
        order_(order),
160
        sorting_type_(sorting_type),
161
28.2M
        pg_type_oid_(pg_type_oid) {
162
28.2M
  }
163
164
  // convenience constructor for creating columns with simple (non-parametric) data types
165
  ColumnSchema(std::string name,
166
               DataType type,
167
               bool is_nullable = false,
168
               bool is_hash_key = false,
169
               bool is_static = false,
170
               bool is_counter = false,
171
               int32_t order = 0,
172
               SortingType sorting_type = SortingType::kNotSpecified,
173
               int32_t pg_type_oid = 0 /*kInvalidOid*/);
174
175
1.26G
  const std::shared_ptr<QLType>& type() const {
176
1.26G
    return type_;
177
1.26G
  }
178
179
20
  void set_type(const std::shared_ptr<QLType>& type) {
180
20
    type_ = type;
181
20
  }
182
183
  const TypeInfo* type_info() const;
184
185
1.01G
  bool is_nullable() const {
186
1.01G
    return is_nullable_;
187
1.01G
  }
188
189
1.00G
  bool is_hash_key() const {
190
1.00G
    return is_hash_key_;
191
1.00G
  }
192
193
1.02G
  bool is_static() const {
194
1.02G
    return is_static_;
195
1.02G
  }
196
197
973M
  bool is_counter() const {
198
973M
    return is_counter_;
199
973M
  }
200
201
976M
  int32_t order() const {
202
976M
    return order_;
203
976M
  }
204
205
953M
  int32_t pg_type_oid() const {
206
953M
    return pg_type_oid_;
207
953M
  }
208
209
1.00G
  SortingType sorting_type() const {
210
1.00G
    return sorting_type_;
211
1.00G
  }
212
213
55.7k
  void set_sorting_type(SortingType sorting_type) {
214
55.7k
    sorting_type_ = sorting_type;
215
55.7k
  }
216
217
2.01M
  const std::string sorting_type_string() const {
218
2.01M
    switch (sorting_type_) {
219
1.76M
      case kNotSpecified:
220
1.76M
        return "none";
221
251k
      case kAscending:
222
251k
        return "asc";
223
536
      case kDescending:
224
536
        return "desc";
225
0
      case kAscendingNullsLast:
226
0
        return "asc nulls last";
227
0
      case kDescendingNullsLast:
228
0
        return "desc nulls last";
229
0
    }
230
0
    LOG(FATAL) << "Invalid sorting type: " << sorting_type_;
231
0
  }
232
233
1.02G
  const std::string &name() const {
234
1.02G
    return name_;
235
1.02G
  }
236
237
  // Return a string identifying this column, including its
238
  // name.
239
  std::string ToString() const;
240
241
  // Same as above, but only including the type information.
242
  // For example, "STRING NOT NULL".
243
  std::string TypeToString() const;
244
245
  template <typename Comparator>
246
753k
  bool Equals(const ColumnSchema &other, Comparator comp) const {
247
753k
    return comp(*this, other);
248
753k
  }
_ZNK2yb12ColumnSchema6EqualsIPFbRKS0_S3_EEEbS3_T_
Line
Count
Source
246
753k
  bool Equals(const ColumnSchema &other, Comparator comp) const {
247
753k
    return comp(*this, other);
248
753k
  }
Unexecuted instantiation: catalog_manager_ent.cc:_ZNK2yb12ColumnSchema6EqualsIZNS_6master10enterprise14CatalogManager16ImportTableEntryERKNSt3__13mapINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS5_4pairISC_NS_11YQLDatabaseEEENS5_4lessISC_EENSA_INSD_IKSC_SF_EEEEEERKNS6_ISC_NS4_25ExternalTableSnapshotDataESH_NSA_INSD_ISI_SO_EEEEEEPSO_E28CompareColumnsExceptNullableEEbRKS0_T_
249
250
679k
  bool EqualsType(const ColumnSchema &other) const {
251
679k
    return Equals(other, CompareType);
252
679k
  }
253
254
0
  bool Equals(const ColumnSchema &other) const {
255
0
    return Equals(other, CompareByDefault);
256
0
  }
257
258
  int Compare(const void *lhs, const void *rhs) const;
259
260
  // Stringify the given cell. This just stringifies the cell contents,
261
  // and doesn't include the column name or type.
262
  std::string Stringify(const void *cell) const;
263
264
  // Append a debug string for this cell. This differs from Stringify above
265
  // in that it also includes the column info, for example 'STRING foo=bar'.
266
  template<class CellType>
267
43
  void DebugCellAppend(const CellType& cell, std::string* ret) const {
268
43
    DoDebugCellAppend((is_nullable_ && cell.is_null()) ? nullptr : cell.ptr(), ret);
269
43
  }
_ZNK2yb12ColumnSchema15DebugCellAppendINS_17ContiguousRowCellINS_13ContiguousRowEEEEEvRKT_PNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEE
Line
Count
Source
267
37
  void DebugCellAppend(const CellType& cell, std::string* ret) const {
268
37
    DoDebugCellAppend((is_nullable_ && cell.is_null()) ? nullptr : cell.ptr(), ret);
269
37
  }
_ZNK2yb12ColumnSchema15DebugCellAppendINS_17ContiguousRowCellINS_18ConstContiguousRowEEEEEvRKT_PNSt3__112basic_stringIcNS8_11char_traitsIcEENS8_9allocatorIcEEEE
Line
Count
Source
267
6
  void DebugCellAppend(const CellType& cell, std::string* ret) const {
268
6
    DoDebugCellAppend((is_nullable_ && cell.is_null()) ? nullptr : cell.ptr(), ret);
269
6
  }
Unexecuted instantiation: _ZNK2yb12ColumnSchema15DebugCellAppendINS_15SimpleConstCellEEEvRKT_PNSt3__112basic_stringIcNS6_11char_traitsIcEENS6_9allocatorIcEEEE
270
271
  // Returns the memory usage of this object without the object itself. Should
272
  // be used when embedded inside another object.
273
  size_t memory_footprint_excluding_this() const;
274
275
  // Returns the memory usage of this object including the object itself.
276
  // Should be used when allocated on the heap.
277
  size_t memory_footprint_including_this() const;
278
279
 private:
280
  friend class SchemaBuilder;
281
282
17
  void set_name(const std::string& name) {
283
17
    name_ = name;
284
17
  }
285
286
  void DoDebugCellAppend(const void* cell, std::string* ret) const;
287
288
  std::string name_;
289
  std::shared_ptr<QLType> type_;
290
  bool is_nullable_;
291
  bool is_hash_key_;
292
  bool is_static_;
293
  bool is_counter_;
294
  int32_t order_;
295
  SortingType sorting_type_;
296
  int32_t pg_type_oid_;
297
};
298
299
class ContiguousRow;
300
const TableId kNoCopartitionTableId = "";
301
302
class TableProperties {
303
 public:
304
  // Containing counters is a internal property instead of a user-defined property, so we don't use
305
  // it when comparing table properties.
306
12.2k
  bool operator==(const TableProperties& other) const {
307
12.2k
    if (!Equivalent(other)) {
308
0
      return false;
309
0
    }
310
311
12.2k
    return default_time_to_live_ == other.default_time_to_live_ &&
312
12.2k
           use_mangled_column_name_ == other.use_mangled_column_name_ &&
313
12.2k
           contain_counters_ == other.contain_counters_;
314
315
    // Ignoring num_tablets_.
316
    // Ignoring retain_delete_markers_.
317
    // Ignoring wal_retention_secs_.
318
12.2k
  }
319
320
12.1k
  bool operator!=(const TableProperties& other) const {
321
12.1k
    return !(*this == other);
322
12.1k
  }
323
324
12.2k
  bool Equivalent(const TableProperties& other) const {
325
12.2k
    if (is_ysql_catalog_table_ != other.is_ysql_catalog_table_) {
326
0
      return false;
327
0
    }
328
329
12.2k
    if (is_transactional_ != other.is_transactional_) {
330
0
      return false;
331
0
    }
332
333
12.2k
    if (consistency_level_ != other.consistency_level_) {
334
0
      return false;
335
0
    }
336
337
12.2k
    if ((copartition_table_id_ == kNoCopartitionTableId ||
338
0
         other.copartition_table_id_ == kNoCopartitionTableId) &&
339
12.2k
        copartition_table_id_ != other.copartition_table_id_) {
340
0
      return false;
341
0
    }
342
343
    // Ignoring default_time_to_live_.
344
    // Ignoring num_tablets_.
345
    // Ignoring use_mangled_column_name_.
346
    // Ignoring contain_counters_.
347
    // Ignoring retain_delete_markers_.
348
    // Ignoring wal_retention_secs_.
349
12.2k
    return true;
350
12.2k
  }
351
352
144M
  bool HasDefaultTimeToLive() const {
353
144M
    return (default_time_to_live_ != kNoDefaultTtl);
354
144M
  }
355
356
4.23k
  void SetDefaultTimeToLive(uint64_t default_time_to_live) {
357
4.23k
    default_time_to_live_ = default_time_to_live;
358
4.23k
  }
359
360
4.12M
  int64_t DefaultTimeToLive() const {
361
4.12M
    return default_time_to_live_;
362
4.12M
  }
363
364
47.3k
  bool contain_counters() const {
365
47.3k
    return contain_counters_;
366
47.3k
  }
367
368
19.8M
  bool is_transactional() const {
369
19.8M
    return is_transactional_;
370
19.8M
  }
371
372
6.88k
  YBConsistencyLevel consistency_level() const {
373
6.88k
    return consistency_level_;
374
6.88k
  }
375
376
1.34M
  void SetContainCounters(bool contain_counters) {
377
1.34M
    contain_counters_ = contain_counters;
378
1.34M
  }
379
380
1.34M
  void SetTransactional(bool is_transactional) {
381
1.34M
    is_transactional_ = is_transactional;
382
1.34M
  }
383
384
1.34M
  void SetConsistencyLevel(YBConsistencyLevel consistency_level) {
385
1.34M
    consistency_level_ = consistency_level;
386
1.34M
  }
387
388
0
  TableId CopartitionTableId() const {
389
0
    return copartition_table_id_;
390
0
  }
391
392
140M
  bool HasCopartitionTableId() const {
393
140M
    return copartition_table_id_ != kNoCopartitionTableId;
394
140M
  }
395
396
0
  void SetCopartitionTableId(const TableId& copartition_table_id) {
397
0
    copartition_table_id_ = copartition_table_id;
398
0
  }
399
400
1.34M
  void SetUseMangledColumnName(bool value) {
401
1.34M
    use_mangled_column_name_ = value;
402
1.34M
  }
403
404
2.02M
  bool use_mangled_column_name() const {
405
2.02M
    return use_mangled_column_name_;
406
2.02M
  }
407
408
33.3k
  void SetNumTablets(int num_tablets) {
409
33.3k
    num_tablets_ = num_tablets;
410
33.3k
  }
411
412
140M
  bool HasNumTablets() const {
413
140M
    return num_tablets_ > 0;
414
140M
  }
415
416
4.02k
  int num_tablets() const {
417
4.02k
    return num_tablets_;
418
4.02k
  }
419
420
1.34M
  void set_is_ysql_catalog_table(bool is_ysql_catalog_table) {
421
1.34M
    is_ysql_catalog_table_ = is_ysql_catalog_table;
422
1.34M
  }
423
424
6.52M
  bool is_ysql_catalog_table() const {
425
6.52M
    return is_ysql_catalog_table_;
426
6.52M
  }
427
428
436
  bool retain_delete_markers() const {
429
436
    return retain_delete_markers_;
430
436
  }
431
432
1.35M
  void SetRetainDeleteMarkers(bool retain_delete_markers) {
433
1.35M
    retain_delete_markers_ = retain_delete_markers;
434
1.35M
  }
435
436
  void ToTablePropertiesPB(TablePropertiesPB *pb) const;
437
438
  static TableProperties FromTablePropertiesPB(const TablePropertiesPB& pb);
439
440
  void AlterFromTablePropertiesPB(const TablePropertiesPB& pb);
441
442
  void Reset();
443
444
  std::string ToString() const;
445
446
 private:
447
  // IMPORTANT: Every time a new property is added, we need to revisit
448
  // operator== and Equivalent methods to make sure that the new property
449
  // is being taken into consideration when deciding whether properties between
450
  // two different tables are equal or equivalent.
451
  static const int kNoDefaultTtl = -1;
452
  int64_t default_time_to_live_ = kNoDefaultTtl;
453
  bool contain_counters_ = false;
454
  bool is_transactional_ = false;
455
  bool retain_delete_markers_ = false;
456
  YBConsistencyLevel consistency_level_ = YBConsistencyLevel::STRONG;
457
  TableId copartition_table_id_ = kNoCopartitionTableId;
458
  boost::optional<uint32_t> wal_retention_secs_;
459
  bool use_mangled_column_name_ = false;
460
  int num_tablets_ = 0;
461
  bool is_ysql_catalog_table_ = false;
462
};
463
464
typedef std::string PgSchemaName;
465
466
// The schema for a set of rows.
467
//
468
// A Schema is simply a set of columns, along with information about
469
// which prefix of columns makes up the primary key.
470
//
471
// Note that, while Schema is copyable and assignable, it is a complex
472
// object that is not inexpensive to copy. You should generally prefer
473
// passing by pointer or reference, and functions that create new
474
// Schemas should generally prefer taking a Schema pointer and using
475
// Schema::swap() or Schema::Reset() rather than returning by value.
476
class Schema {
477
 public:
478
479
  static const ssize_t kColumnNotFound = -1;
480
481
  Schema()
482
    : num_key_columns_(0),
483
      num_hash_key_columns_(0),
484
      // TODO: C++11 provides a single-arg constructor
485
      name_to_index_(10,
486
                     NameToIndexMap::hasher(),
487
                     NameToIndexMap::key_equal(),
488
                     NameToIndexMapAllocator(&name_to_index_bytes_)),
489
      has_nullables_(false),
490
      cotable_id_(Uuid::Nil()),
491
      pgtable_id_(0),
492
18.2M
      pgschema_name_("") {
493
18.2M
  }
494
495
  Schema(const Schema& other);
496
  Schema& operator=(const Schema& other);
497
498
  void swap(Schema& other); // NOLINT(build/include_what_you_use)
499
500
  void CopyFrom(const Schema& other);
501
502
  // Construct a schema with the given information.
503
  //
504
  // NOTE: if the schema is user-provided, it's better to construct an
505
  // empty schema and then use Reset(...)  so that errors can be
506
  // caught. If an invalid schema is passed to this constructor, an
507
  // assertion will be fired!
508
  Schema(const vector<ColumnSchema>& cols,
509
         size_t key_columns,
510
         const TableProperties& table_properties = TableProperties(),
511
         const Uuid& cotable_id = Uuid::Nil(),
512
         const PgTableOid pgtable_id = 0,
513
         const PgSchemaName pgschema_name = "");
514
515
  // Construct a schema with the given information.
516
  //
517
  // NOTE: if the schema is user-provided, it's better to construct an
518
  // empty schema and then use Reset(...)  so that errors can be
519
  // caught. If an invalid schema is passed to this constructor, an
520
  // assertion will be fired!
521
  Schema(const vector<ColumnSchema>& cols,
522
         const vector<ColumnId>& ids,
523
         size_t key_columns,
524
         const TableProperties& table_properties = TableProperties(),
525
         const Uuid& cotable_id = Uuid::Nil(),
526
         const PgTableOid pgtable_id = 0,
527
         const PgSchemaName pgschema_name = "");
528
529
  // Reset this Schema object to the given schema.
530
  // If this fails, the Schema object is left in an inconsistent
531
  // state and may not be used.
532
  CHECKED_STATUS Reset(const vector<ColumnSchema>& cols, size_t key_columns,
533
                       const TableProperties& table_properties = TableProperties(),
534
                       const Uuid& cotable_id = Uuid::Nil(),
535
                       const PgTableOid pgtable_id = 0,
536
                       const PgSchemaName pgschema_name = "");
537
538
  // Reset this Schema object to the given schema.
539
  // If this fails, the Schema object is left in an inconsistent
540
  // state and may not be used.
541
  CHECKED_STATUS Reset(const vector<ColumnSchema>& cols,
542
                       const vector<ColumnId>& ids,
543
                       size_t key_columns,
544
                       const TableProperties& table_properties = TableProperties(),
545
                       const Uuid& cotable_id = Uuid::Nil(),
546
                       const PgTableOid pgtable_id = 0,
547
                       const PgSchemaName pgschema_name = "");
548
549
  // Return the number of bytes needed to represent a single row of this schema.
550
  //
551
  // This size does not include any indirected (variable length) data (eg strings)
552
60
  size_t byte_size() const {
553
60
    DCHECK(initialized());
554
60
    return col_offsets_.back();
555
60
  }
556
557
  // Return the number of bytes needed to represent
558
  // only the key portion of this schema.
559
6
  size_t key_byte_size() const {
560
6
    return col_offsets_[num_key_columns_];
561
6
  }
562
563
  // Return the number of columns in this schema
564
457M
  size_t num_columns() const {
565
457M
    return cols_.size();
566
457M
  }
567
568
  // Return the length of the key prefix in this schema.
569
1.08G
  size_t num_key_columns() const {
570
1.08G
    return num_key_columns_;
571
1.08G
  }
572
573
  // Number of hash key columns.
574
135M
  size_t num_hash_key_columns() const {
575
135M
    return num_hash_key_columns_;
576
135M
  }
577
578
  // Number of range key columns.
579
74.4M
  size_t num_range_key_columns() const {
580
74.4M
    return num_key_columns_ - num_hash_key_columns_;
581
74.4M
  }
582
583
  // Return the byte offset within the row for the given column index.
584
147
  size_t column_offset(size_t col_idx) const {
585
147
    DCHECK_LT(col_idx, cols_.size());
586
147
    return col_offsets_[col_idx];
587
147
  }
588
589
  // Return the ColumnSchema corresponding to the given column index.
590
386M
  inline const ColumnSchema &column(size_t idx) const {
591
386M
    DCHECK_LT(idx, cols_.size());
592
386M
    return cols_[idx];
593
386M
  }
594
595
  // Return the ColumnSchema corresponding to the given column ID.
596
  Result<const ColumnSchema&> column_by_id(ColumnId id) const;
597
598
  // Return the column ID corresponding to the given column index
599
1.32G
  ColumnId column_id(size_t idx) const {
600
1.32G
    DCHECK(has_column_ids());
601
1.32G
    DCHECK_LT(idx, cols_.size());
602
1.32G
    return col_ids_[idx];
603
1.32G
  }
604
605
  // Return true if the schema contains an ID mapping for its columns.
606
  // In the case of an empty schema, this is false.
607
2.50G
  bool has_column_ids() const {
608
2.50G
    return !col_ids_.empty();
609
2.50G
  }
610
611
149M
  const std::vector<ColumnSchema>& columns() const {
612
149M
    return cols_;
613
149M
  }
614
615
447k
  const std::vector<ColumnId>& column_ids() const {
616
447k
    return col_ids_;
617
447k
  }
618
619
0
  const std::vector<std::string> column_names() const {
620
0
    std::vector<std::string> column_names;
621
0
    for (const auto& col : cols_) {
622
0
      column_names.push_back(col.name());
623
0
    }
624
0
    return column_names;
625
0
  }
626
627
177M
  const TableProperties& table_properties() const {
628
177M
    return table_properties_;
629
177M
  }
630
631
2.26k
  TableProperties* mutable_table_properties() {
632
2.26k
    return &table_properties_;
633
2.26k
  }
634
635
0
  void SetDefaultTimeToLive(const uint64_t& ttl_msec) {
636
0
    table_properties_.SetDefaultTimeToLive(ttl_msec);
637
0
  }
638
639
0
  void SetCopartitionTableId(const TableId& copartition_table_id) {
640
0
    table_properties_.SetCopartitionTableId(copartition_table_id);
641
0
  }
642
643
15
  void SetTransactional(bool is_transactional) {
644
15
    table_properties_.SetTransactional(is_transactional);
645
15
  }
646
647
7.77k
  void SetRetainDeleteMarkers(bool retain_delete_markers) {
648
7.77k
    table_properties_.SetRetainDeleteMarkers(retain_delete_markers);
649
7.77k
  }
650
651
0
  bool has_pgschema_name() const {
652
0
    return !pgschema_name_.empty();
653
0
  }
654
655
1.30M
  void SetSchemaName(std::string pgschema_name) {
656
1.30M
    pgschema_name_ = pgschema_name;
657
1.30M
  }
658
659
139M
  PgSchemaName SchemaName() const {
660
139M
    return pgschema_name_;
661
139M
  }
662
663
  // Return the column index corresponding to the given column,
664
  // or kColumnNotFound if the column is not in this schema.
665
19.8M
  ssize_t find_column(const GStringPiece col_name) const {
666
19.8M
    auto iter = name_to_index_.find(col_name);
667
19.8M
    if (PREDICT_FALSE(iter == name_to_index_.end())) {
668
5
      return kColumnNotFound;
669
19.8M
    } else {
670
19.8M
      return iter->second;
671
19.8M
    }
672
19.8M
  }
673
674
  Result<ColumnId> ColumnIdByName(const std::string& name) const;
675
676
  Result<ssize_t> ColumnIndexByName(GStringPiece col_name) const;
677
678
  // Returns true if the schema contains nullable columns
679
29
  bool has_nullables() const {
680
29
    return has_nullables_;
681
29
  }
682
683
  // Returns true if the schema contains static columns
684
63.4M
  bool has_statics() const {
685
63.4M
    return has_statics_;
686
63.4M
  }
687
688
  // Returns true if the specified column (by index) is a key
689
40.3M
  bool is_key_column(size_t idx) const {
690
40.3M
    return idx < num_key_columns_;
691
40.3M
  }
692
693
  // Returns true if the specified column (by column id) is a key
694
23.5M
  bool is_key_column(ColumnId column_id) const {
695
23.5M
    return is_key_column(find_column_by_id(column_id));
696
23.5M
  }
697
698
  // Returns true if the specified column (by name) is a key
699
96
  bool is_key_column(const GStringPiece col_name) const {
700
96
    return is_key_column(find_column(col_name));
701
96
  }
702
703
  // Returns true if the specified column (by index) is a hash key
704
1.24M
  bool is_hash_key_column(size_t idx) const {
705
1.24M
    return idx < num_hash_key_columns_;
706
1.24M
  }
707
708
  // Returns true if the specified column (by column id) is a hash key
709
0
  bool is_hash_key_column(ColumnId column_id) const {
710
0
    return is_hash_key_column(find_column_by_id(column_id));
711
0
  }
712
713
  // Returns true if the specified column (by name) is a hash key
714
0
  bool is_hash_key_column(const GStringPiece col_name) const {
715
0
    return is_hash_key_column(find_column(col_name));
716
0
  }
717
718
  // Returns true if the specified column (by index) is a range column
719
1.25M
  bool is_range_column(size_t idx) const {
720
1.25M
    return is_key_column(idx) && !is_hash_key_column(idx);
721
1.25M
  }
722
723
  // Returns true if the specified column (by column id) is a range column
724
1.04M
  bool is_range_column(ColumnId column_id) const {
725
1.04M
    return is_range_column(find_column_by_id(column_id));
726
1.04M
  }
727
728
  // Returns true if the specified column (by name) is a range column
729
0
  bool is_range_column(const GStringPiece col_name) const {
730
0
    return is_range_column(find_column(col_name));
731
0
  }
732
733
  // Return true if this Schema is initialized and valid.
734
6.04k
  bool initialized() const {
735
6.04k
    return !col_offsets_.empty();
736
6.04k
  }
737
738
  // Returns the highest column id in this Schema.
739
31.6k
  ColumnId max_col_id() const {
740
31.6k
    return max_col_id_;
741
31.6k
  }
742
743
  // Gets and sets the uuid of the non-primary table this schema belongs to co-located in a tablet.
744
206M
  const Uuid& cotable_id() const {
745
206M
    return cotable_id_;
746
206M
  }
747
748
141M
  bool has_cotable_id() const {
749
141M
    return !cotable_id_.IsNil();
750
141M
  }
751
752
488k
  void set_cotable_id(const Uuid& cotable_id) {
753
488k
    if (!cotable_id.IsNil()) {
754
488k
      DCHECK_EQ(pgtable_id_, 0);
755
488k
    }
756
488k
    cotable_id_ = cotable_id;
757
488k
  }
758
759
  // Gets and sets the PG table OID of the non-primary table this schema belongs to in a tablet
760
  // with colocated tables.
761
38.6M
  PgTableOid pgtable_id() const {
762
38.6M
    return pgtable_id_;
763
38.6M
  }
764
765
141M
  bool has_pgtable_id() const {
766
141M
    return pgtable_id_ > 0;
767
141M
  }
768
769
185
  void set_pgtable_id(const PgTableOid pgtable_id) {
770
185
    if (pgtable_id > 0) {
771
185
      DCHECK(cotable_id_.IsNil());
772
185
    }
773
185
    pgtable_id_ = pgtable_id;
774
185
  }
775
776
  // Extract a given column from a row where the type is
777
  // known at compile-time. The type is checked with a debug
778
  // assertion -- but if the wrong type is used and these assertions
779
  // are off, incorrect data may result.
780
  //
781
  // This is mostly useful for tests at this point.
782
  // TODO: consider removing it.
783
  template<DataType Type, class RowType>
784
  const typename DataTypeTraits<Type>::cpp_type *
785
16
  ExtractColumnFromRow(const RowType& row, size_t idx) const {
786
16
    DCHECK_SCHEMA_EQ(*this, *row.schema());
787
16
    const ColumnSchema& col_schema = cols_[idx];
788
16
    DCHECK_LT(idx, cols_.size());
789
16
    DCHECK_EQ(col_schema.type_info()->type(), Type);
790
791
16
    const void *val;
792
16
    if (col_schema.is_nullable()) {
793
5
      val = row.nullable_cell_ptr(idx);
794
11
    } else {
795
11
      val = row.cell_ptr(idx);
796
11
    }
797
798
16
    return reinterpret_cast<const typename DataTypeTraits<Type>::cpp_type *>(val);
799
16
  }
_ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE9ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
Line
Count
Source
785
1
  ExtractColumnFromRow(const RowType& row, size_t idx) const {
786
1
    DCHECK_SCHEMA_EQ(*this, *row.schema());
787
1
    const ColumnSchema& col_schema = cols_[idx];
788
1
    DCHECK_LT(idx, cols_.size());
789
1
    DCHECK_EQ(col_schema.type_info()->type(), Type);
790
791
1
    const void *val;
792
1
    if (col_schema.is_nullable()) {
793
1
      val = row.nullable_cell_ptr(idx);
794
0
    } else {
795
0
      val = row.cell_ptr(idx);
796
0
    }
797
798
1
    return reinterpret_cast<const typename DataTypeTraits<Type>::cpp_type *>(val);
799
1
  }
Unexecuted instantiation: _ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE13ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
Unexecuted instantiation: _ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE25ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
Unexecuted instantiation: _ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE17ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
Unexecuted instantiation: _ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE18ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
Unexecuted instantiation: _ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE22ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
_ZNK2yb6Schema20ExtractColumnFromRowILNS_8DataTypeE5ENS_13ContiguousRowEEEPKNS_14DataTypeTraitsIXT_EE8cpp_typeERKT0_m
Line
Count
Source
785
15
  ExtractColumnFromRow(const RowType& row, size_t idx) const {
786
15
    DCHECK_SCHEMA_EQ(*this, *row.schema());
787
15
    const ColumnSchema& col_schema = cols_[idx];
788
15
    DCHECK_LT(idx, cols_.size());
789
15
    DCHECK_EQ(col_schema.type_info()->type(), Type);
790
791
15
    const void *val;
792
15
    if (col_schema.is_nullable()) {
793
4
      val = row.nullable_cell_ptr(idx);
794
11
    } else {
795
11
      val = row.cell_ptr(idx);
796
11
    }
797
798
15
    return reinterpret_cast<const typename DataTypeTraits<Type>::cpp_type *>(val);
799
15
  }
800
801
  // Stringify the given row, which conforms to this schema,
802
  // in a way suitable for debugging. This isn't currently optimized
803
  // so should be avoided in hot paths.
804
  template<class RowType>
805
1
  std::string DebugRow(const RowType& row) const {
806
1
    DCHECK_SCHEMA_EQ(*this, *row.schema());
807
1
    return DebugRowColumns(row, num_columns());
808
1
  }
809
810
  // Stringify the given row, which must have a schema which is
811
  // key-compatible with this one. Per above, this is not for use in
812
  // hot paths.
813
  template<class RowType>
814
3
  std::string DebugRowKey(const RowType& row) const {
815
3
    DCHECK_KEY_PROJECTION_SCHEMA_EQ(*this, *row.schema());
816
3
    return DebugRowColumns(row, num_key_columns());
817
3
  }
818
819
  // Decode the specified encoded key into the given 'buffer', which
820
  // must be at least as large as this->key_byte_size().
821
  //
822
  // 'arena' is used for allocating indirect strings, but is unused
823
  // for other datatypes.
824
  CHECKED_STATUS DecodeRowKey(Slice encoded_key, uint8_t* buffer, Arena* arena) const;
825
826
  // Decode and stringify the given contiguous encoded row key in
827
  // order to, e.g., provide print human-readable information about a
828
  // tablet's start and end keys.
829
  //
830
  // If the encoded key is empty then '<start of table>' or '<end of table>'
831
  // will be returned based on the value of 'start_or_end'.
832
  //
833
  // See also: DebugRowKey, DecodeRowKey.
834
  enum StartOrEnd {
835
    START_KEY,
836
    END_KEY
837
  };
838
  std::string DebugEncodedRowKey(Slice encoded_key, StartOrEnd start_or_end) const;
839
840
  // Compare two rows of this schema.
841
  template<class RowTypeA, class RowTypeB>
842
2
  int Compare(const RowTypeA& lhs, const RowTypeB& rhs) const {
843
2
    DCHECK(KeyEquals(*lhs.schema()) && KeyEquals(*rhs.schema()));
844
845
2
    for (size_t col = 0; col < num_key_columns_; col++) {
846
2
      int col_compare = column(col).Compare(lhs.cell_ptr(col), rhs.cell_ptr(col));
847
2
      if (col_compare != 0) {
848
2
        return col_compare;
849
2
      }
850
2
    }
851
0
    return 0;
852
2
  }
853
854
  // Return the projection of this schema which contains only
855
  // the key columns.
856
  // TODO: this should take a Schema* out-parameter to avoid an
857
  // extra copy of the ColumnSchemas.
858
  // TODO this should probably be cached since the key projection
859
  // is not supposed to change, for a single schema.
860
188k
  Schema CreateKeyProjection() const {
861
188k
    vector<ColumnSchema> key_cols(cols_.begin(),
862
188k
                                  cols_.begin() + num_key_columns_);
863
188k
    vector<ColumnId> col_ids;
864
188k
    if (!col_ids_.empty()) {
865
188k
      col_ids.assign(col_ids_.begin(), col_ids_.begin() + num_key_columns_);
866
188k
    }
867
868
188k
    return Schema(key_cols, col_ids, num_key_columns_);
869
188k
  }
870
871
  // Initialize column IDs by default values.
872
  // Requires that this schema has no column IDs.
873
  void InitColumnIdsByDefault();
874
875
  // Return a new Schema which is the same as this one, but without any column
876
  // IDs assigned.
877
  //
878
  // Requires that this schema has column IDs.
879
  Schema CopyWithoutColumnIds() const;
880
881
  // Create a new schema containing only the selected columns.
882
  // The resulting schema will have no key columns defined.
883
  // If this schema has IDs, the resulting schema will as well.
884
  CHECKED_STATUS CreateProjectionByNames(const std::vector<GStringPiece>& col_names,
885
                                         Schema* out, size_t num_key_columns = 0) const;
886
887
  // Create a new schema containing only the selected column IDs.
888
  //
889
  // If any column IDs are invalid, then they will be ignored and the
890
  // result will have fewer columns than requested.
891
  //
892
  // The resulting schema will have no key columns defined.
893
  CHECKED_STATUS CreateProjectionByIdsIgnoreMissing(const std::vector<ColumnId>& col_ids,
894
                                                    Schema* out) const;
895
896
  // Stringify this Schema. This is not particularly efficient,
897
  // so should only be used when necessary for output.
898
  std::string ToString() const;
899
900
  // Return true if the schemas have exactly the same set of columns
901
  // and respective types, and the same table properties.
902
  template <typename ColumnComparator>
903
12.2k
  bool Equals(const Schema &other, ColumnComparator comp) const {
904
12.2k
    if (this == &other) return true;
905
12.2k
    if (this->num_key_columns_ != other.num_key_columns_) return false;
906
12.1k
    if (this->table_properties_ != other.table_properties_) return false;
907
12.1k
    if (this->cols_.size() != other.cols_.size()) return false;
908
909
86.3k
    for (size_t i = 0; i < other.cols_.size(); i++) {
910
74.1k
      if (!this->cols_[i].Equals(other.cols_[i], comp)) return false;
911
74.1k
    }
912
913
12.1k
    return true;
914
12.1k
  }
_ZNK2yb6Schema6EqualsIPFbRKNS_12ColumnSchemaES4_EEEbRKS0_T_
Line
Count
Source
903
12.2k
  bool Equals(const Schema &other, ColumnComparator comp) const {
904
12.2k
    if (this == &other) return true;
905
12.2k
    if (this->num_key_columns_ != other.num_key_columns_) return false;
906
12.1k
    if (this->table_properties_ != other.table_properties_) return false;
907
12.1k
    if (this->cols_.size() != other.cols_.size()) return false;
908
909
86.3k
    for (size_t i = 0; i < other.cols_.size(); i++) {
910
74.1k
      if (!this->cols_[i].Equals(other.cols_[i], comp)) return false;
911
74.1k
    }
912
913
12.1k
    return true;
914
12.1k
  }
Unexecuted instantiation: catalog_manager_ent.cc:_ZNK2yb6Schema6EqualsIZNS_6master10enterprise14CatalogManager16ImportTableEntryERKNSt3__13mapINS5_12basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEEENS5_4pairISC_NS_11YQLDatabaseEEENS5_4lessISC_EENSA_INSD_IKSC_SF_EEEEEERKNS6_ISC_NS4_25ExternalTableSnapshotDataESH_NSA_INSD_ISI_SO_EEEEEEPSO_E28CompareColumnsExceptNullableEEbRKS0_T_
915
916
12.2k
  bool Equals(const Schema &other) const {
917
12.2k
    return Equals(other, ColumnSchema::CompareByDefault);
918
12.2k
  }
919
920
  // Return true if the schemas have exactly the same set of columns
921
  // and respective types, and equivalent properties.
922
  // For example, one table property could have different properties for wal_retention_secs_ and
923
  // retain_delete_markers_ but still be equivalent.
924
0
  bool EquivalentForDataCopy(const Schema& other) const {
925
0
    if (this == &other) return true;
926
0
    if (this->num_key_columns_ != other.num_key_columns_) return false;
927
0
    if (!this->table_properties_.Equivalent(other.table_properties_)) return false;
928
0
    if (this->cols_.size() != other.cols_.size()) return false;
929
0
930
0
    for (size_t i = 0; i < other.cols_.size(); i++) {
931
0
      if (!this->cols_[i].Equals(other.cols_[i])) return false;
932
0
      if (this->column_id(i) != other.column_id(i)) return false;
933
0
    }
934
0
935
0
    return true;
936
0
  }
937
938
  // Return true if the key projection schemas have exactly the same set of
939
  // columns and respective types. Doesn't check column names.
940
99.0k
  bool KeyEquals(const Schema& other) const {
941
99.0k
    if (this->num_key_columns_ != other.num_key_columns_) return false;
942
357k
    for (size_t i = 0; i < this->num_key_columns_; i++) {
943
258k
      if (!this->cols_[i].EqualsType(other.cols_[i])) return false;
944
258k
    }
945
99.0k
    return true;
946
99.0k
  }
947
948
  // Return a non-OK status if the project is not compatible with the current schema
949
  // - User columns non present in the tablet are considered errors
950
  // - Matching columns with different types, at the moment, are considered errors
951
  CHECKED_STATUS VerifyProjectionCompatibility(const Schema& projection) const;
952
953
  // Returns the projection schema mapped on the current one
954
  // If the project is invalid, return a non-OK status.
955
  CHECKED_STATUS GetMappedReadProjection(const Schema& projection,
956
                                 Schema *mapped_projection) const;
957
958
  // Loops through this schema (the projection) and calls the projector methods once for
959
  // each column.
960
  //
961
  // - CHECKED_STATUS ProjectBaseColumn(size_t proj_col_idx, size_t base_col_idx)
962
  //
963
  //     Called if the column in this schema matches one of the columns in 'base_schema'.
964
  //     The column type must match exactly.
965
  //
966
  // - CHECKED_STATUS ProjectDefaultColumn(size_t proj_idx)
967
  //
968
  //     Called if the column in this schema does not match any column in 'base_schema',
969
  //     but has a default or is nullable.
970
  //
971
  // - CHECKED_STATUS ProjectExtraColumn(size_t proj_idx, const ColumnSchema& col)
972
  //
973
  //     Called if the column in this schema does not match any column in 'base_schema',
974
  //     and does not have a default, and is not nullable.
975
  //
976
  // If both schemas have column IDs, then the matching is done by ID. Otherwise, it is
977
  // done by name.
978
  //
979
  // TODO(MAYBE): Pass the ColumnSchema and not only the column index?
980
  template <class Projector>
981
5
  CHECKED_STATUS GetProjectionMapping(const Schema& base_schema, Projector *projector) const {
982
5
    const bool use_column_ids = base_schema.has_column_ids() && has_column_ids();
983
984
5
    int proj_idx = 0;
985
13
    for (size_t i = 0; i < cols_.size(); ++i) {
986
10
      const ColumnSchema& col_schema = cols_[i];
987
988
      // try to lookup the column by ID if present or just by name.
989
      // Unit tests and Iter-Projections are probably always using the
990
      // lookup by name. The IDs are generally set by the server on AlterTable().
991
10
      ssize_t base_idx;
992
10
      if (use_column_ids) {
993
3
        base_idx = base_schema.find_column_by_id(col_ids_[i]);
994
7
      } else {
995
7
        base_idx = base_schema.find_column(col_schema.name());
996
7
      }
997
998
10
      if (base_idx >= 0) {
999
7
        const ColumnSchema& base_col_schema = base_schema.column(base_idx);
1000
        // Column present in the Base Schema...
1001
7
        if (!col_schema.EqualsType(base_col_schema)) {
1002
          // ...but with a different type, (TODO: try with an adaptor)
1003
1
          return STATUS(InvalidArgument, "The column '" + col_schema.name() +
1004
1
                                         "' must have type " +
1005
1
                                         base_col_schema.TypeToString() +
1006
1
                                         " found " + col_schema.TypeToString());
1007
6
        } else {
1008
6
          RETURN_NOT_OK(projector->ProjectBaseColumn(proj_idx, base_idx));
1009
6
        }
1010
3
      } else {
1011
3
        if (!col_schema.is_nullable()) {
1012
1
          RETURN_NOT_OK(projector->ProjectExtraColumn(proj_idx));
1013
1
        }
1014
3
      }
1015
8
      proj_idx++;
1016
8
    }
1017
3
    return Status::OK();
1018
5
  }
1019
1020
  // Returns the column index given the column ID.
1021
  // If no such column exists, returns kColumnNotFound.
1022
72.6M
  int find_column_by_id(ColumnId id) const {
1023
72.6M
    DCHECK(cols_.empty() || has_column_ids());
1024
72.6M
    int ret = id_to_index_[id];
1025
72.6M
    if (ret == -1) {
1026
1.24k
      return kColumnNotFound;
1027
1.24k
    }
1028
72.6M
    return ret;
1029
72.6M
  }
1030
1031
  // Returns the memory usage of this object without the object itself. Should
1032
  // be used when embedded inside another object.
1033
  size_t memory_footprint_excluding_this() const;
1034
1035
  // Returns the memory usage of this object including the object itself.
1036
  // Should be used when allocated on the heap.
1037
  size_t memory_footprint_including_this() const;
1038
1039
  static ColumnId first_column_id();
1040
1041
 private:
1042
1043
  void ResetColumnIds(const vector<ColumnId>& ids);
1044
1045
  // Return a stringified version of the first 'num_columns' columns of the
1046
  // row.
1047
  template<class RowType>
1048
4
  std::string DebugRowColumns(const RowType& row, size_t num_columns) const {
1049
4
    std::string ret;
1050
4
    ret.append("(");
1051
1052
14
    for (size_t col_idx = 0; col_idx < num_columns; col_idx++) {
1053
10
      if (col_idx > 0) {
1054
6
        ret.append(", ");
1055
6
      }
1056
10
      const ColumnSchema& col = cols_[col_idx];
1057
10
      col.DebugCellAppend(row.cell(col_idx), &ret);
1058
10
    }
1059
4
    ret.append(")");
1060
4
    return ret;
1061
4
  }
_ZNK2yb6Schema15DebugRowColumnsINS_13ContiguousRowEEENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKT_m
Line
Count
Source
1048
1
  std::string DebugRowColumns(const RowType& row, size_t num_columns) const {
1049
1
    std::string ret;
1050
1
    ret.append("(");
1051
1052
5
    for (size_t col_idx = 0; col_idx < num_columns; col_idx++) {
1053
4
      if (col_idx > 0) {
1054
3
        ret.append(", ");
1055
3
      }
1056
4
      const ColumnSchema& col = cols_[col_idx];
1057
4
      col.DebugCellAppend(row.cell(col_idx), &ret);
1058
4
    }
1059
1
    ret.append(")");
1060
1
    return ret;
1061
1
  }
_ZNK2yb6Schema15DebugRowColumnsINS_18ConstContiguousRowEEENSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEERKT_m
Line
Count
Source
1048
3
  std::string DebugRowColumns(const RowType& row, size_t num_columns) const {
1049
3
    std::string ret;
1050
3
    ret.append("(");
1051
1052
9
    for (size_t col_idx = 0; col_idx < num_columns; col_idx++) {
1053
6
      if (col_idx > 0) {
1054
3
        ret.append(", ");
1055
3
      }
1056
6
      const ColumnSchema& col = cols_[col_idx];
1057
6
      col.DebugCellAppend(row.cell(col_idx), &ret);
1058
6
    }
1059
3
    ret.append(")");
1060
3
    return ret;
1061
3
  }
1062
1063
  friend class SchemaBuilder;
1064
1065
  vector<ColumnSchema> cols_;
1066
  size_t num_key_columns_;
1067
  size_t num_hash_key_columns_;
1068
  ColumnId max_col_id_;
1069
  vector<ColumnId> col_ids_;
1070
  vector<size_t> col_offsets_;
1071
1072
  // The keys of this map are GStringPiece references to the actual name members of the
1073
  // ColumnSchema objects inside cols_. This avoids an extra copy of those strings,
1074
  // and also allows us to do lookups on the map using GStringPiece keys, sometimes
1075
  // avoiding copies.
1076
  //
1077
  // The map is instrumented with a counting allocator so that we can accurately
1078
  // measure its memory footprint.
1079
  int64_t name_to_index_bytes_ = 0;
1080
  typedef STLCountingAllocator<std::pair<const GStringPiece, size_t>> NameToIndexMapAllocator;
1081
  typedef std::unordered_map<
1082
      GStringPiece,
1083
      size_t,
1084
      std::hash<GStringPiece>,
1085
      std::equal_to<GStringPiece>,
1086
      NameToIndexMapAllocator> NameToIndexMap;
1087
  NameToIndexMap name_to_index_;
1088
1089
  IdMapping id_to_index_;
1090
1091
  // Cached indicator whether any columns are nullable.
1092
  bool has_nullables_;
1093
1094
  // Cached indicator whether any columns are static.
1095
  bool has_statics_ = false;
1096
1097
  TableProperties table_properties_;
1098
1099
  // Uuid of the non-primary table this schema belongs to co-located in a tablet. Nil for the
1100
  // primary or single-tenant table.
1101
  Uuid cotable_id_;
1102
1103
  // PG table OID of the non-primary table this schema belongs to in a tablet with colocated
1104
  // tables. Nil for the primary or single-tenant table.
1105
  PgTableOid pgtable_id_;
1106
1107
  PgSchemaName pgschema_name_;
1108
1109
  // NOTE: if you add more members, make sure to add the appropriate
1110
  // code to swap() and CopyFrom() as well to prevent subtle bugs.
1111
};
1112
1113
// Helper used for schema creation/editing.
1114
//
1115
// Example:
1116
//   Status s;
1117
//   SchemaBuilder builder(base_schema);
1118
//   s = builder.RemoveColumn("value");
1119
//   s = builder.AddKeyColumn("key2", STRING);
1120
//   s = builder.AddColumn("new_c1", UINT32);
1121
//   ...
1122
//   Schema new_schema = builder.Build();
1123
//
1124
// TODO(neil): Must introduce hash_key in this builder. Currently, only YBSchemaBuilder support
1125
// hash key, and YBSchemaBuilder don't use this builder.
1126
class SchemaBuilder {
1127
 public:
1128
42.9k
  SchemaBuilder() { Reset(); }
1129
1.19k
  explicit SchemaBuilder(const Schema& schema) { Reset(schema); }
1130
1131
  void Reset();
1132
  void Reset(const Schema& schema);
1133
1134
0
  bool is_valid() const { return cols_.size() > 0; }
1135
1136
  // Set the next column ID to be assigned to columns added with
1137
  // AddColumn.
1138
276
  void set_next_column_id(ColumnId next_id) {
1139
276
    DCHECK_GE(next_id, ColumnId(0));
1140
276
    next_id_ = next_id;
1141
276
  }
1142
1143
  // Return the next column ID that would be assigned with AddColumn.
1144
276
  ColumnId next_column_id() const {
1145
276
    return next_id_;
1146
276
  }
1147
1148
2
  void set_pgtable_id(PgTableOid pgtable_id) {
1149
2
    pgtable_id_ = pgtable_id;
1150
2
  }
1151
1152
0
  PgTableOid pgtable_id() const {
1153
0
    return pgtable_id_;
1154
0
  }
1155
1156
0
  void set_pgschema_name(PgSchemaName pgschema_name) {
1157
0
    pgschema_name_ = pgschema_name;
1158
0
  }
1159
1160
0
  PgSchemaName pgschema_name() const {
1161
0
    return pgschema_name_;
1162
0
  }
1163
1164
0
  void set_cotable_id(Uuid cotable_id) {
1165
0
    cotable_id_ = cotable_id;
1166
0
  }
1167
1168
0
  Uuid cotable_id() const {
1169
0
    return cotable_id_;
1170
0
  }
1171
1172
44.1k
  Schema Build() const {
1173
44.1k
    return Schema(cols_, col_ids_, num_key_columns_, table_properties_, cotable_id_,
1174
44.1k
                  pgtable_id_, pgschema_name_);
1175
44.1k
  }
1176
3
  Schema BuildWithoutIds() const {
1177
3
    return Schema(cols_, num_key_columns_, table_properties_, cotable_id_,
1178
3
                  pgtable_id_, pgschema_name_);
1179
3
  }
1180
1181
  // assumes type is allowed in primary key -- this should be checked before getting here
1182
  // using DataType (not QLType) since primary key columns only support elementary types
1183
  CHECKED_STATUS AddKeyColumn(const std::string& name, const std::shared_ptr<QLType>& type);
1184
  CHECKED_STATUS AddKeyColumn(const std::string& name, DataType type);
1185
1186
  // assumes type is allowed in hash key -- this should be checked before getting here
1187
  // using DataType (not QLType) since hash key columns only support elementary types
1188
  CHECKED_STATUS AddHashKeyColumn(const std::string& name, const std::shared_ptr<QLType>& type);
1189
  CHECKED_STATUS AddHashKeyColumn(const std::string& name, DataType type);
1190
1191
  CHECKED_STATUS AddColumn(const ColumnSchema& column, bool is_key);
1192
1193
221k
  CHECKED_STATUS AddColumn(const std::string& name, const std::shared_ptr<QLType>& type) {
1194
221k
    return AddColumn(name, type, false, false, false, false, 0,
1195
221k
                     SortingType::kNotSpecified);
1196
221k
  }
1197
1198
  // convenience function for adding columns with simple (non-parametric) data types
1199
  CHECKED_STATUS AddColumn(const std::string& name, DataType type);
1200
1201
2
  CHECKED_STATUS AddNullableColumn(const std::string& name, const std::shared_ptr<QLType>& type) {
1202
2
    return AddColumn(name, type, true, false, false, false, 0,
1203
2
                     SortingType::kNotSpecified);
1204
2
  }
1205
1206
  // convenience function for adding columns with simple (non-parametric) data types
1207
  CHECKED_STATUS AddNullableColumn(const std::string& name, DataType type);
1208
1209
  CHECKED_STATUS AddColumn(const std::string& name,
1210
                           const std::shared_ptr<QLType>& type,
1211
                           bool is_nullable,
1212
                           bool is_hash_key,
1213
                           bool is_static,
1214
                           bool is_counter,
1215
                           int32_t order,
1216
                           yb::SortingType sorting_type);
1217
1218
  // convenience function for adding columns with simple (non-parametric) data types
1219
  CHECKED_STATUS AddColumn(const std::string& name,
1220
                           DataType type,
1221
                           bool is_nullable,
1222
                           bool is_hash_key,
1223
                           bool is_static,
1224
                           bool is_counter,
1225
                           int32_t order,
1226
                           yb::SortingType sorting_type);
1227
1228
  CHECKED_STATUS RemoveColumn(const std::string& name);
1229
  CHECKED_STATUS RenameColumn(const std::string& old_name, const std::string& new_name);
1230
  CHECKED_STATUS AlterProperties(const TablePropertiesPB& pb);
1231
1232
 private:
1233
  ColumnId next_id_;
1234
  vector<ColumnId> col_ids_;
1235
  vector<ColumnSchema> cols_;
1236
  std::unordered_set<string> col_names_;
1237
  size_t num_key_columns_;
1238
  TableProperties table_properties_;
1239
  PgTableOid pgtable_id_ = 0;
1240
  PgSchemaName pgschema_name_ = "";
1241
  Uuid cotable_id_ = Uuid::Nil();
1242
1243
  DISALLOW_COPY_AND_ASSIGN(SchemaBuilder);
1244
};
1245
} // namespace yb
1246
1247
// Specialize std::hash for ColumnId
1248
namespace std {
1249
template<>
1250
struct hash<yb::ColumnId> {
1251
5.45M
  int operator()(const yb::ColumnId& col_id) const {
1252
5.45M
    return col_id;
1253
5.45M
  }
1254
};
1255
} // namespace std
1256
1257
#endif  // YB_COMMON_SCHEMA_H