YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/yb/yql/pggate/pg_ddl.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_ddl.h"
17
18
#include "yb/client/yb_op.h"
19
#include "yb/client/yb_table_name.h"
20
21
#include "yb/common/common.pb.h"
22
#include "yb/common/constants.h"
23
#include "yb/common/entity_ids.h"
24
#include "yb/common/pg_system_attr.h"
25
26
#include "yb/util/flag_tags.h"
27
#include "yb/util/status_format.h"
28
#include "yb/util/status_log.h"
29
#include "yb/util/tsan_util.h"
30
31
#include "yb/yql/pggate/pg_client.h"
32
33
DEFINE_test_flag(int32, user_ddl_operation_timeout_sec, 0,
34
                 "Adjusts the timeout for a DDL operation from the YBClient default, if non-zero.");
35
36
DECLARE_int32(max_num_tablets_for_table);
37
38
namespace yb {
39
namespace pggate {
40
41
using std::make_shared;
42
using std::shared_ptr;
43
using std::string;
44
using namespace std::literals;  // NOLINT
45
46
using client::YBSession;
47
using client::YBMetaDataCache;
48
49
// TODO(neil) This should be derived from a GFLAGS.
50
static MonoDelta kDdlTimeout = 60s * kTimeMultiplier;
51
52
namespace {
53
54
6.43k
CoarseTimePoint DdlDeadline() {
55
6.43k
  auto timeout = MonoDelta::FromSeconds(FLAGS_TEST_user_ddl_operation_timeout_sec);
56
6.43k
  if (timeout == MonoDelta::kZero) {
57
6.42k
    timeout = kDdlTimeout;
58
6.42k
  }
59
6.43k
  return CoarseMonoClock::now() + timeout;
60
6.43k
}
61
62
} // namespace
63
64
//--------------------------------------------------------------------------------------------------
65
// PgCreateDatabase
66
//--------------------------------------------------------------------------------------------------
67
68
PgCreateDatabase::PgCreateDatabase(PgSession::ScopedRefPtr pg_session,
69
                                   const char *database_name,
70
                                   const PgOid database_oid,
71
                                   const PgOid source_database_oid,
72
                                   const PgOid next_oid,
73
                                   const bool colocated)
74
134
    : PgDdl(std::move(pg_session)) {
75
134
  req_.set_database_name(database_name);
76
134
  req_.set_database_oid(database_oid);
77
134
  req_.set_source_database_oid(source_database_oid);
78
134
  req_.set_next_oid(next_oid);
79
134
  req_.set_colocated(colocated);
80
134
}
81
82
134
PgCreateDatabase::~PgCreateDatabase() {
83
134
}
84
85
134
Status PgCreateDatabase::Exec() {
86
134
  return pg_session_->pg_client().CreateDatabase(&req_, DdlDeadline());
87
134
}
88
89
PgDropDatabase::PgDropDatabase(PgSession::ScopedRefPtr pg_session,
90
                               const char *database_name,
91
                               PgOid database_oid)
92
    : PgDdl(pg_session),
93
      database_name_(database_name),
94
72
      database_oid_(database_oid) {
95
72
}
96
97
72
PgDropDatabase::~PgDropDatabase() {
98
72
}
99
100
72
Status PgDropDatabase::Exec() {
101
72
  return pg_session_->DropDatabase(database_name_, database_oid_);
102
72
}
103
104
PgAlterDatabase::PgAlterDatabase(PgSession::ScopedRefPtr pg_session,
105
                               const char *database_name,
106
                               PgOid database_oid)
107
3
    : PgDdl(pg_session) {
108
3
  req_.set_database_name(database_name);
109
3
  req_.set_database_oid(database_oid);
110
3
}
111
112
3
PgAlterDatabase::~PgAlterDatabase() {
113
3
}
114
115
3
Status PgAlterDatabase::Exec() {
116
3
  return pg_session_->pg_client().AlterDatabase(&req_, DdlDeadline());
117
3
}
118
119
3
void PgAlterDatabase::RenameDatabase(const char *newname) {
120
3
  req_.set_new_name(newname);
121
3
}
122
123
//--------------------------------------------------------------------------------------------------
124
// PgCreateTablegroup / PgDropTablegroup
125
//--------------------------------------------------------------------------------------------------
126
127
PgCreateTablegroup::PgCreateTablegroup(PgSession::ScopedRefPtr pg_session,
128
                                       const char *database_name,
129
                                       const PgOid database_oid,
130
                                       const PgOid tablegroup_oid,
131
                                       const PgOid tablespace_oid)
132
54
    : PgDdl(pg_session) {
133
54
  req_.set_database_name(database_name);
134
54
  PgObjectId(database_oid, tablegroup_oid).ToPB(req_.mutable_tablegroup_id());
135
54
  PgObjectId(database_oid, tablespace_oid).ToPB(req_.mutable_tablespace_id());
136
54
}
137
138
54
PgCreateTablegroup::~PgCreateTablegroup() {
139
54
}
140
141
54
Status PgCreateTablegroup::Exec() {
142
54
  return pg_session_->pg_client().CreateTablegroup(&req_, DdlDeadline());
143
54
}
144
145
PgDropTablegroup::PgDropTablegroup(PgSession::ScopedRefPtr pg_session,
146
                                   const PgOid database_oid,
147
                                   const PgOid tablegroup_oid)
148
39
    : PgDdl(pg_session) {
149
39
  PgObjectId(database_oid, tablegroup_oid).ToPB(req_.mutable_tablegroup_id());
150
39
}
151
152
39
PgDropTablegroup::~PgDropTablegroup() {
153
39
}
154
155
39
Status PgDropTablegroup::Exec() {
156
39
  return pg_session_->pg_client().DropTablegroup(&req_, DdlDeadline());
157
39
}
158
159
//--------------------------------------------------------------------------------------------------
160
// PgCreateTable
161
//--------------------------------------------------------------------------------------------------
162
163
PgCreateTable::PgCreateTable(PgSession::ScopedRefPtr pg_session,
164
                             const char *database_name,
165
                             const char *schema_name,
166
                             const char *table_name,
167
                             const PgObjectId& table_id,
168
                             bool is_shared_table,
169
                             bool if_not_exist,
170
                             bool add_primary_key,
171
                             const bool colocated,
172
                             const PgObjectId& tablegroup_oid,
173
                             const ColocationId colocation_id,
174
                             const PgObjectId& tablespace_oid,
175
                             const PgObjectId& matview_pg_table_oid)
176
5.14k
    : PgDdl(pg_session) {
177
5.14k
  table_id.ToPB(req_.mutable_table_id());
178
5.14k
  req_.set_database_name(database_name);
179
5.14k
  req_.set_table_name(table_name);
180
5.14k
  req_.set_num_tablets(-1);
181
5.14k
  req_.set_is_pg_catalog_table(strcmp(schema_name, "pg_catalog") == 0 ||
182
5.14k
                               
strcmp(schema_name, "information_schema") == 04.85k
);
183
5.14k
  req_.set_is_shared_table(is_shared_table);
184
5.14k
  req_.set_if_not_exist(if_not_exist);
185
5.14k
  req_.set_colocated(colocated);
186
5.14k
  req_.set_schema_name(schema_name);
187
5.14k
  tablegroup_oid.ToPB(req_.mutable_tablegroup_oid());
188
5.14k
  if (colocation_id != kColocationIdNotSet) {
189
24
    req_.set_colocation_id(colocation_id);
190
24
  }
191
5.14k
  tablespace_oid.ToPB(req_.mutable_tablespace_oid());
192
5.14k
  matview_pg_table_oid.ToPB(req_.mutable_matview_pg_table_oid());
193
194
  // Add internal primary key column to a Postgres table without a user-specified primary key.
195
5.14k
  if (add_primary_key) {
196
    // For regular user table, ybrowid should be a hash key because ybrowid is a random uuid.
197
    // For colocated or sys catalog table, ybrowid should be a range key because they are
198
    // unpartitioned tables in a single tablet.
199
2.25k
    bool is_hash = !(req_.is_pg_catalog_table() || 
colocated2.22k
||
tablegroup_oid.IsValid()2.20k
);
200
2.25k
    CHECK_OK(AddColumn("ybrowid", static_cast<int32_t>(PgSystemAttrNum::kYBRowId),
201
2.25k
                       YB_YQL_DATA_TYPE_BINARY, is_hash, true /* is_range */));
202
2.25k
  }
203
5.14k
}
204
205
Status PgCreateTable::AddColumnImpl(const char *attr_name,
206
                                    int attr_num,
207
                                    int attr_ybtype,
208
                                    int pg_type_oid,
209
                                    bool is_hash,
210
                                    bool is_range,
211
13.9k
                                    SortingType sorting_type) {
212
13.9k
  auto& column = *req_.mutable_create_columns()->Add();
213
13.9k
  column.set_attr_name(attr_name);
214
13.9k
  column.set_attr_num(attr_num);
215
13.9k
  column.set_attr_ybtype(attr_ybtype);
216
13.9k
  column.set_is_hash(is_hash);
217
13.9k
  column.set_is_range(is_range);
218
13.9k
  column.set_sorting_type(sorting_type);
219
13.9k
  column.set_attr_pgoid(pg_type_oid);
220
13.9k
  return Status::OK();
221
13.9k
}
222
223
353
Status PgCreateTable::SetNumTablets(int32_t num_tablets) {
224
353
  if (num_tablets < 0) {
225
0
    return STATUS(InvalidArgument, "num_tablets cannot be less than zero");
226
0
  }
227
353
  if (num_tablets > FLAGS_max_num_tablets_for_table) {
228
1
    return STATUS(InvalidArgument, "num_tablets exceeds system limit");
229
1
  }
230
231
352
  req_.set_num_tablets(num_tablets);
232
352
  return Status::OK();
233
353
}
234
235
181
Status PgCreateTable::AddSplitBoundary(PgExpr **exprs, int expr_count) {
236
181
  auto* values = req_.mutable_split_bounds()->Add()->mutable_values();
237
459
  for (int i = 0; i < expr_count; 
++i278
) {
238
278
    RETURN_NOT_OK(exprs[i]->Eval(values->Add()));
239
278
  }
240
181
  return Status::OK();
241
181
}
242
243
5.05k
Status PgCreateTable::Exec() {
244
5.05k
  RETURN_NOT_OK(pg_session_->pg_client().CreateTable(&req_, DdlDeadline()));
245
5.02k
  auto base_table_id = PgObjectId::FromPB(req_.base_table_id());
246
5.02k
  if (base_table_id.IsValid()) {
247
855
    pg_session_->InvalidateTableCache(base_table_id, InvalidateOnPgClient::kFalse);
248
855
  }
249
5.02k
  return Status::OK();
250
5.05k
}
251
252
void PgCreateTable::SetupIndex(
253
868
    const PgObjectId& base_table_id, bool is_unique_index, bool skip_index_backfill) {
254
868
  base_table_id.ToPB(req_.mutable_base_table_id());
255
868
  req_.set_is_unique_index(is_unique_index);
256
868
  req_.set_skip_index_backfill(skip_index_backfill);
257
868
}
258
259
17.3k
StmtOp PgCreateTable::stmt_op() const {
260
17.3k
  return PgObjectId::FromPB(req_.base_table_id()).IsValid()
261
17.3k
      ? 
StmtOp::STMT_CREATE_INDEX2.17k
:
StmtOp::STMT_CREATE_TABLE15.1k
;
262
17.3k
}
263
264
//--------------------------------------------------------------------------------------------------
265
// PgDropTable
266
//--------------------------------------------------------------------------------------------------
267
268
PgDropTable::PgDropTable(PgSession::ScopedRefPtr pg_session,
269
                         const PgObjectId& table_id,
270
                         bool if_exist)
271
    : PgDdl(pg_session),
272
      table_id_(table_id),
273
4.16k
      if_exist_(if_exist) {
274
4.16k
}
275
276
4.16k
PgDropTable::~PgDropTable() {
277
4.16k
}
278
279
3.48k
Status PgDropTable::Exec() {
280
3.48k
  Status s = pg_session_->DropTable(table_id_);
281
3.48k
  pg_session_->InvalidateTableCache(table_id_, InvalidateOnPgClient::kFalse);
282
3.48k
  if (s.ok() || 
(5
s.IsNotFound()5
&&
if_exist_2
)) {
283
3.47k
    return Status::OK();
284
3.47k
  }
285
5
  return s;
286
3.48k
}
287
288
//--------------------------------------------------------------------------------------------------
289
// PgTruncateTable
290
//--------------------------------------------------------------------------------------------------
291
292
PgTruncateTable::PgTruncateTable(PgSession::ScopedRefPtr pg_session,
293
                                 const PgObjectId& table_id)
294
624
    : PgDdl(pg_session) {
295
624
  table_id.ToPB(req_.mutable_table_id());
296
624
}
297
298
624
PgTruncateTable::~PgTruncateTable() {
299
624
}
300
301
624
Status PgTruncateTable::Exec() {
302
624
  return pg_session_->pg_client().TruncateTable(&req_, DdlDeadline());
303
624
}
304
305
//--------------------------------------------------------------------------------------------------
306
// PgDropIndex
307
//--------------------------------------------------------------------------------------------------
308
309
PgDropIndex::PgDropIndex(PgSession::ScopedRefPtr pg_session,
310
                         const PgObjectId& index_id,
311
                         bool if_exist)
312
672
    : PgDropTable(pg_session, index_id, if_exist) {
313
672
}
314
315
672
PgDropIndex::~PgDropIndex() {
316
672
}
317
318
669
Status PgDropIndex::Exec() {
319
669
  client::YBTableName indexed_table_name;
320
669
  Status s = pg_session_->DropIndex(table_id_, &indexed_table_name);
321
669
  if (s.ok() || 
(2
s.IsNotFound()2
&&
if_exist_0
)) {
322
667
    RSTATUS_DCHECK(!indexed_table_name.empty(), Uninitialized, "indexed_table_name uninitialized");
323
667
    PgObjectId indexed_table_id(indexed_table_name.table_id());
324
325
667
    pg_session_->InvalidateTableCache(table_id_, InvalidateOnPgClient::kFalse);
326
667
    pg_session_->InvalidateTableCache(indexed_table_id, InvalidateOnPgClient::kFalse);
327
667
    return Status::OK();
328
667
  }
329
2
  return s;
330
669
}
331
332
//--------------------------------------------------------------------------------------------------
333
// PgAlterTable
334
//--------------------------------------------------------------------------------------------------
335
336
PgAlterTable::PgAlterTable(PgSession::ScopedRefPtr pg_session,
337
                           const PgObjectId& table_id)
338
1.71k
    : PgDdl(pg_session) {
339
1.71k
  table_id.ToPB(req_.mutable_table_id());
340
1.71k
}
341
342
Status PgAlterTable::AddColumn(const char *name,
343
                               const YBCPgTypeEntity *attr_type,
344
238
                               int order) {
345
238
  auto& col = *req_.mutable_add_columns()->Add();
346
238
  col.set_attr_name(name);
347
238
  col.set_attr_ybtype(attr_type->yb_type);
348
238
  col.set_attr_num(order);
349
238
  col.set_attr_pgoid(attr_type->type_oid);
350
238
  return Status::OK();
351
238
}
352
353
17
Status PgAlterTable::RenameColumn(const char *oldname, const char *newname) {
354
17
  auto& rename = *req_.mutable_rename_columns()->Add();
355
17
  rename.set_old_name(oldname);
356
17
  rename.set_new_name(newname);
357
17
  return Status::OK();
358
17
}
359
360
408
Status PgAlterTable::DropColumn(const char *name) {
361
408
  req_.mutable_drop_columns()->Add(name);
362
408
  return Status::OK();
363
408
}
364
365
115
Status PgAlterTable::RenameTable(const char *db_name, const char *newname) {
366
115
  auto& rename = *req_.mutable_rename_table();
367
115
  rename.set_database_name(db_name);
368
115
  rename.set_table_name(newname);
369
115
  return Status::OK();
370
115
}
371
372
522
Status PgAlterTable::Exec() {
373
522
  RETURN_NOT_OK(pg_session_->pg_client().AlterTable(&req_, DdlDeadline()));
374
520
  pg_session_->InvalidateTableCache(
375
520
      PgObjectId::FromPB(req_.table_id()), InvalidateOnPgClient::kFalse);
376
520
  return Status::OK();
377
522
}
378
379
1.71k
PgAlterTable::~PgAlterTable() {
380
1.71k
}
381
382
}  // namespace pggate
383
}  // namespace yb