YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

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