YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/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