Skip to content

Commit

Permalink
[YSQL] #1175: Cascade truncate indexes
Browse files Browse the repository at this point in the history
Summary:
This revision fixes an issue with the TRUNCATE statement where indexes on a table are not truncated when the table is truncated. For example,

```
# create table test (id int primary key, value int);
CREATE TABLE
# create unique index unique_idx on test (value);
CREATE INDEX
# insert into test values (1, 2);
INSERT 0 1
# truncate test;
TRUNCATE TABLE
# select * from test;
 id | value
----+-------
(0 rows)
# insert into test values(1, 2);
ERROR:  duplicate key value violates unique constraint "unique_idx"
```

The associated indexes are now truncated along with the base table in this revision.

A few miscellaneous code cleanups are also included in this diff.

Test Plan: yb_create_index

Reviewers: neha, mihnea

Reviewed By: mihnea

Subscribers: yql

Differential Revision: https://phabricator.dev.yugabyte.com/D6552
  • Loading branch information
robertpang committed May 2, 2019
1 parent 9cfdfc9 commit b7fa3d9
Show file tree
Hide file tree
Showing 11 changed files with 100 additions and 298 deletions.
22 changes: 22 additions & 0 deletions src/postgres/src/backend/commands/ybccmds.c
Expand Up @@ -253,9 +253,31 @@ YBCTruncateTable(Relation rel) {
YBCPgStatement handle;
Oid relationId = RelationGetRelid(rel);

/* Truncate the base table */
HandleYBStatus(YBCPgNewTruncateTable(ybc_pg_session, MyDatabaseId, relationId, &handle));
HandleYBStmtStatus(YBCPgExecTruncateTable(handle), handle);
HandleYBStatus(YBCPgDeleteStatement(handle));

if (!rel->rd_rel->relhasindex)
return;

/* Truncate the associated secondary indexes */
List *indexlist = RelationGetIndexList(rel);
ListCell *lc;

foreach(lc, indexlist)
{
Oid indexId = lfirst_oid(lc);

if (indexId == rel->rd_pkindex)
continue;

HandleYBStatus(YBCPgNewTruncateTable(ybc_pg_session, MyDatabaseId, indexId, &handle));
HandleYBStmtStatus(YBCPgExecTruncateTable(handle), handle);
HandleYBStatus(YBCPgDeleteStatement(handle));
}

list_free(indexlist);
}

void
Expand Down
7 changes: 4 additions & 3 deletions src/postgres/src/backend/executor/ybcModifyTable.c
Expand Up @@ -265,6 +265,7 @@ static Oid YBCExecuteInsertInternal(Relation rel,
Bitmapset *pkey = GetTablePrimaryKey(rel);
YBCPgStatement insert_stmt = NULL;
bool is_null = false;
bool has_indices = YBCRelHasSecondaryIndices(rel);

/* Generate a new oid for this row if needed */
if (rel->rd_rel->relhasoids)
Expand Down Expand Up @@ -310,7 +311,7 @@ static Oid YBCExecuteInsertInternal(Relation rel,
* If the relation has indexes, request ybctid of the inserted row to update
* the indexes.
*/
if (rel->rd_rel->relhasindex)
if (has_indices)
{
YBCPgTypeAttrs type_attrs = {0};
YBCPgExpr ybc_expr = YBCNewColumnRef(insert_stmt,
Expand All @@ -327,7 +328,7 @@ static Oid YBCExecuteInsertInternal(Relation rel,
* If the relation has indexes, save ybctid to insert the new row into the
* indexes.
*/
if (rel->rd_rel->relhasindex)
if (has_indices)
{
YBCPgSysColumns syscols;
bool has_data = false;
Expand Down Expand Up @@ -568,7 +569,7 @@ void YBCExecuteUpdate(Relation rel, TupleTableSlot *slot, HeapTuple tuple)
/*
* If the relation has indexes, save the ybctid to insert the updated row into the indexes.
*/
if (rel->rd_rel->relhasindex)
if (YBCRelHasSecondaryIndices(rel))
{
tuple->t_ybctid = ybctid;
}
Expand Down
92 changes: 24 additions & 68 deletions src/postgres/src/backend/parser/gram.y
Expand Up @@ -1690,10 +1690,7 @@ NonReservedWord_or_Sconst:
;

VariableResetStmt:
RESET reset_rest
{
$$ = (Node *) $2;
}
RESET reset_rest { $$ = (Node *) $2; }
;

reset_rest:
Expand Down Expand Up @@ -1750,6 +1747,7 @@ FunctionSetResetClause:
| VariableResetStmt { $$ = (VariableSetStmt *) $1; }
;


VariableShowStmt:
SHOW var_name
{
Expand Down Expand Up @@ -2077,14 +2075,8 @@ AlterTableStmt:
;

alter_table_cmds:
alter_table_cmd
{
$$ = list_make1($1);
}
| alter_table_cmds ',' alter_table_cmd
{
$$ = lappend($1, $3);
}
alter_table_cmd { $$ = list_make1($1); }
| alter_table_cmds ',' alter_table_cmd { $$ = lappend($1, $3); }
;

partition_cmd:
Expand Down Expand Up @@ -3458,21 +3450,10 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
* implement LOCAL as meaning the same as our default temp table behavior,
* so we'll probably continue to treat LOCAL as a noise word.
*/

OptTemp:
TEMPORARY
{
$$ = RELPERSISTENCE_TEMP;
}
| TEMP { $$ = RELPERSISTENCE_TEMP; }
| LOCAL TEMPORARY
{
$$ = RELPERSISTENCE_TEMP;
}
| LOCAL TEMP
{
$$ = RELPERSISTENCE_TEMP;
}
OptTemp: TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
| TEMP { $$ = RELPERSISTENCE_TEMP; }
| LOCAL TEMPORARY { $$ = RELPERSISTENCE_TEMP; }
| LOCAL TEMP { $$ = RELPERSISTENCE_TEMP; }
| GLOBAL TEMPORARY
{
ereport(WARNING,
Expand Down Expand Up @@ -4157,19 +4138,9 @@ OptWith:
| /*EMPTY*/ { $$ = NIL; }
;

OnCommitOption:
ON COMMIT DROP
{
$$ = ONCOMMIT_DROP;
}
| ON COMMIT DELETE_P ROWS
{
$$ = ONCOMMIT_DELETE_ROWS;
}
| ON COMMIT PRESERVE ROWS
{
$$ = ONCOMMIT_PRESERVE_ROWS;
}
OnCommitOption: ON COMMIT DROP { $$ = ONCOMMIT_DROP; }
| ON COMMIT DELETE_P ROWS { $$ = ONCOMMIT_DELETE_ROWS; }
| ON COMMIT PRESERVE ROWS { $$ = ONCOMMIT_PRESERVE_ROWS; }
| /*EMPTY*/ { $$ = ONCOMMIT_NOOP; }
;

Expand Down Expand Up @@ -10556,20 +10527,14 @@ opt_transaction: WORK {}

transaction_mode_item:
ISOLATION LEVEL iso_level
{
$$ = makeDefElem("transaction_isolation",
makeStringConst($3, @3), @1);
}
{ $$ = makeDefElem("transaction_isolation",
makeStringConst($3, @3), @1); }
| READ ONLY
{
$$ = makeDefElem("transaction_read_only",
makeIntConst(true, @1), @1);
}
{ $$ = makeDefElem("transaction_read_only",
makeIntConst(true, @1), @1); }
| READ WRITE
{
$$ = makeDefElem("transaction_read_only",
makeIntConst(false, @1), @1);
}
{ $$ = makeDefElem("transaction_read_only",
makeIntConst(false, @1), @1); }
| DEFERRABLE
{
parser_ybc_signal_unsupported(@1, "TRANSACTION DEFERRABLE mode", 1125);
Expand Down Expand Up @@ -10600,6 +10565,7 @@ transaction_mode_list_or_empty:
{ $$ = NIL; }
;


/*****************************************************************************
*
* QUERY:
Expand Down Expand Up @@ -11617,10 +11583,7 @@ opt_conf_expr:
;

returning_clause:
RETURNING target_list
{
$$ = $2;
}
RETURNING target_list { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;

Expand Down Expand Up @@ -11649,12 +11612,12 @@ DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias
;

using_clause:
/*EMPTY*/ { $$ = NIL; }
| USING from_list
USING from_list
{
parser_ybc_signal_unsupported(@1, "USING clause in DELETE", 738);
$$ = $2;
}
| /*EMPTY*/ { $$ = NIL; }
;


Expand Down Expand Up @@ -13196,13 +13159,9 @@ Typename: SimpleTypename opt_array_bounds

opt_array_bounds:
opt_array_bounds '[' ']'
{
$$ = lappend($1, makeInteger(-1));
}
{ $$ = lappend($1, makeInteger(-1)); }
| opt_array_bounds '[' Iconst ']'
{
$$ = lappend($1, makeInteger($3));
}
{ $$ = lappend($1, makeInteger($3)); }
| /*EMPTY*/
{ $$ = NIL; }
;
Expand Down Expand Up @@ -13266,10 +13225,7 @@ GenericType:
}
;

opt_type_modifiers: '(' expr_list ')'
{
$$ = $2;
}
opt_type_modifiers: '(' expr_list ')' { $$ = $2; }
| /* EMPTY */ { $$ = NIL; }
;

Expand Down
30 changes: 30 additions & 0 deletions src/postgres/src/test/regress/expected/yb_create_index.out
Expand Up @@ -417,3 +417,33 @@ SELECT * FROM test_unique;
1 | 1 | 1
2 | 2 | 2
(2 rows)

-- Test cascade-truncate indexes
CREATE TABLE test_truncate (a int PRIMARY KEY, b int);
CREATE UNIQUE INDEX test_truncate_index ON test_truncate (b);
INSERT INTO test_truncate VALUES (1, 2);
INSERT INTO test_truncate VALUES (2, 2);
ERROR: duplicate key value violates unique constraint "test_truncate_index"
EXPLAIN SELECT b FROM test_truncate WHERE b = 2;
QUERY PLAN
-------------------------------------------------------------------------------------------------
Index Only Scan using test_truncate_index on test_truncate (cost=0.00..4.01 rows=1000 width=4)
Index Cond: (b = 2)
(2 rows)

SELECT b FROM test_truncate WHERE b = 2;
b
---
2
(1 row)

TRUNCATE test_truncate;
SELECT b FROM test_truncate WHERE b = 2;
b
---
(0 rows)

INSERT INTO test_truncate VALUES (2, 2);
INSERT INTO test_truncate VALUES (1, 2);
ERROR: duplicate key value violates unique constraint "test_truncate_index"
DROP TABLE test_truncate;
18 changes: 18 additions & 0 deletions src/postgres/src/test/regress/sql/yb_create_index.sql
Expand Up @@ -196,3 +196,21 @@ SELECT v2 FROM test_unique WHERE v2 IN (1, 2);
INSERT INTO test_unique VALUES (1, 1, 1);
INSERT INTO test_unique VALUES (2, 2, 2);
SELECT * FROM test_unique;

-- Test cascade-truncate indexes
CREATE TABLE test_truncate (a int PRIMARY KEY, b int);
CREATE UNIQUE INDEX test_truncate_index ON test_truncate (b);

INSERT INTO test_truncate VALUES (1, 2);
INSERT INTO test_truncate VALUES (2, 2);

EXPLAIN SELECT b FROM test_truncate WHERE b = 2;
SELECT b FROM test_truncate WHERE b = 2;

TRUNCATE test_truncate;
SELECT b FROM test_truncate WHERE b = 2;

INSERT INTO test_truncate VALUES (2, 2);
INSERT INTO test_truncate VALUES (1, 2);

DROP TABLE test_truncate;
42 changes: 0 additions & 42 deletions src/yb/yql/pggate/pg_ddl.cc
Expand Up @@ -75,48 +75,6 @@ Status PgDropDatabase::Exec() {
return pg_session_->DropDatabase(database_name_, if_exist_);
}

//--------------------------------------------------------------------------------------------------
// PgCreateSchema
//--------------------------------------------------------------------------------------------------

PgCreateSchema::PgCreateSchema(PgSession::ScopedRefPtr pg_session,
const char *database_name,
const char *schema_name,
bool if_not_exist)
: PgDdl(pg_session),
database_name_(database_name),
schema_name_(schema_name),
if_not_exist_(if_not_exist) {
}

PgCreateSchema::~PgCreateSchema() {
}

Status PgCreateSchema::Exec() {
LOG(FATAL) << "Create schema (" << database_name_ << "," << schema_name_ << "," << if_not_exist_
<< ") is under development";
return STATUS(NotSupported, "SCHEMA is not yet implemented");
}

PgDropSchema::PgDropSchema(PgSession::ScopedRefPtr pg_session,
const char *database_name,
const char *schema_name,
bool if_exist)
: PgDdl(pg_session),
database_name_(database_name),
schema_name_(schema_name),
if_exist_(if_exist) {
}

PgDropSchema::~PgDropSchema() {
}

Status PgDropSchema::Exec() {
LOG(FATAL) << "Drop schema " << database_name_ << "." << schema_name_ << "," << if_exist_
<< ") is underdevelopment";
return STATUS(NotSupported, "SCHEMA is not yet implemented");
}

//--------------------------------------------------------------------------------------------------
// PgCreateTable
//--------------------------------------------------------------------------------------------------
Expand Down

0 comments on commit b7fa3d9

Please sign in to comment.