Skip to content

Commit

Permalink
[INDEXES_WITH_NULL_VALUES] Enhance support for partitioned tables/ind…
Browse files Browse the repository at this point in the history
…exes (#540)

* Update queries

* [INDEXES_WITH_NULL_VALUES] Enhance support for partitioned tables/indexes

* Fix checkstyle
  • Loading branch information
mfvanek authored Dec 11, 2024
1 parent 0440030 commit 5709af1
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 5 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ All checks can be divided into 2 groups:

|| Description | Type | Supports partitioning | SQL query |
|----|-------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|-----------------------|-------------------------------------------------------------------------------------------------------------------|
| 1 | Invalid (broken) indexes | **runtime**/static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/invalid_indexes.sql) |
| 1 | Invalid (broken) indexes | **runtime**/static | yes | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/invalid_indexes.sql) |
| 1 | Duplicated (completely identical) indexes | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/duplicated_indexes.sql) |
| 3 | Intersected (partially identical) indexes | static | no | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/intersected_indexes.sql) |
| 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) |
| 6 | Indexes with null values | static | yes | [sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_null_values.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) |
Expand Down
2 changes: 1 addition & 1 deletion pg-index-health-core/src/main/resources
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import io.github.mfvanek.pg.core.checks.common.DatabaseCheckOnHost;
import io.github.mfvanek.pg.core.checks.common.Diagnostic;
import io.github.mfvanek.pg.core.fixtures.support.DatabaseAwareTestBase;
import io.github.mfvanek.pg.core.fixtures.support.DatabasePopulator;
import io.github.mfvanek.pg.model.context.PgContext;
import io.github.mfvanek.pg.model.index.IndexWithNulls;
import io.github.mfvanek.pg.model.predicates.SkipIndexesByNamePredicate;
Expand Down Expand Up @@ -43,7 +44,7 @@ void onDatabaseWithThem(final String schemaName) {
assertThat(check)
.executing(ctx)
.hasSize(1)
.containsExactly(IndexWithNulls.of(ctx, "clients", "i_clients_middle_name", 0L, "middle_name"))
.containsExactly(IndexWithNulls.of(ctx, "clients", "i_clients_middle_name", "middle_name"))
.allMatch(i -> i.getNullableColumn().isNullable());

assertThat(check)
Expand All @@ -55,4 +56,17 @@ void onDatabaseWithThem(final String schemaName) {
.isEmpty();
});
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldWorkWithPartitionedTables(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withNullableIndexesInPartitionedTable, ctx ->
assertThat(check)
.executing(ctx)
.hasSize(2)
.containsExactly(
IndexWithNulls.of(ctx, "custom_entity_reference_with_very_very_very_long_name", "idx_custom_entity_reference_with_very_very_very_long_name_1", "ref_type"),
IndexWithNulls.of(ctx, "custom_entity_reference_with_very_very_very_long_name_1_default", "idx_custom_entity_reference_with_very_very_very_long_name_1_d_3", "ref_type"))
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
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.CreatePartitionedTableWithNullableFieldsStatement;
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;
Expand Down Expand Up @@ -330,6 +331,12 @@ public DatabasePopulator withPrimaryKeyForDefaultPartition() {
return this;
}

@Nonnull
public DatabasePopulator withNullableIndexesInPartitionedTable() {
statementsToExecuteInSameTransaction.putIfAbsent(113, new CreatePartitionedTableWithNullableFieldsStatement());
return this;
}

public void populate() {
try (SchemaNameHolder ignored = SchemaNameHolder.with(schemaName)) {
ExecuteUtils.executeInTransaction(dataSource, statementsToExecuteInSameTransaction.values());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 CreatePartitionedTableWithNullableFieldsStatement 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)," +
"ref_value varchar(64)," +
"creation_date timestamp with time zone not null," +
"entity_id varchar(64) not null" +
") partition by range (creation_date);",
"create index if not exists idx_custom_entity_reference_with_very_very_very_long_name_1 " +
"on {schemaName}.custom_entity_reference_with_very_very_very_long_name (ref_type, ref_value);",
"create index if not exists idx_custom_entity_reference_with_very_very_very_long_name_2 " +
"on {schemaName}.custom_entity_reference_with_very_very_very_long_name (entity_id, ref_value);",
"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;",
"create index if not exists idx_custom_entity_reference_with_very_very_very_long_name_1_d_3 " +
"on {schemaName}.custom_entity_reference_with_very_very_very_long_name_1_default (ref_type, ref_value);"
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,22 @@ public static IndexWithNulls of(@Nonnull final PgContext pgContext,
return new IndexWithNulls(PgContext.enrichWith(tableName, pgContext), PgContext.enrichWith(indexName, pgContext),
indexSizeInBytes, Column.ofNullable(pgContext, tableName, nullableColumnName));
}

/**
* Constructs an {@code IndexWithNulls} object with given context.
*
* @param pgContext the schema context to enrich table and index name; must be non-null.
* @param tableName table name; should be non-blank.
* @param indexName index name; should be non-blank.
* @param nullableColumnName nullable column in this index.
* @return {@code IndexWithNulls}
* @since 0.14.3
*/
@Nonnull
public static IndexWithNulls of(@Nonnull final PgContext pgContext,
@Nonnull final String tableName,
@Nonnull final String indexName,
@Nonnull final String nullableColumnName) {
return of(pgContext, tableName, indexName, 0L, nullableColumnName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ void testToString() {
.hasToString("IndexWithNulls{tableName='t', indexName='i', indexSizeInBytes=22, columns=[Column{tableName='t', columnName='f', notNull=false}]}");
assertThat(IndexWithNulls.of(PgContext.of("tst"), "t", "i", 22L, "f"))
.hasToString("IndexWithNulls{tableName='tst.t', indexName='tst.i', indexSizeInBytes=22, columns=[Column{tableName='tst.t', columnName='f', notNull=false}]}");
assertThat(IndexWithNulls.of(PgContext.of("tst"), "t", "i", "f"))
.hasToString("IndexWithNulls{tableName='tst.t', indexName='tst.i', indexSizeInBytes=0, columns=[Column{tableName='tst.t', columnName='f', notNull=false}]}");
}

@SuppressWarnings("ConstantConditions")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import io.github.mfvanek.pg.core.checks.common.Diagnostic;
import io.github.mfvanek.pg.core.fixtures.support.DatabaseAwareTestBase;
import io.github.mfvanek.pg.core.fixtures.support.DatabasePopulator;
import io.github.mfvanek.pg.health.checks.common.DatabaseCheckOnCluster;
import io.github.mfvanek.pg.model.context.PgContext;
import io.github.mfvanek.pg.model.index.IndexWithNulls;
Expand Down Expand Up @@ -51,7 +52,7 @@ void onDatabaseWithThem(final String schemaName) {
assertThat(check)
.executing(ctx)
.hasSize(1)
.containsExactly(IndexWithNulls.of(ctx, "clients", "i_clients_middle_name", 0L, "middle_name"))
.containsExactly(IndexWithNulls.of(ctx, "clients", "i_clients_middle_name", "middle_name"))
.allMatch(i -> i.getNullableColumn().isNullable());

assertThat(check)
Expand All @@ -63,4 +64,17 @@ void onDatabaseWithThem(final String schemaName) {
.isEmpty();
});
}

@ParameterizedTest
@ValueSource(strings = {PgContext.DEFAULT_SCHEMA_NAME, "custom"})
void shouldWorkWithPartitionedTables(final String schemaName) {
executeTestOnDatabase(schemaName, DatabasePopulator::withNullableIndexesInPartitionedTable, ctx ->
assertThat(check)
.executing(ctx)
.hasSize(2)
.containsExactly(
IndexWithNulls.of(ctx, "custom_entity_reference_with_very_very_very_long_name", "idx_custom_entity_reference_with_very_very_very_long_name_1", "ref_type"),
IndexWithNulls.of(ctx, "custom_entity_reference_with_very_very_very_long_name_1_default", "idx_custom_entity_reference_with_very_very_very_long_name_1_d_3", "ref_type"))
);
}
}

0 comments on commit 5709af1

Please sign in to comment.