Skip to content

Commit

Permalink
Wrong detection of serial types on columns with multiple constraints (#…
Browse files Browse the repository at this point in the history
…179)

* Updated sql query

* Added test to cover the issue

Co-authored-by: Ivan Vakhrushev <i.vakhrushev@banki.ru>
  • Loading branch information
mfvanek and Ivan Vakhrushev authored Sep 24, 2022
1 parent 808768a commit 92cd4d9
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/main/resources
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,40 @@ void shouldIgnoreDroppedColumns(final String schemaName) {
Column.ofNotNull(ctx.enrichWithSchema("bad_accounts"), "real_client_id"), String.format("%s.bad_accounts_real_client_id_seq", schemaName))
));
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldIgnoreCheckConstraintsOnSerialPrimaryKey(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withCheckConstraintOnSerialPrimaryKey, ctx ->
assertThat(check.check(ctx))
.isEmpty());
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldDetectSerialColumnsWithUniqueConstraints(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withUniqueConstraintOnSerialColumn, ctx ->
assertThat(check.check(ctx))
.hasSize(1)
.containsExactly(
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("one_more_table"), "id"), String.format("%s.one_more_table_id_seq", schemaName))
));
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldDetectPrimaryKeysThatAreForeignKeysAsWell(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withSerialPrimaryKeyReferencesToAnotherTable, ctx ->
assertThat(check.check(ctx))
.hasSize(3)
.containsExactly(
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("one_more_table"), "id"), String.format("%s.one_more_table_id_seq", schemaName)),
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("test_table"), "id"), String.format("%s.test_table_id_seq", schemaName)),
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("test_table"), "num"), String.format("%s.test_table_num_seq", schemaName))
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,43 @@ void shouldIgnoreDroppedColumns(final String schemaName) {
Column.ofNotNull(ctx.enrichWithSchema("bad_accounts"), "real_client_id"), String.format("%s.bad_accounts_real_client_id_seq", schemaName))
));
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldIgnoreCheckConstraintsOnSerialPrimaryKey(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withCheckConstraintOnSerialPrimaryKey, ctx ->
assertThat(check)
.executing(ctx)
.isEmpty());
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldDetectSerialColumnsWithUniqueConstraints(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withUniqueConstraintOnSerialColumn, ctx ->
assertThat(check)
.executing(ctx)
.hasSize(1)
.containsExactly(
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("one_more_table"), "id"), String.format("%s.one_more_table_id_seq", schemaName))
));
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldDetectPrimaryKeysThatAreForeignKeysAsWell(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withSerialPrimaryKeyReferencesToAnotherTable, ctx ->
assertThat(check)
.executing(ctx)
.hasSize(3)
.containsExactly(
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("one_more_table"), "id"), String.format("%s.one_more_table_id_seq", schemaName)),
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("test_table"), "id"), String.format("%s.test_table_id_seq", schemaName)),
ColumnWithSerialType.ofBigSerial(
Column.ofNotNull(ctx.enrichWithSchema("test_table"), "num"), String.format("%s.test_table_num_seq", schemaName))
));
}
}
22 changes: 22 additions & 0 deletions src/test/java/io/github/mfvanek/pg/support/DatabasePopulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
import io.github.mfvanek.pg.support.statements.CreateNotSuitableIndexForForeignKeyStatement;
import io.github.mfvanek.pg.support.statements.CreateSchemaStatement;
import io.github.mfvanek.pg.support.statements.CreateSuitableIndexForForeignKeyStatement;
import io.github.mfvanek.pg.support.statements.CreateTableWithCheckConstraintOnSerialPrimaryKey;
import io.github.mfvanek.pg.support.statements.CreateTableWithColumnOfBigSerialTypeStatement;
import io.github.mfvanek.pg.support.statements.CreateTableWithSerialPrimaryKeyReferencesToAnotherTable;
import io.github.mfvanek.pg.support.statements.CreateTableWithUniqueSerialColumn;
import io.github.mfvanek.pg.support.statements.CreateTableWithoutPrimaryKeyStatement;
import io.github.mfvanek.pg.support.statements.DbStatement;
import io.github.mfvanek.pg.support.statements.DropColumnStatement;
Expand Down Expand Up @@ -197,6 +200,25 @@ public DatabasePopulator withDroppedSerialColumn() {
return this;
}

@Nonnull
public DatabasePopulator withCheckConstraintOnSerialPrimaryKey() {
statementsToExecuteInSameTransaction.putIfAbsent(80, new CreateTableWithCheckConstraintOnSerialPrimaryKey(schemaName));
return this;
}

@Nonnull
public DatabasePopulator withUniqueConstraintOnSerialColumn() {
statementsToExecuteInSameTransaction.putIfAbsent(81, new CreateTableWithUniqueSerialColumn(schemaName));
return this;
}

@Nonnull
public DatabasePopulator withSerialPrimaryKeyReferencesToAnotherTable() {
statementsToExecuteInSameTransaction.putIfAbsent(82, new CreateTableWithSerialPrimaryKeyReferencesToAnotherTable(schemaName));
return withCheckConstraintOnSerialPrimaryKey()
.withUniqueConstraintOnSerialColumn();
}

public void populate() {
TestUtils.executeInTransaction(dataSource, statementsToExecuteInSameTransaction.values());
actionsToExecuteOutsideTransaction.forEach((k, v) -> v.run());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public AddLinksBetweenAccountsAndClientsStatement(@Nonnull final String schemaNa

@Override
public void execute(@Nonnull final Statement statement) throws SQLException {
statement.execute(String.format("alter table if exists %s.accounts " +
"add constraint c_accounts_fk_client_id foreign key (client_id) references %s.clients (id);",
schemaName, schemaName));
statement.execute(String.format("alter table if exists %1$s.accounts " +
"add constraint c_accounts_fk_client_id foreign key (client_id) references %1$s.clients (id);",
schemaName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2019-2022. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.support.statements;

import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Nonnull;

public class CreateTableWithCheckConstraintOnSerialPrimaryKey extends AbstractDbStatement {

public CreateTableWithCheckConstraintOnSerialPrimaryKey(@Nonnull final String schemaName) {
super(schemaName);
}

@Override
public void execute(@Nonnull final Statement statement) throws SQLException {
statement.execute(String.format("create table if not exists %1$s.another_table(" +
"id bigserial primary key, " +
"constraint not_reserved_id check (id > 1000), " +
"constraint less_than_million check (id < 1000000));",
schemaName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright (c) 2019-2022. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.support.statements;

import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Nonnull;

public class CreateTableWithSerialPrimaryKeyReferencesToAnotherTable extends AbstractDbStatement {

public CreateTableWithSerialPrimaryKeyReferencesToAnotherTable(@Nonnull final String schemaName) {
super(schemaName);
}

@Override
public void execute(@Nonnull final Statement statement) throws SQLException {
statement.execute(String.format("create table if not exists %1$s.test_table(" +
"id bigserial, " +
"num bigserial, " +
"constraint test_table_pkey_id primary key (id), " +
"constraint test_table_fkey_other_id foreign key (id) references %1$s.another_table (id), " +
"constraint test_table_fkey_one_more_id foreign key (id) references %1$s.one_more_table (id));",
schemaName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2019-2022. Ivan Vakhrushev and others.
* https://github.com/mfvanek/pg-index-health
*
* This file is a part of "pg-index-health" - a Java library for
* analyzing and maintaining indexes health in PostgreSQL databases.
*
* Licensed under the Apache License 2.0
*/

package io.github.mfvanek.pg.support.statements;

import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Nonnull;

public class CreateTableWithUniqueSerialColumn extends AbstractDbStatement {

public CreateTableWithUniqueSerialColumn(@Nonnull final String schemaName) {
super(schemaName);
}

@Override
public void execute(@Nonnull final Statement statement) throws SQLException {
statement.execute(String.format("create table if not exists %1$s.one_more_table(" +
"id bigserial, " +
"constraint unique_id unique (id), " +
"constraint not_reserved_id check (id > 1000), " +
"constraint less_than_million check (id < 1000000));",
schemaName));
}
}

0 comments on commit 92cd4d9

Please sign in to comment.