YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
2.98M
void UuidSetDatabaseId(const uint32_t database_oid, uuid* id) {
62
2.98M
  id->data[0] = database_oid >> 24 & 0xFF;
63
2.98M
  id->data[1] = database_oid >> 16 & 0xFF;
64
2.98M
  id->data[2] = database_oid >> 8  & 0xFF;
65
2.98M
  id->data[3] = database_oid & 0xFF;
66
2.98M
}
67
68
2.96M
void UuidSetTableIds(const uint32_t table_oid, uuid* id) {
69
2.96M
  id->data[12] = table_oid >> 24 & 0xFF;
70
2.96M
  id->data[13] = table_oid >> 16 & 0xFF;
71
2.96M
  id->data[14] = table_oid >> 8  & 0xFF;
72
2.96M
  id->data[15] = table_oid & 0xFF;
73
2.96M
}
74
75
2.98M
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
2.98M
  id->data[8] &= 0xBF;
79
2.98M
  id->data[8] |= 0x80;
80
81
  // Set version that is stored in octet 9 which is index 6, since indexes count backwards.
82
2.98M
  id->data[6] &= 0x0F;
83
2.98M
  id->data[6] |= (kUuidVersion << 4);
84
85
2.98M
  return b2a_hex(to_char_ptr(id->data), sizeof(id->data));
86
2.98M
}
87
88
} // namespace
89
90
20.6k
NamespaceId GetPgsqlNamespaceId(const uint32_t database_oid) {
91
20.6k
  uuid id = boost::uuids::nil_uuid();
92
20.6k
  UuidSetDatabaseId(database_oid, &id);
93
20.6k
  return UuidToString(&id);
94
20.6k
}
95
96
2.96M
TableId GetPgsqlTableId(const uint32_t database_oid, const uint32_t table_oid) {
97
2.96M
  uuid id = boost::uuids::nil_uuid();
98
2.96M
  UuidSetDatabaseId(database_oid, &id);
99
2.96M
  UuidSetTableIds(table_oid, &id);
100
2.96M
  return UuidToString(&id);
101
2.96M
}
102
103
9
TablegroupId GetPgsqlTablegroupId(const uint32_t database_oid, const uint32_t tablegroup_oid) {
104
9
  return GetPgsqlTableId(database_oid, tablegroup_oid);
105
9
}
106
107
966
TablespaceId GetPgsqlTablespaceId(const uint32_t tablespace_oid) {
108
966
  uuid id = boost::uuids::nil_uuid();
109
  // Tablespace is an entity across databases so this is better than UuidSetTableIds.
110
966
  UuidSetDatabaseId(tablespace_oid, &id);
111
966
  return UuidToString(&id);
112
966
}
113
114
309k
bool IsPgsqlId(const string& id) {
115
309k
  if (id.size() != 32) return false; // Ignore non-UUID id like "sys.catalog.uuid"
116
307k
  try {
117
307k
    size_t pos = 0;
118
307k
#ifndef NDEBUG
119
307k
    const int variant = std::stoi(id.substr(8 * 2, 2), &pos, 16);
120
0
    DCHECK((pos == 2) && (variant & 0xC0) == 0x80) << "Invalid Postgres id " << id;
121
307k
#endif
122
123
307k
    const int version = std::stoi(id.substr(6 * 2, 2), &pos, 16);
124
307k
    if ((pos == 2) && (version & 0xF0) >> 4 == kUuidVersion) return true;
125
126
0
  } catch(const std::invalid_argument&) {
127
0
  } catch(const std::out_of_range&) {
128
0
  }
129
130
31.5k
  return false;
131
307k
}
132
133
40.7k
Result<uint32_t> GetPgsqlOid(const std::string& str, size_t offset, const char* name) {
134
40.7k
  DCHECK(IsPgsqlId(str));
135
40.7k
  try {
136
40.7k
    size_t pos = 0;
137
40.7k
    const uint32_t oid = static_cast<uint32_t>(
138
40.7k
        stoul(str.substr(offset, sizeof(uint32_t) * 2), &pos, 16));
139
40.7k
    if (pos == sizeof(uint32_t) * 2) {
140
40.7k
      return oid;
141
40.7k
    }
142
0
  } 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
40.7k
}
148
149
23.1k
Result<uint32_t> GetPgsqlDatabaseOid(const NamespaceId& namespace_id) {
150
23.1k
  return GetPgsqlOid(namespace_id, 0, "namespace id");
151
23.1k
}
152
153
16.0k
Result<uint32_t> GetPgsqlTableOid(const TableId& table_id) {
154
16.0k
  return GetPgsqlOid(table_id, 12 * 2, "table id");
155
16.0k
}
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
1.55k
Result<uint32_t> GetPgsqlDatabaseOidByTableId(const TableId& table_id) {
171
1.55k
  return GetPgsqlOid(table_id, 0, "table id");
172
1.55k
}
173
174
0
Result<uint32_t> GetPgsqlTablespaceOid(const TablespaceId& tablespace_id) {
175
0
  return GetPgsqlOid(tablespace_id, 0, "tablespace id");
176
0
}
177
178
}  // namespace yb