/Users/deen/code/yugabyte-db/src/yb/common/entity_ids.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) YugaByte, Inc. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
4 | | // in compliance with the License. You may obtain a copy of the License at |
5 | | // |
6 | | // http://www.apache.org/licenses/LICENSE-2.0 |
7 | | // |
8 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
9 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
10 | | // or implied. See the License for the specific language governing permissions and limitations |
11 | | // under the License. |
12 | | // |
13 | | |
14 | | #include <boost/uuid/nil_generator.hpp> |
15 | | |
16 | | #include "yb/common/entity_ids.h" |
17 | | |
18 | | #include "yb/gutil/strings/escaping.h" |
19 | | #include "yb/util/cast.h" |
20 | | #include "yb/util/result.h" |
21 | | |
22 | | using boost::uuids::uuid; |
23 | | |
24 | | namespace yb { |
25 | | |
26 | | static constexpr int kUuidVersion = 3; // Repurpose old name-based UUID v3 to embed Postgres oids. |
27 | | |
28 | | const uint32_t kTemplate1Oid = 1; // Hardcoded for template1. (in initdb.c) |
29 | | const uint32_t kPgProcTableOid = 1255; // Hardcoded for pg_proc. (in pg_proc.h) |
30 | | |
31 | | // This should match the value for pg_yb_catalog_version hardcoded in pg_yb_catalog_version.h. |
32 | | const uint32_t kPgYbCatalogVersionTableOid = 8010; |
33 | | |
34 | | // This should match the value for pg_tablespace hardcoded in pg_tablespace.h |
35 | | const uint32_t kPgTablespaceTableOid = 1213; |
36 | | |
37 | | // Static initialization is OK because this won't be used in another static initialization. |
38 | | const TableId kPgProcTableId = GetPgsqlTableId(kTemplate1Oid, kPgProcTableOid); |
39 | | const TableId kPgYbCatalogVersionTableId = |
40 | | GetPgsqlTableId(kTemplate1Oid, kPgYbCatalogVersionTableOid); |
41 | | const TableId kPgTablespaceTableId = |
42 | | GetPgsqlTableId(kTemplate1Oid, kPgTablespaceTableOid); |
43 | | const string kPgSequencesDataNamespaceId = |
44 | | GetPgsqlNamespaceId(kPgSequencesDataDatabaseOid); |
45 | | |
46 | | |
47 | | |
48 | | //------------------------------------------------------------------------------------------------- |
49 | | |
50 | | namespace { |
51 | | |
52 | | // Layout of Postgres database and table 4-byte oids in a YugaByte 16-byte table UUID: |
53 | | // |
54 | | // +-----------------------------------------------------------------------------------------------+ |
55 | | // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
56 | | // +-----------------------------------------------------------------------------------------------+ |
57 | | // | database | | vsn | | var | | | table | |
58 | | // | oid | | | | | | | oid | |
59 | | // +-----------------------------------------------------------------------------------------------+ |
60 | | |
61 | 9.63M | void UuidSetDatabaseId(const uint32_t database_oid, uuid* id) { |
62 | 9.63M | id->data[0] = database_oid >> 24 & 0xFF; |
63 | 9.63M | id->data[1] = database_oid >> 16 & 0xFF; |
64 | 9.63M | id->data[2] = database_oid >> 8 & 0xFF; |
65 | 9.63M | id->data[3] = database_oid & 0xFF; |
66 | 9.63M | } |
67 | | |
68 | 9.58M | void UuidSetTableIds(const uint32_t table_oid, uuid* id) { |
69 | 9.58M | id->data[12] = table_oid >> 24 & 0xFF; |
70 | 9.58M | id->data[13] = table_oid >> 16 & 0xFF; |
71 | 9.58M | id->data[14] = table_oid >> 8 & 0xFF; |
72 | 9.58M | id->data[15] = table_oid & 0xFF; |
73 | 9.58M | } |
74 | | |
75 | 9.63M | std::string UuidToString(uuid* id) { |
76 | | // Set variant that is stored in octet 7, which is index 8, since indexes count backwards. |
77 | | // Variant must be 0b10xxxxxx for RFC 4122 UUID variant 1. |
78 | 9.63M | id->data[8] &= 0xBF; |
79 | 9.63M | id->data[8] |= 0x80; |
80 | | |
81 | | // Set version that is stored in octet 9 which is index 6, since indexes count backwards. |
82 | 9.63M | id->data[6] &= 0x0F; |
83 | 9.63M | id->data[6] |= (kUuidVersion << 4); |
84 | | |
85 | 9.63M | return b2a_hex(to_char_ptr(id->data), sizeof(id->data)); |
86 | 9.63M | } |
87 | | |
88 | | } // namespace |
89 | | |
90 | 40.1k | NamespaceId GetPgsqlNamespaceId(const uint32_t database_oid) { |
91 | 40.1k | uuid id = boost::uuids::nil_uuid(); |
92 | 40.1k | UuidSetDatabaseId(database_oid, &id); |
93 | 40.1k | return UuidToString(&id); |
94 | 40.1k | } |
95 | | |
96 | 9.58M | TableId GetPgsqlTableId(const uint32_t database_oid, const uint32_t table_oid) { |
97 | 9.58M | uuid id = boost::uuids::nil_uuid(); |
98 | 9.58M | UuidSetDatabaseId(database_oid, &id); |
99 | 9.58M | UuidSetTableIds(table_oid, &id); |
100 | 9.58M | return UuidToString(&id); |
101 | 9.58M | } |
102 | | |
103 | 474 | TablegroupId GetPgsqlTablegroupId(const uint32_t database_oid, const uint32_t tablegroup_oid) { |
104 | 474 | return GetPgsqlTableId(database_oid, tablegroup_oid); |
105 | 474 | } |
106 | | |
107 | 9.15k | TablespaceId GetPgsqlTablespaceId(const uint32_t tablespace_oid) { |
108 | 9.15k | uuid id = boost::uuids::nil_uuid(); |
109 | | // Tablespace is an entity across databases so this is better than UuidSetTableIds. |
110 | 9.15k | UuidSetDatabaseId(tablespace_oid, &id); |
111 | 9.15k | return UuidToString(&id); |
112 | 9.15k | } |
113 | | |
114 | 743k | bool IsPgsqlId(const string& id) { |
115 | 743k | if (id.size() != 32) return false3.12k ; // Ignore non-UUID id like "sys.catalog.uuid" |
116 | 740k | try { |
117 | 740k | size_t pos = 0; |
118 | 740k | #ifndef NDEBUG |
119 | 740k | const int variant = std::stoi(id.substr(8 * 2, 2), &pos, 16); |
120 | 740k | DCHECK((pos == 2) && (variant & 0xC0) == 0x80) << "Invalid Postgres id " << id0 ; |
121 | 740k | #endif |
122 | | |
123 | 740k | const int version = std::stoi(id.substr(6 * 2, 2), &pos, 16); |
124 | 740k | if ((pos == 2) && (version & 0xF0) >> 4 == kUuidVersion) return true691k ; |
125 | | |
126 | 740k | } catch(const std::invalid_argument&) { |
127 | 0 | } catch(const std::out_of_range&) { |
128 | 0 | } |
129 | | |
130 | 48.4k | return false; |
131 | 740k | } |
132 | | |
133 | 155k | Result<uint32_t> GetPgsqlOid(const std::string& str, size_t offset, const char* name) { |
134 | 155k | SCHECK(IsPgsqlId(str), InvalidArgument, Format("Not a YSQL ID string: $0", str)); |
135 | 155k | try { |
136 | 155k | size_t pos = 0; |
137 | 155k | const uint32_t oid = static_cast<uint32_t>( |
138 | 155k | stoul(str.substr(offset, sizeof(uint32_t) * 2), &pos, 16)); |
139 | 155k | if (pos == sizeof(uint32_t) * 2) { |
140 | 155k | return oid; |
141 | 155k | } |
142 | 155k | } catch(const std::invalid_argument&) { |
143 | 0 | } catch(const std::out_of_range&) { |
144 | 0 | } |
145 | | |
146 | 0 | return STATUS_FORMAT(InvalidArgument, "Invalid PostgreSQL $0: $1", name, str); |
147 | 155k | } |
148 | | |
149 | 98.9k | Result<uint32_t> GetPgsqlDatabaseOid(const NamespaceId& namespace_id) { |
150 | 98.9k | return GetPgsqlOid(namespace_id, 0, "namespace id"); |
151 | 98.9k | } |
152 | | |
153 | 50.9k | Result<uint32_t> GetPgsqlTableOid(const TableId& table_id) { |
154 | 50.9k | return GetPgsqlOid(table_id, 12 * 2, "table id"); |
155 | 50.9k | } |
156 | | |
157 | 0 | Result<uint32_t> GetPgsqlTablegroupOid(const TablegroupId& tablegroup_id) { |
158 | 0 | return GetPgsqlOid(tablegroup_id, 12 * 2, "tablegroup id"); |
159 | 0 | } |
160 | | |
161 | 0 | Result<uint32_t> GetPgsqlTablegroupOidByTableId(const TableId& table_id) { |
162 | 0 | if (table_id.size() < 32) { |
163 | 0 | return STATUS(InvalidArgument, "Invalid PostgreSQL table id for tablegroup", table_id); |
164 | 0 | } |
165 | 0 | TablegroupId tablegroup_id = table_id.substr(0, 32); |
166 | |
|
167 | 0 | return GetPgsqlTablegroupOid(tablegroup_id); |
168 | 0 | } |
169 | | |
170 | 5.44k | Result<uint32_t> GetPgsqlDatabaseOidByTableId(const TableId& table_id) { |
171 | 5.44k | return GetPgsqlOid(table_id, 0, "table id"); |
172 | 5.44k | } |
173 | | |
174 | 12 | Result<uint32_t> GetPgsqlTablespaceOid(const TablespaceId& tablespace_id) { |
175 | 12 | return GetPgsqlOid(tablespace_id, 0, "tablespace id"); |
176 | 12 | } |
177 | | |
178 | | } // namespace yb |