/Users/deen/code/yugabyte-db/src/yb/yql/pggate/pg_tabledesc.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 "yb/yql/pggate/pg_tabledesc.h" |
17 | | |
18 | | #include "yb/client/schema.h" |
19 | | #include "yb/client/table.h" |
20 | | #include "yb/client/yb_op.h" |
21 | | |
22 | | #include "yb/common/partition.h" |
23 | | #include "yb/common/pg_system_attr.h" |
24 | | #include "yb/common/schema.h" |
25 | | #include "yb/common/wire_protocol.h" |
26 | | |
27 | | #include "yb/docdb/doc_key.h" |
28 | | |
29 | | #include "yb/gutil/casts.h" |
30 | | |
31 | | #include "yb/util/result.h" |
32 | | #include "yb/util/status_format.h" |
33 | | |
34 | | namespace yb { |
35 | | namespace pggate { |
36 | | |
37 | | PgTableDesc::PgTableDesc( |
38 | | const PgObjectId& id, const master::GetTableSchemaResponsePB& resp, |
39 | | std::shared_ptr<client::VersionedTablePartitionList> partitions) |
40 | 191k | : id_(id), resp_(resp), table_partitions_(std::move(partitions)) { |
41 | 191k | table_name_.GetFromTableIdentifierPB(resp.identifier()); |
42 | 191k | } |
43 | | |
44 | 191k | Status PgTableDesc::Init() { |
45 | 191k | RETURN_NOT_OK(SchemaFromPB(resp_.schema(), &schema_)); |
46 | 191k | size_t idx = 0; |
47 | 1.72M | for (const auto& column : schema().columns()) { |
48 | 1.72M | attr_num_map_.emplace(column.order(), idx++); |
49 | 1.72M | } |
50 | 191k | return PartitionSchema::FromPB(resp_.partition_schema(), schema_, &partition_schema_); |
51 | 191k | } |
52 | | |
53 | 54.6M | Result<size_t> PgTableDesc::FindColumn(int attr_num) const { |
54 | | // Find virtual columns. |
55 | 54.6M | if (attr_num == static_cast<int>(PgSystemAttrNum::kYBTupleId)) { |
56 | 7.26M | return num_columns(); |
57 | 7.26M | } |
58 | | |
59 | | // Find physical column. |
60 | 47.3M | const auto itr = attr_num_map_.find(attr_num); |
61 | 47.3M | if (itr != attr_num_map_.end()47.3M ) { |
62 | 47.3M | return itr->second; |
63 | 47.3M | } |
64 | | |
65 | 18.4E | return STATUS_FORMAT(InvalidArgument, "Invalid column number $0", attr_num); |
66 | 47.3M | } |
67 | | |
68 | 83.9M | Result<YBCPgColumnInfo> PgTableDesc::GetColumnInfo(int16_t attr_number) const { |
69 | 83.9M | YBCPgColumnInfo column_info { |
70 | 83.9M | .is_primary = false, |
71 | 83.9M | .is_hash = false |
72 | 83.9M | }; |
73 | 83.9M | const auto itr = attr_num_map_.find(attr_number); |
74 | 83.9M | if (itr != attr_num_map_.end()) { |
75 | 71.5M | column_info.is_primary = itr->second < schema().num_key_columns(); |
76 | 71.5M | column_info.is_hash = itr->second < schema().num_hash_key_columns(); |
77 | 71.5M | } |
78 | 83.9M | return column_info; |
79 | 83.9M | } |
80 | | |
81 | 5.63k | bool PgTableDesc::IsColocated() const { |
82 | 5.63k | return resp_.colocated(); |
83 | 5.63k | } |
84 | | |
85 | 249 | YBCPgOid PgTableDesc::GetColocationId() const { |
86 | 249 | return schema().has_colocation_id() ? schema().colocation_id()79 : kColocationIdNotSet170 ; |
87 | 249 | } |
88 | | |
89 | 1.54M | bool PgTableDesc::IsHashPartitioned() const { |
90 | 1.54M | return schema().num_hash_key_columns() > 0; |
91 | 1.54M | } |
92 | | |
93 | 3.07M | bool PgTableDesc::IsRangePartitioned() const { |
94 | 3.07M | return schema().num_hash_key_columns() == 0; |
95 | 3.07M | } |
96 | | |
97 | 14.0k | const std::vector<std::string>& PgTableDesc::GetPartitions() const { |
98 | 14.0k | return table_partitions_->keys; |
99 | 14.0k | } |
100 | | |
101 | 4.36M | const std::string& PgTableDesc::LastPartition() const { |
102 | 4.36M | return table_partitions_->keys.back(); |
103 | 4.36M | } |
104 | | |
105 | 1.55M | size_t PgTableDesc::GetPartitionCount() const { |
106 | 1.55M | return table_partitions_->keys.size(); |
107 | 1.55M | } |
108 | | |
109 | 1.54M | Result<string> PgTableDesc::DecodeYbctid(const Slice& ybctid) const { |
110 | | // TODO(neil) If a partition schema can have both hash and range partitioning, this function needs |
111 | | // to be updated to return appropriate primary key. |
112 | 1.54M | RSTATUS_DCHECK(!IsHashPartitioned() || !IsRangePartitioned(), InvalidArgument, |
113 | 1.54M | "Partitioning schema by both hash and range is not yet supported"); |
114 | | |
115 | | // Use range key if there's no hash columns. |
116 | | // NOTE: Also see bug github #5832. |
117 | 1.54M | if (IsRangePartitioned()) { |
118 | | // Decoding using range partitioning method. |
119 | 19.4k | return ybctid.ToBuffer(); |
120 | 19.4k | } |
121 | | |
122 | | // Decoding using hash partitioning method. |
123 | | // Do not check with predicate IsHashPartitioning() for now to use existing behavior by default. |
124 | 1.52M | uint16 hash_code = VERIFY_RESULT(docdb::DocKey::DecodeHash(ybctid)); |
125 | 0 | return PartitionSchema::EncodeMultiColumnHashValue(hash_code); |
126 | 1.52M | } |
127 | | |
128 | 1.54M | Result<size_t> PgTableDesc::FindPartitionIndex(const Slice& ybctid) const { |
129 | | // Find partition index based on ybctid value. |
130 | | // - Hash Partition: ybctid -> hashcode -> key -> partition index. |
131 | | // - Range Partition: ybctid == key -> partition index. |
132 | 1.54M | string partition_key = VERIFY_RESULT(DecodeYbctid(ybctid)); |
133 | 0 | return client::FindPartitionStartIndex(table_partitions_->keys, partition_key); |
134 | 1.54M | } |
135 | | |
136 | | Status PgTableDesc::SetScanBoundary(PgsqlReadRequestPB *req, |
137 | | const string& partition_lower_bound, |
138 | | bool lower_bound_is_inclusive, |
139 | | const string& partition_upper_bound, |
140 | 27.7k | bool upper_bound_is_inclusive) { |
141 | | // Setup lower boundary. |
142 | 27.7k | if (!partition_lower_bound.empty()) { |
143 | 17.5k | req->mutable_lower_bound()->set_key(partition_lower_bound); |
144 | 17.5k | req->mutable_lower_bound()->set_is_inclusive(lower_bound_is_inclusive); |
145 | 17.5k | } |
146 | | |
147 | | // Setup upper boundary. |
148 | 27.7k | if (!partition_upper_bound.empty()) { |
149 | 19.0k | req->mutable_upper_bound()->set_key(partition_upper_bound); |
150 | 19.0k | req->mutable_upper_bound()->set_is_inclusive(upper_bound_is_inclusive); |
151 | 19.0k | } |
152 | | |
153 | 27.7k | return Status::OK(); |
154 | 27.7k | } |
155 | | |
156 | 2 | const client::YBTableName& PgTableDesc::table_name() const { |
157 | 2 | return table_name_; |
158 | 2 | } |
159 | | |
160 | 27.6M | size_t PgTableDesc::num_hash_key_columns() const { |
161 | 27.6M | return schema().num_hash_key_columns(); |
162 | 27.6M | } |
163 | | |
164 | 19.6M | size_t PgTableDesc::num_key_columns() const { |
165 | 19.6M | return schema().num_key_columns(); |
166 | 19.6M | } |
167 | | |
168 | 18.1M | size_t PgTableDesc::num_columns() const { |
169 | 18.1M | return schema().num_columns(); |
170 | 18.1M | } |
171 | | |
172 | 15.9M | const PartitionSchema& PgTableDesc::partition_schema() const { |
173 | 15.9M | return partition_schema_; |
174 | 15.9M | } |
175 | | |
176 | 350M | const Schema& PgTableDesc::schema() const { |
177 | 350M | return schema_; |
178 | 350M | } |
179 | | |
180 | 8.80M | uint32_t PgTableDesc::schema_version() const { |
181 | 8.80M | return resp_.version(); |
182 | 8.80M | } |
183 | | |
184 | | } // namespace pggate |
185 | | } // namespace yb |