Skip to content

Commit

Permalink
Add check for not valid constraints (#383)
Browse files Browse the repository at this point in the history
* Add check for not valid constraints

* fix :: check style

* modify :: request

* fix :: check

* fix :: coverage

* A fix for Constraint code coverage

* Improve tests and update README.md

* ForeignKey now extends Constraint

* Add IndexWithSingleColumnExtractor

---------

Co-authored-by: BLoHny <[email protected]>
  • Loading branch information
mfvanek and BLoHny authored May 2, 2024
1 parent 6771404 commit 95b477a
Show file tree
Hide file tree
Showing 27 changed files with 754 additions and 105 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ For **Java 8** compatible version take a look at release [0.7.0](https://github.
14. Columns of [serial types](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-SERIAL) that are not primary keys ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/non_primary_key_columns_with_serial_types.sql)).
15. Functions without [description](https://www.postgresql.org/docs/current/sql-comment.html) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/functions_without_description.sql)).
16. Indexes [with boolean](https://habr.com/ru/companies/tensor/articles/488104/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/indexes_with_boolean.sql)).
17. B-tree indexes [on array columns](https://habr.com/ru/articles/800121/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/btree_indexes_on_array_columns.sql)).
17. Tables with [not valid constraints](https://habr.com/ru/articles/800121/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/check_not_valid_constraints.sql)).
18. B-tree indexes [on array columns](https://habr.com/ru/articles/800121/) ([sql](https://github.com/mfvanek/pg-index-health-sql/blob/master/sql/btree_indexes_on_array_columns.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 @@ -25,8 +25,17 @@
*/
public enum SerialType {

/**
* Constant for smallserial.
*/
SMALL_SERIAL("smallserial"),
/**
* Constant for serial.
*/
SERIAL("serial"),
/**
* Constant for bigserial.
*/
BIG_SERIAL("bigserial");

private static final Map<String, SerialType> VALUES = new HashMap<>();
Expand Down Expand Up @@ -59,6 +68,12 @@ public String toString() {
'}';
}

/**
* Gets {@code SerialType} from PostgreSQL serial column type.
*
* @param pgColumnType PostgreSQL serial column type; should be non-null.
* @return {@code SerialType}
*/
@Nonnull
public static SerialType valueFrom(@Nonnull final String pgColumnType) {
Objects.requireNonNull(pgColumnType, "pgColumnType cannot be null");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* 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.model.constraint;

import io.github.mfvanek.pg.model.DbObject;
import io.github.mfvanek.pg.model.table.TableNameAware;
import io.github.mfvanek.pg.model.validation.Validators;

import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.concurrent.Immutable;

/**
* A representation of constraint in a database.
*
* @author Blohny
* @see TableNameAware
* @since 0.10.4
*/
@Immutable
public class Constraint implements DbObject, TableNameAware {

private final String tableName;
private final String constraintName;
private final ConstraintType constraintType;

/**
* Constructs a {@code Constraint} object with given {@code ConstraintType}.
*
* @param tableName table name; should be non-blank.
* @param constraintName constraint name; should be non-blank.
* @param constraintType constraint type; should be non-null.
*/
protected Constraint(
@Nonnull final String tableName,
@Nonnull final String constraintName,
@Nonnull final ConstraintType constraintType) {
this.tableName = Validators.tableNameNotBlank(tableName);
this.constraintName = Validators.notBlank(constraintName, "constraintName");
this.constraintType = Objects.requireNonNull(constraintType, "constraintType cannot be null");
}

/**
* {@inheritDoc}
*/
@Nonnull
@Override
public final String getName() {
return getConstraintName();
}

/**
* {@inheritDoc}
*/
@Nonnull
@Override
public String getTableName() {
return tableName;
}

/**
* Gets the name of constraint.
*
* @return the name of constraint
*/
@Nonnull
public String getConstraintName() {
return constraintName;
}

/**
* Gets type of constraint.
*
* @return type of constraint
* @see ConstraintType
*/
@Nonnull
public ConstraintType getConstraintType() {
return constraintType;
}

/**
* {@inheritDoc}
*/
@Override
public final boolean equals(final Object other) {
if (this == other) {
return true;
}

if (!(other instanceof Constraint)) {
return false;
}

final Constraint that = (Constraint) other;
return Objects.equals(tableName, that.tableName) &&
Objects.equals(constraintName, that.constraintName);
}

/**
* {@inheritDoc}
*/
@Override
public final int hashCode() {
return Objects.hash(tableName, constraintName);
}

/**
* An auxiliary utility method for implementing {@code toString()} in child classes.
*
* @return string representation of the internal fields of this class
*/
@Nonnull
final String innerToString() {
return "tableName='" + tableName + '\'' +
", constraintName='" + constraintName + '\'';
}

/**
* {@inheritDoc}
*/
@Override
public String toString() {
return Constraint.class.getSimpleName() + '{' +
innerToString() +
", constraintType=" + constraintType +
'}';
}

/**
* Constructs a {@code Constraint} object with given {@code ConstraintType}.
*
* @param tableName table name; should be non-blank.
* @param constraintName constraint name; should be non-blank.
* @param constraintType constraint type; should be non-null.
* @return {@code Constraint}
*/
@Nonnull
public static Constraint ofType(@Nonnull final String tableName,
@Nonnull final String constraintName,
@Nonnull final ConstraintType constraintType) {
return new Constraint(tableName, constraintName, constraintType);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.model.constraint;

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

/**
* A mapping to PostgreSQL constraint types.
*
* @author Blohny
* @since 0.10.4
* @see <a href="https://www.postgresql.org/docs/current/catalog-pg-constraint.html">pg_constraint</a>
*/
public enum ConstraintType {

/**
* Check constraint.
*/
CHECK("c"),
/**
* Foreign key constraint.
*/
FOREIGN_KEY("f");

private final String pgConType;

ConstraintType(@Nonnull final String pgConType) {
this.pgConType = Objects.requireNonNull(pgConType, "pgConType");
}

/**
* Gets internal PostgreSQL constraint type.
*
* @return pgConType
*/
@Nonnull
public String getPgConType() {
return pgConType;
}

/**
* Gets {@code ConstraintType} from internal PostgreSQL constraint type.
*
* @param pgConType internal PostgreSQL constraint type; should be non-null.
* @return {@code ConstraintType}
*/
@Nonnull
public static ConstraintType valueFrom(@Nonnull final String pgConType) {
Objects.requireNonNull(pgConType, "pgConType cannot be null");
for (final ConstraintType ct : values()) {
if (ct.getPgConType().equals(pgConType)) {
return ct;
}
}
throw new IllegalArgumentException("Unknown pgConType: " + pgConType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

package io.github.mfvanek.pg.model.constraint;

import io.github.mfvanek.pg.model.DbObject;
import io.github.mfvanek.pg.model.column.Column;
import io.github.mfvanek.pg.model.table.TableNameAware;
import io.github.mfvanek.pg.model.validation.Validators;
Expand All @@ -25,53 +24,23 @@
*
* @author Ivan Vakhrushev
* @see TableNameAware
* @see Constraint
*/
@Immutable
public class ForeignKey implements DbObject, TableNameAware {
public class ForeignKey extends Constraint {

private final String tableName;
private final String constraintName;
private final List<Column> columnsInConstraint;

private ForeignKey(@Nonnull final String tableName,
@Nonnull final String constraintName,
@Nonnull final List<Column> columnsInConstraint) {
this.tableName = Validators.tableNameNotBlank(tableName);
this.constraintName = Validators.notBlank(constraintName, "constraintName");
super(tableName, constraintName, ConstraintType.FOREIGN_KEY);
final List<Column> defensiveCopy = List.copyOf(Objects.requireNonNull(columnsInConstraint, "columnsInConstraint cannot be null"));
Validators.validateThatNotEmpty(defensiveCopy);
Validators.validateThatTableIsTheSame(tableName, defensiveCopy);
this.columnsInConstraint = defensiveCopy;
}

/**
* {@inheritDoc}
*/
@Nonnull
@Override
public final String getName() {
return getConstraintName();
}

/**
* {@inheritDoc}
*/
@Override
@Nonnull
public String getTableName() {
return tableName;
}

/**
* Gets the name of foreign key constraint.
*
* @return the name of foreign key
*/
@Nonnull
public String getConstraintName() {
return constraintName;
}

/**
* Gets columns of foreign key constraint.
*
Expand All @@ -83,42 +52,14 @@ public List<Column> getColumnsInConstraint() {
return columnsInConstraint;
}

/**
* {@inheritDoc}
*/
@Override
public final boolean equals(final Object other) {
if (this == other) {
return true;
}

if (!(other instanceof ForeignKey)) {
return false;
}

final ForeignKey that = (ForeignKey) other;
return Objects.equals(tableName, that.tableName) &&
Objects.equals(constraintName, that.constraintName) &&
Objects.equals(columnsInConstraint, that.columnsInConstraint);
}

/**
* {@inheritDoc}
*/
@Override
public final int hashCode() {
return Objects.hash(tableName, constraintName, columnsInConstraint);
}

/**
* {@inheritDoc}
*/
@Nonnull
@Override
public String toString() {
return ForeignKey.class.getSimpleName() + '{' +
"tableName='" + tableName + '\'' +
", constraintName='" + constraintName + '\'' +
innerToString() +
", columnsInConstraint=" + columnsInConstraint +
'}';
}
Expand Down
Loading

0 comments on commit 95b477a

Please sign in to comment.