Skip to content

Commit

Permalink
[#3047] Added SPLIT INTO # TABLETS to CREATE INDEX DDL
Browse files Browse the repository at this point in the history
Summary:
Extended the Postgres grammar to allow for SPLIT INTO # TABLETS in CREATE INDEX DDL
statments. Adding functionality for SPLIT AT is a WIP.

Test Plan:
Using yb-ctl performed CREATE INDEX ... SPLIT INTO # TABLETS. Confirmed using web UI.
Added to the TestPgRegressindex.java test:
```
./yb_build.sh release --java-test org.yb.pgsql.TestPgRegressIndex
```

Reviewers: neha, dmitry

Reviewed By: dmitry

Subscribers: yql

Differential Revision: https://phabricator.dev.yugabyte.com/D8583
  • Loading branch information
vvkgopalan committed Jun 3, 2020
1 parent f01cc66 commit 0909995
Show file tree
Hide file tree
Showing 16 changed files with 115 additions and 15 deletions.
6 changes: 4 additions & 2 deletions src/postgres/src/backend/catalog/index.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,8 @@ index_create(Relation heapRelation,
bits16 constr_flags,
bool allow_system_table_mods,
bool is_internal,
Oid *constraintId)
Oid *constraintId,
OptSplit *split_options)
{
Oid heapRelationId = RelationGetRelid(heapRelation);
Relation pg_class;
Expand Down Expand Up @@ -969,7 +970,8 @@ index_create(Relation heapRelation,
coloptions,
reloptions,
indexRelationId,
heapRelation);
heapRelation,
split_options);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion src/postgres/src/backend/catalog/toasting.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
BTREE_AM_OID,
rel->rd_rel->reltablespace,
collationObjectId, classObjectId, coloptions, (Datum) 0,
INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL);
INDEX_CREATE_IS_PRIMARY, 0, true, true, NULL, NULL);

heap_close(toast_rel, NoLock);

Expand Down
2 changes: 1 addition & 1 deletion src/postgres/src/backend/commands/indexcmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,7 @@ DefineIndex(Oid relationId,
coloptions, reloptions,
flags, constr_flags,
allowSystemTableMods, !check_rights,
&createdConstraintId);
&createdConstraintId, stmt->split_options);

ObjectAddressSet(address, RelationRelationId, indexRelationId);

Expand Down
36 changes: 33 additions & 3 deletions src/postgres/src/backend/commands/ybccmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ static void CreateTableHandleSplitOptions(YBCPgStatement handle,
}

/* Tell pggate about it */
YBCPgCreateTableSetNumTablets(handle, split_options->num_tablets);
HandleYBStatus(YBCPgCreateTableSetNumTablets(handle, split_options->num_tablets));
break;
case SPLIT_POINTS: ;
/* Number of columns used in the primary key */
Expand Down Expand Up @@ -368,7 +368,8 @@ static void CreateTableHandleSplitOptions(YBCPgStatement handle,
split_num++;
}

YBCPgCreateTableAddSplitRow(handle, split_columns, type_entities, (uint64_t *)datums);
HandleYBStatus(YBCPgCreateTableAddSplitRow(handle, split_columns,
type_entities, (uint64_t *)datums));
}

break;
Expand Down Expand Up @@ -602,14 +603,38 @@ YBCTruncateTable(Relation rel) {
list_free(indexlist);
}

static void CreateIndexHandleSplitOptions(YBCPgStatement handle,
OptSplit *split_options,
TupleDesc desc,
int16 * coloptions)
{
/* Address both types of split options */
switch (split_options->split_type)
{
case NUM_TABLETS:
/* Make sure we have HASH columns */
if (!(coloptions[0] & INDOPTION_HASH)) {
ereport(ERROR, (errmsg("HASH columns must be present to "
"split by number of tablets")));
}
/* Tell pggate about it */
HandleYBStatus(YBCPgCreateIndexSetNumTablets(handle, split_options->num_tablets));
break;
default:
ereport(ERROR, (errmsg("Illegal memory state for SPLIT options")));
break;
}
}

void
YBCCreateIndex(const char *indexName,
IndexInfo *indexInfo,
TupleDesc indexTupleDesc,
int16 *coloptions,
Datum reloptions,
Oid indexId,
Relation rel)
Relation rel,
OptSplit *split_options)
{
char *db_name = get_database_name(MyDatabaseId);
char *schema_name = get_namespace_name(RelationGetNamespace(rel));
Expand Down Expand Up @@ -680,6 +705,11 @@ YBCCreateIndex(const char *indexName,
is_nulls_first));
}

/* Handle SPLIT statement, if present */
if (split_options) {
CreateIndexHandleSplitOptions(handle, split_options, indexTupleDesc, coloptions);
}

/* Create the index. */
HandleYBStatus(YBCPgExecCreateIndex(handle));
}
Expand Down
1 change: 1 addition & 0 deletions src/postgres/src/backend/nodes/copyfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3481,6 +3481,7 @@ _copyIndexStmt(const IndexStmt *from)
COPY_SCALAR_FIELD(transformed);
COPY_SCALAR_FIELD(concurrent);
COPY_SCALAR_FIELD(if_not_exists);
COPY_NODE_FIELD(split_options);

return newnode;
}
Expand Down
14 changes: 8 additions & 6 deletions src/postgres/src/backend/parser/gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -7818,13 +7818,13 @@ defacl_privilege_target:
*
* QUERY: CREATE INDEX
*
* Note: we cannot put TABLESPACE clause after WHERE clause unless we are
* willing to make TABLESPACE a fully reserved word.
* Note: we cannot put TABLESPACE or SPLIT clause after WHERE clause unless we
* are willing to make TABLESPACE or SPLIT fully reserved words.
*****************************************************************************/

IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name
ON relation_expr access_method_clause '(' yb_index_params ')'
opt_include opt_reloptions OptTableSpace where_clause
opt_include opt_reloptions OptTableSpace OptSplit where_clause
{
IndexStmt *n = makeNode(IndexStmt);
n->unique = $2;
Expand All @@ -7837,7 +7837,8 @@ IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name
n->indexIncludingParams = $12;
n->options = $13;
n->tableSpace = $14;
n->whereClause = $15;
n->split_options = $15;
n->whereClause = $16;
n->excludeOpNames = NIL;
n->idxcomment = NULL;
n->indexOid = InvalidOid;
Expand All @@ -7852,7 +7853,7 @@ IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name
}
| CREATE opt_unique INDEX opt_concurrently IF_P NOT EXISTS index_name
ON relation_expr access_method_clause '(' yb_index_params ')'
opt_include opt_reloptions OptTableSpace where_clause
opt_include opt_reloptions OptTableSpace OptSplit where_clause
{
IndexStmt *n = makeNode(IndexStmt);
n->unique = $2;
Expand All @@ -7865,7 +7866,8 @@ IndexStmt: CREATE opt_unique INDEX opt_concurrently opt_index_name
n->indexIncludingParams = $15;
n->options = $16;
n->tableSpace = $17;
n->whereClause = $18;
n->split_options = $18;
n->whereClause = $19;
n->excludeOpNames = NIL;
n->idxcomment = NULL;
n->indexOid = InvalidOid;
Expand Down
3 changes: 2 additions & 1 deletion src/postgres/src/include/catalog/index.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ extern Oid index_create(Relation heapRelation,
bits16 constr_flags,
bool allow_system_table_mods,
bool is_internal,
Oid *constraintId);
Oid *constraintId,
OptSplit *split_options);

#define INDEX_CONSTR_CREATE_MARK_AS_PRIMARY (1 << 0)
#define INDEX_CONSTR_CREATE_DEFERRABLE (1 << 1)
Expand Down
3 changes: 2 additions & 1 deletion src/postgres/src/include/commands/ybccmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ extern void YBCCreateIndex(const char *indexName,
int16 *coloptions,
Datum reloptions,
Oid indexId,
Relation rel);
Relation rel,
OptSplit *split_options);

extern void YBCDropIndex(Oid relationId);

Expand Down
1 change: 1 addition & 0 deletions src/postgres/src/include/nodes/execnodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ typedef struct ExprState
* Am Oid of index AM
* AmCache private cache area for index AM
* Context memory context holding this IndexInfo
* SplitOptions Options to split index into tablets.
*
* ii_Concurrent, ii_BrokenHotChain, and ii_ParallelWorkers are used only
* during index build; they're conventionally zeroed otherwise.
Expand Down
2 changes: 2 additions & 0 deletions src/postgres/src/include/nodes/parsenodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -2784,6 +2784,8 @@ typedef struct IndexStmt
bool transformed; /* true when transformIndexStmt is finished */
bool concurrent; /* should this be a concurrent index build? */
bool if_not_exists; /* just do nothing if index already exists? */

OptSplit *split_options; /* SPLIT statement options */
} IndexStmt;

/* ----------------------
Expand Down
30 changes: 30 additions & 0 deletions src/postgres/src/test/regress/expected/yb_create_index.out
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,36 @@ SELECT * FROM test_include ORDER BY c2;
1 | | 1
(2 rows)

-- Test SPLIT INTO
CREATE TABLE test_split (
h1 int, h2 int, r1 int, r2 int, v1 int, v2 int,
PRIMARY KEY ((h1, h2) HASH, r1, r2));
CREATE INDEX ON test_split (h2 HASH, r2, r1) SPLIT INTO 20 TABLETS;
CREATE INDEX ON test_split ((r1,r2) HASH) SPLIT INTO 20 TABLETS;
CREATE INDEX ON test_split (h2) SPLIT INTO 20 TABLETS;
\d test_split
Table "public.test_split"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
h1 | integer | | not null |
h2 | integer | | not null |
r1 | integer | | not null |
r2 | integer | | not null |
v1 | integer | | |
v2 | integer | | |
Indexes:
"test_split_pkey" PRIMARY KEY, lsm ((h1, h2) HASH, r1, r2)
"test_split_h2_idx" lsm (h2 HASH)
"test_split_h2_r2_r1_idx" lsm (h2 HASH, r2, r1)
"test_split_r1_r2_idx" lsm ((r1, r2) HASH)

-- These should fail
CREATE INDEX ON test_split (r1 ASC) SPLIT INTO 20 TABLETS;
ERROR: HASH columns must be present to split by number of tablets
CREATE INDEX ON test_split (h2 ASC, r1) SPLIT INTO 20 TABLETS;
ERROR: HASH columns must be present to split by number of tablets
CREATE INDEX ON test_split (h1 HASH) SPLIT INTO 10000 TABLETS;
ERROR: Invalid argument: num_tablets exceeds system limit
-- Test hash methods
CREATE TABLE test_method (
h1 int, h2 int, r1 int, r2 int, v1 int, v2 int,
Expand Down
14 changes: 14 additions & 0 deletions src/postgres/src/test/regress/sql/yb_create_index.sql
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@ DELETE FROM test_include WHERE c1 = 2;
SELECT c1, c2 FROM test_include WHERE c1 > 0 ORDER BY c2;
SELECT * FROM test_include ORDER BY c2;

-- Test SPLIT INTO
CREATE TABLE test_split (
h1 int, h2 int, r1 int, r2 int, v1 int, v2 int,
PRIMARY KEY ((h1, h2) HASH, r1, r2));
CREATE INDEX ON test_split (h2 HASH, r2, r1) SPLIT INTO 20 TABLETS;
CREATE INDEX ON test_split ((r1,r2) HASH) SPLIT INTO 20 TABLETS;
CREATE INDEX ON test_split (h2) SPLIT INTO 20 TABLETS;
\d test_split

-- These should fail
CREATE INDEX ON test_split (r1 ASC) SPLIT INTO 20 TABLETS;
CREATE INDEX ON test_split (h2 ASC, r1) SPLIT INTO 20 TABLETS;
CREATE INDEX ON test_split (h1 HASH) SPLIT INTO 10000 TABLETS;

-- Test hash methods
CREATE TABLE test_method (
h1 int, h2 int, r1 int, r2 int, v1 int, v2 int,
Expand Down
8 changes: 8 additions & 0 deletions src/yb/yql/pggate/pggate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,14 @@ Status PgApiImpl::CreateIndexAddColumn(PgStatement *handle, const char *attr_nam
is_hash, is_range, is_desc, is_nulls_first);
}

Status PgApiImpl::CreateIndexSetNumTablets(PgStatement *handle, int32_t num_tablets) {
if (!PgStatement::IsValidStmt(handle, StmtOp::STMT_CREATE_INDEX)) {
// Invalid handle.
return STATUS(InvalidArgument, "Invalid statement handle");
}
return down_cast<PgCreateIndex*>(handle)->SetNumTablets(num_tablets);
}

Status PgApiImpl::ExecCreateIndex(PgStatement *handle) {
if (!PgStatement::IsValidStmt(handle, StmtOp::STMT_CREATE_INDEX)) {
// Invalid handle.
Expand Down
2 changes: 2 additions & 0 deletions src/yb/yql/pggate/pggate.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ class PgApiImpl {
const YBCPgTypeEntity *attr_type, bool is_hash,
bool is_range, bool is_desc, bool is_nulls_first);

CHECKED_STATUS CreateIndexSetNumTablets(PgStatement *handle, int32_t num_tablets);

CHECKED_STATUS ExecCreateIndex(PgStatement *handle);

CHECKED_STATUS NewDropIndex(const PgObjectId& index_id,
Expand Down
4 changes: 4 additions & 0 deletions src/yb/yql/pggate/ybc_pggate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,10 @@ YBCStatus YBCPgCreateIndexAddColumn(YBCPgStatement handle, const char *attr_name
is_hash, is_range, is_desc, is_nulls_first));
}

YBCStatus YBCPgCreateIndexSetNumTablets(YBCPgStatement handle, int32_t num_tablets) {
return ToYBCStatus(pgapi->CreateIndexSetNumTablets(handle, num_tablets));
}

YBCStatus YBCPgExecCreateIndex(YBCPgStatement handle) {
return ToYBCStatus(pgapi->ExecCreateIndex(handle));
}
Expand Down
2 changes: 2 additions & 0 deletions src/yb/yql/pggate/ybc_pggate.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ YBCStatus YBCPgCreateIndexAddColumn(YBCPgStatement handle, const char *attr_name
const YBCPgTypeEntity *attr_type, bool is_hash, bool is_range,
bool is_desc, bool is_nulls_first);

YBCStatus YBCPgCreateIndexSetNumTablets(YBCPgStatement handle, int32_t num_tablets);

YBCStatus YBCPgExecCreateIndex(YBCPgStatement handle);

YBCStatus YBCPgNewDropIndex(YBCPgOid database_oid,
Expand Down

0 comments on commit 0909995

Please sign in to comment.