Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TABLES_NOT_LINKED_TO_OTHERS] Decide how to handle partitioned tables #539

Merged
merged 4 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ All checks can be divided into 2 groups:
| 4 | Unused indexes | **runtime** | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/unused_indexes.sql) |
| 5 | Foreign keys without associated indexes | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_without_index.sql) |
| 6 | Indexes with null values | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_null_values.sql) |
| 7 | Tables with missing indexes | **runtime** | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_missing_indexes.sql) |
| 8 | Tables without primary key | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_primary_key.sql) |
| 7 | Tables with missing indexes | **runtime** | yes | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_with_missing_indexes.sql) |
| 8 | Tables without primary key | static | yes | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_primary_key.sql) |
| 9 | Indexes [bloat](https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/) | **runtime** | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/bloated_indexes.sql) |
| 10 | Tables [bloat](https://www.percona.com/blog/2018/08/06/basic-understanding-bloat-vacuum-postgresql-mvcc/) | **runtime** | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/bloated_tables.sql) |
| 11 | Tables without [description](https://www.postgresql.org/docs/current/sql-comment.html) | static | yes | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_without_description.sql) |
Expand All @@ -71,7 +71,7 @@ All checks can be divided into 2 groups:
| 21 | Duplicated ([completely identical](https://habr.com/ru/articles/803841/)) foreign keys | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/duplicated_foreign_keys.sql) |
| 22 | Intersected ([partially identical](https://habr.com/ru/articles/803841/)) foreign keys | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/intersected_foreign_keys.sql) |
| 23 | Possible object name overflow (identifiers with maximum length) | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/possible_object_name_overflow.sql) |
| 24 | Tables not linked to other tables | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_not_linked_to_others.sql) |
| 24 | Tables not linked to other tables | static | yes | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/tables_not_linked_to_others.sql) |
| 25 | Foreign keys [with unmatched column type](https://habr.com/ru/articles/803841/) | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/foreign_keys_with_unmatched_column_type.sql) |

For raw sql queries see [pg-index-health-sql](https://github.com/mfvanek/pg-index-health-sql) project.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,15 @@ void onDatabaseWithThem(final String schemaName) {
.isEmpty();
});
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldWorkWithPartitionedTables(final String schemaName) {
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withPartitionedTableWithoutComments(), ctx ->
assertThat(check)
.executing(ctx)
.hasSize(1)
.containsExactly(
Table.of(ctx, "custom_entity_reference_with_very_very_very_long_name")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void shouldSatisfyContract() {
@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void onDatabaseWithThem(final String schemaName) {
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withData().withTableWithoutPrimaryKey().withIdentityPrimaryKey(), ctx -> {
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withTableWithoutPrimaryKey().withIdentityPrimaryKey(), ctx -> {
assertThat(check)
.executing(ctx)
.hasSize(1)
Expand All @@ -53,9 +53,33 @@ void onDatabaseWithThem(final String schemaName) {
@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldReturnNothingForMaterializedViews(final String schemaName) {
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withData().withMaterializedView(), ctx ->
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withMaterializedView(), ctx ->
assertThat(check)
.executing(ctx)
.isEmpty());
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldWorkWithPartitionedTablesAndPartitions(final String schemaName) {
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withPartitionedTableWithoutPrimaryKey(), ctx ->
assertThat(check)
.executing(ctx)
.hasSize(2)
.containsExactly(
Table.of(ctx, "custom_entity_reference_with_very_very_very_long_name"),
Table.of(ctx, "custom_entity_reference_with_very_very_very_long_name_1_default")
));
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldWorkWithPartitionedTablesWhenOnlyPartitionsHavePrimaryKeys(final String schemaName) {
executeTestOnDatabase(schemaName, dbp -> dbp.withReferences().withPartitionedTableWithoutPrimaryKey().withPrimaryKeyForDefaultPartition(), ctx ->
assertThat(check)
.executing(ctx)
.hasSize(1)
.containsExactly(
Table.of(ctx, "custom_entity_reference_with_very_very_very_long_name")));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.github.mfvanek.pg.core.fixtures.support.statements.AddIntersectedForeignKeysStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.AddInvalidForeignKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.AddLinksBetweenAccountsAndClientsStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.AddPrimaryKeyForDefaultPartitionStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.ConvertColumnToJsonTypeStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateAccountsTableStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateClientsTableStatement;
Expand All @@ -30,22 +31,23 @@
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateDuplicatedIndexStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateForeignKeyOnNullableColumnStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateFunctionsStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexWithBooleanValues;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexWithNullValues;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexesOnArrayColumn;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexWithBooleanValuesStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexWithNullValuesStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexesOnArrayColumnStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateIndexesWithDifferentOpclassStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateMaterializedViewStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateNotSuitableIndexForForeignKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreatePartitionedTableWithoutComments;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreatePartitionedTableWithoutCommentsStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreatePartitionedTableWithoutPrimaryKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateProceduresStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateSchemaStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateSequenceStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateSuitableIndexForForeignKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithCheckConstraintOnSerialPrimaryKey;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithCheckConstraintOnSerialPrimaryKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithColumnOfBigSerialTypeStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithIdentityPrimaryKey;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithSerialPrimaryKeyReferencesToAnotherTable;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithUniqueSerialColumn;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithIdentityPrimaryKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithSerialPrimaryKeyReferencesToAnotherTableStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithUniqueSerialColumnStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.CreateTableWithoutPrimaryKeyStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.DbStatement;
import io.github.mfvanek.pg.core.fixtures.support.statements.DropColumnStatement;
Expand Down Expand Up @@ -140,13 +142,13 @@ public DatabasePopulator withTableWithoutPrimaryKey() {

@Nonnull
public DatabasePopulator withNullValuesInIndex() {
statementsToExecuteInSameTransaction.putIfAbsent(48, new CreateIndexWithNullValues());
statementsToExecuteInSameTransaction.putIfAbsent(48, new CreateIndexWithNullValuesStatement());
return this;
}

@Nonnull
public DatabasePopulator withBooleanValuesInIndex() {
statementsToExecuteInSameTransaction.putIfAbsent(49, new CreateIndexWithBooleanValues());
statementsToExecuteInSameTransaction.putIfAbsent(49, new CreateIndexWithBooleanValuesStatement());
return this;
}

Expand Down Expand Up @@ -224,19 +226,19 @@ public DatabasePopulator withDroppedSerialColumn() {

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

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

@Nonnull
public DatabasePopulator withSerialPrimaryKeyReferencesToAnotherTable() {
statementsToExecuteInSameTransaction.putIfAbsent(82, new CreateTableWithSerialPrimaryKeyReferencesToAnotherTable());
statementsToExecuteInSameTransaction.putIfAbsent(82, new CreateTableWithSerialPrimaryKeyReferencesToAnotherTableStatement());
return withCheckConstraintOnSerialPrimaryKey()
.withUniqueConstraintOnSerialColumn();
}
Expand Down Expand Up @@ -282,7 +284,7 @@ public DatabasePopulator withNotValidConstraints() {
}

public DatabasePopulator withBtreeIndexesOnArrayColumn() {
statementsToExecuteInSameTransaction.putIfAbsent(96, new CreateIndexesOnArrayColumn());
statementsToExecuteInSameTransaction.putIfAbsent(96, new CreateIndexesOnArrayColumnStatement());
return this;
}

Expand All @@ -294,7 +296,7 @@ public DatabasePopulator withSequenceOverflow() {

@Nonnull
public DatabasePopulator withIdentityPrimaryKey() {
statementsToExecuteInSameTransaction.putIfAbsent(98, new CreateTableWithIdentityPrimaryKey());
statementsToExecuteInSameTransaction.putIfAbsent(98, new CreateTableWithIdentityPrimaryKeyStatement());
return this;
}

Expand All @@ -312,7 +314,19 @@ public DatabasePopulator withIntersectedForeignKeys() {

@Nonnull
public DatabasePopulator withPartitionedTableWithoutComments() {
statementsToExecuteInSameTransaction.putIfAbsent(110, new CreatePartitionedTableWithoutComments());
statementsToExecuteInSameTransaction.putIfAbsent(110, new CreatePartitionedTableWithoutCommentsStatement());
return this;
}

@Nonnull
public DatabasePopulator withPartitionedTableWithoutPrimaryKey() {
statementsToExecuteInSameTransaction.putIfAbsent(111, new CreatePartitionedTableWithoutPrimaryKeyStatement());
return this;
}

@Nonnull
public DatabasePopulator withPrimaryKeyForDefaultPartition() {
statementsToExecuteInSameTransaction.putIfAbsent(112, new AddPrimaryKeyForDefaultPartitionStatement());
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2019-2024. 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.core.fixtures.support.statements;

import java.util.List;
import javax.annotation.Nonnull;

public class AddPrimaryKeyForDefaultPartitionStatement extends AbstractDbStatement {

@Nonnull
@Override
protected List<String> getSqlToExecute() {
return List.of(
"alter table if exists {schemaName}.custom_entity_reference_with_very_very_very_long_name_1_default " +
"add primary key (ref_type, ref_value, creation_date, entity_id);"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateIndexWithBooleanValues extends AbstractDbStatement {
public class CreateIndexWithBooleanValuesStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateIndexWithNullValues extends AbstractDbStatement {
public class CreateIndexWithNullValuesStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateIndexesOnArrayColumn extends AbstractDbStatement {
public class CreateIndexesOnArrayColumnStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreatePartitionedTableWithoutComments extends AbstractDbStatement {
public class CreatePartitionedTableWithoutCommentsStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2019-2024. 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.core.fixtures.support.statements;

import java.util.List;
import javax.annotation.Nonnull;

public class CreatePartitionedTableWithoutPrimaryKeyStatement extends AbstractDbStatement {

@Nonnull
@Override
protected List<String> getSqlToExecute() {
return List.of(
"create table if not exists {schemaName}.custom_entity_reference_with_very_very_very_long_name(" +
"ref_type varchar(32) not null," +
"ref_value varchar(64) not null," +
"creation_date timestamp with time zone not null," +
"entity_id varchar(64) not null" +
") partition by range (creation_date);",
"create table if not exists {schemaName}.custom_entity_reference_with_very_very_very_long_name_1_default " +
"partition of {schemaName}.custom_entity_reference_with_very_very_very_long_name default;"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateTableWithCheckConstraintOnSerialPrimaryKey extends AbstractDbStatement {
public class CreateTableWithCheckConstraintOnSerialPrimaryKeyStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateTableWithIdentityPrimaryKey extends AbstractDbStatement {
public class CreateTableWithIdentityPrimaryKeyStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateTableWithSerialPrimaryKeyReferencesToAnotherTable extends AbstractDbStatement {
public class CreateTableWithSerialPrimaryKeyReferencesToAnotherTableStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import java.util.List;
import javax.annotation.Nonnull;

public class CreateTableWithUniqueSerialColumn extends AbstractDbStatement {
public class CreateTableWithUniqueSerialColumnStatement extends AbstractDbStatement {

@Nonnull
@Override
Expand Down
Loading
Loading