From c00bc22b7882a22576d2adbc073eced4dd5066d8 Mon Sep 17 00:00:00 2001 From: Jin Kwon Date: Sun, 4 Feb 2024 02:49:08 +0900 Subject: [PATCH] Squash sketch --- .mvn/jvm.config | 1 + .mvn/wrapper/maven-wrapper.properties | 2 +- README.md | 5 + pom.xml | 129 +- .../metadata/bind/AbstractMetadataType.java | 18 +- .../database/metadata/bind/Attribute.java | 134 +- .../metadata/bind/BestRowIdentifier.java | 173 +- .../database/metadata/bind/Catalog.java | 72 +- .../metadata/bind/ClientInfoProperty.java | 80 +- .../database/metadata/bind/Column.java | 189 +-- .../metadata/bind/ColumnPrivilege.java | 122 +- .../database/metadata/bind/Context.java | 742 ++++++--- .../metadata/bind/CrossReference.java | 188 +-- .../database/metadata/bind/ExportedKey.java | 23 +- .../database/metadata/bind/Function.java | 11 +- .../metadata/bind/FunctionColumn.java | 23 +- .../database/metadata/bind/ImportedKey.java | 23 +- .../database/metadata/bind/IndexInfo.java | 179 +- .../database/metadata/bind/PrimaryKey.java | 155 +- .../database/metadata/bind/Procedure.java | 166 +- .../metadata/bind/ProcedureColumn.java | 81 +- .../database/metadata/bind/PseudoColumn.java | 91 +- .../database/metadata/bind/Schema.java | 84 +- .../database/metadata/bind/SuperTable.java | 101 +- .../database/metadata/bind/SuperType.java | 137 +- .../jinahya/database/metadata/bind/Table.java | 149 +- .../database/metadata/bind/TableKey.java | 395 +++-- .../metadata/bind/TableKeyDeferrability.java | 66 - .../metadata/bind/TableKeyDeleteRule.java | 73 - .../metadata/bind/TableKeyUpdateRule.java | 73 - .../metadata/bind/TablePrivilege.java | 59 +- .../database/metadata/bind/TableType.java | 41 +- .../database/metadata/bind/TypeInfo.java | 87 +- .../jinahya/database/metadata/bind/UDT.java | 122 +- .../jinahya/database/metadata/bind/Utils.java | 4 - .../database/metadata/bind/VersionColumn.java | 68 +- .../database/metadata/bind/_NonNull.java} | 21 +- ...Null.java => _NonNullBySpecification.java} | 3 +- .../bind/_NullableBySpecification.java | 2 +- .../metadata/bind/TestContainers_$_IT.java | 6 +- .../bind/TestContainers_MySQL_IT.java | 31 +- .../database/metadata/bind/AttributeTest.java | 4 +- .../metadata/bind/BestRowIdentifierTest.java | 12 +- .../database/metadata/bind/CatalogTest.java | 17 +- .../metadata/bind/ColumnPrivilegeTest.java | 39 - .../database/metadata/bind/ColumnTest.java | 10 +- .../database/metadata/bind/ContextTest.java | 19 +- .../metadata/bind/ContextTestUtils.java | 1436 +++++++++++++++++ .../database/metadata/bind/ContextTests.java | 1397 ---------------- .../database/metadata/bind/ExternalIT.java | 2 +- .../metadata/bind/FunctionColumnTest.java | 10 +- .../database/metadata/bind/FunctionTest.java | 4 +- .../database/metadata/bind/IndexInfoTest.java | 6 +- .../database/metadata/bind/Memory_$_Test.java | 8 +- .../metadata/bind/Memory_Sqlite_Test.java | 73 - .../metadata/bind/MetadataTypeTest.java | 260 +-- .../metadata/bind/MetadataTypeTestUtils.java | 90 ++ .../metadata/bind/PrimaryKeyTest.java | 4 +- .../metadata/bind/ProcedureColumnTest.java | 4 +- .../database/metadata/bind/ProcedureTest.java | 9 +- .../database/metadata/bind/SchemaTest.java | 4 +- .../bind/TableKeyDeferrabilityTest.java | 30 +- .../metadata/bind/TableKeyDeleteRuleTest.java | 30 +- .../database/metadata/bind/TableKeyTest.java | 35 +- .../metadata/bind/TableKeyUpdateRuleTest.java | 30 +- .../database/metadata/bind/TableTest.java | 4 +- .../metadata/bind/ValidationTestUtils.java | 44 + .../metadata/bind/VersionColumnTest.java | 6 +- .../metadata/bind/_MetadataTypeTest.java | 92 -- src/test/resources/logback-test.xml | 1 + 70 files changed, 3813 insertions(+), 3996 deletions(-) create mode 100644 .mvn/jvm.config delete mode 100644 src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrability.java delete mode 100644 src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRule.java delete mode 100644 src/main/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRule.java rename src/{test/java/com/github/jinahya/database/metadata/bind/EmptyTest.java => main/java/com/github/jinahya/database/metadata/bind/_NonNull.java} (63%) rename src/main/java/com/github/jinahya/database/metadata/bind/{_NotNull.java => _NonNullBySpecification.java} (96%) delete mode 100644 src/test/java/com/github/jinahya/database/metadata/bind/ContextTests.java create mode 100644 src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTestUtils.java create mode 100644 src/test/java/com/github/jinahya/database/metadata/bind/ValidationTestUtils.java delete mode 100644 src/test/java/com/github/jinahya/database/metadata/bind/_MetadataTypeTest.java diff --git a/.mvn/jvm.config b/.mvn/jvm.config new file mode 100644 index 00000000..27456518 --- /dev/null +++ b/.mvn/jvm.config @@ -0,0 +1 @@ +-Dnet.bytebuddy.experimental=true diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index fec191f3..4a95a136 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.0/apache-maven-3.9.0-bin.zip +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/README.md b/README.md index 64176ff3..4b212898 100644 --- a/README.md +++ b/README.md @@ -58,3 +58,8 @@ $ mvn -Pfailsafe \ -Dpassword='' clean failsafe:integration-test ``` +---- +## Links + +### MariaDB +* [getTables should be ordered as expected](https://jira.mariadb.org/browse/CONJ-1156) diff --git a/pom.xml b/pom.xml index aa1427db..be76a70f 100644 --- a/pom.xml +++ b/pom.xml @@ -1,11 +1,12 @@ - + 4.0.0 com.github.jinahya jinahya-parent - 0.8.9 + 0.9.2 database-metadata-bind @@ -39,7 +40,8 @@ 1.8 ${maven.compiler.source} - 17 + 8 + 21 ${maven.compiler.testSource} ${maven.compiler.testTarget} none @@ -47,24 +49,37 @@ https://sonarcloud.io 1.23 19.3.0.0 - 1.18.26 + 1.18.30 ${version.maven-surefire} - 3.0.0-M7 - 8.0.32 + 3.2.5 + 8.3.0 11.2.0.4 21.8.0.0 19.17.0.0 21.8.0.0 10.16.1.1 - 5.9.2 - 5.2.0 + 8.0.1.Final + 5.10.1 + 5.10.0 + + + + jakarta.platform + jakarta.jakartaee-bom + 11.0.0-M1 + pom + import + + + + ch.qos.logback logback-classic - 1.4.6 + 1.4.14 test @@ -76,19 +91,19 @@ com.google.guava guava - 31.1-jre + 33.0.0-jre test com.ibm.db2 jcc - 11.5.8.0 + 11.5.9.0 test com.h2database h2 - 2.1.214 + 2.2.224 test @@ -97,16 +112,26 @@ 1.0.0-alpha-4 test + + jakarta.annotation + jakarta.annotation-api + provided + + + jakarta.validation + jakarta.validation-api + provided + nl.jqno.equalsverifier equalsverifier-nodep - 3.14.1 + 3.15.6 test org.apache.commons commons-text - 1.10.0 + 1.11.0 test @@ -130,7 +155,7 @@ org.assertj assertj-core - 3.24.2 + 3.25.2 test @@ -139,10 +164,28 @@ ${version.animal-sniffer} provided + + org.glassfish.expressly + expressly + 5.0.0 + test + + + org.hibernate.validator + hibernate-validator + ${version.org.hibernate.validator} + test + + + org.hibernate.validator + hibernate-validator-test-utils + ${version.org.hibernate.validator} + test + org.hsqldb hsqldb - 2.7.1 + 2.7.2 test @@ -151,12 +194,12 @@ ${version.org.junit.jupiter} test - - org.mockito - mockito-inline - ${version.org.mockito} - test - + + + + + + org.mockito mockito-junit-jupiter @@ -172,7 +215,7 @@ org.xerial sqlite-jdbc - 3.41.2.1 + 3.45.1.0 test @@ -183,7 +226,7 @@ org.apache.maven.plugins maven-javadoc-plugin - 3.4.1 + 3.6.3 -Xdoclint:${doclint} @@ -212,37 +255,37 @@ org.apache.maven.plugins maven-jar-plugin - 3.2.2 + 3.3.0 org.apache.maven.plugins maven-project-info-reports-plugin - 3.4.1 + 3.5.0 org.apache.maven.plugins maven-site-plugin - 4.0.0-M3 + 4.0.0-M13 org.codehaus.mojo build-helper-maven-plugin - 3.3.0 + 3.5.0 org.codehaus.mojo versions-maven-plugin - 2.15.0 + 2.16.2 org.codehaus.mojo sonar-maven-plugin - 3.9.1.2184 + 3.10.0.2594 org.jacoco jacoco-maven-plugin - 0.8.9 + 0.8.11 @@ -250,7 +293,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.11.0 + 3.12.1 @@ -278,13 +321,13 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.3.0 + 3.4.1 enforce-dependency-convergence - + @@ -360,7 +403,7 @@ org.codehaus.mojo license-maven-plugin - 2.0.0 + 2.4.0 apache_v2 @@ -390,6 +433,7 @@ + true false @@ -412,12 +456,12 @@ com.github.spotbugs spotbugs-maven-plugin - 4.7.1.1 + 4.8.3.0 org.apache.maven.plugins maven-jxr-plugin - 3.2.0 + 3.3.2 org.apache.maven.plugins @@ -426,12 +470,12 @@ org.apache.maven.plugins maven-checkstyle-plugin - 3.1.2 + 3.3.1 org.apache.maven.plugins maven-pmd-plugin - 3.17.0 + 3.21.2 org.jacoco @@ -482,7 +526,7 @@ org.testcontainers testcontainers-bom - 1.18.0 + 1.19.4 pom import @@ -514,13 +558,14 @@ org.mariadb.jdbc mariadb-java-client - 3.1.3 + 3.3.2 test org.postgresql postgresql - 42.6.0 + + 42.7.1 test diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/AbstractMetadataType.java b/src/main/java/com/github/jinahya/database/metadata/bind/AbstractMetadataType.java index 2ed2e610..493e5561 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/AbstractMetadataType.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/AbstractMetadataType.java @@ -24,32 +24,31 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.HashMap; import java.util.Map; +import java.util.Objects; +@ToString(callSuper = true) abstract class AbstractMetadataType implements MetadataType { private static final long serialVersionUID = -3285362930174073345L; - @Override - public String toString() { - return super.toString() + '{' + - "unmappedValues=" + unmappedValues + - '}'; - } - + // ----------------------------------------------------------------------------------------------------------------- @Override public boolean equals(final Object obj) { if (this == obj) return true; - return obj instanceof AbstractMetadataType; + if (obj == null || getClass() != obj.getClass()) return false; + return true; } @Override public int hashCode() { - return super.hashCode(); + return Objects.hash(getClass()); } + // -------------------------------------------------------------------------------------------------- unmappedValues @Override public Map getUnmappedValues() { if (unmappedValues == null) { @@ -58,6 +57,7 @@ public Map getUnmappedValues() { return unmappedValues; } + // ----------------------------------------------------------------------------------------------------------------- @Setter(AccessLevel.NONE) @Getter(AccessLevel.NONE) @EqualsAndHashCode.Exclude diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Attribute.java b/src/main/java/com/github/jinahya/database/metadata/bind/Attribute.java index cb7b1265..213c33de 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Attribute.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Attribute.java @@ -20,8 +20,10 @@ * #L% */ +import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; @@ -39,6 +41,7 @@ */ @Setter @Getter +@ToString(callSuper = true) public class Attribute extends AbstractMetadataType { private static final long serialVersionUID = 1913681105410440186L; @@ -55,6 +58,13 @@ public class Attribute extends AbstractMetadataType { .thenComparing(Attribute::getTypeName, nullsFirst(naturalOrder())) .thenComparingInt(Attribute::getOrdinalPosition); + // -------------------------------------------------------------------------------------------------------- TYPE_CAT + public static final String COLUMN_LABEL_TYPE_CAT = "TYPE_CAT"; + + // ------------------------------------------------------------------------------------------------------ TYPE_SCHEM + public static final String COLUMN_LABEL_TYPE_SCHEM = "TYPE_SCHEM"; + + // -------------------------------------------------------------------------------------------------------- NULLABLE public static final String COLUMN_LABEL_NULLABLE = "NULLABLE"; /** @@ -102,39 +112,16 @@ public int fieldValueAsInt() { private final int fieldValue; } + // ----------------------------------------------------------------------------------------------------------------- + public static final String COLUMN_LABEL_IS_NULLABLE = "IS_NULLABLE"; + public static final String COLUMN_VALUE_IS_NULLABLE_YES = "YES"; public static final String COLUMN_VALUE_IS_NULLABLE_NO = "NO"; public static final String COLUMN_VALUE_IS_NULLABLE_EMPTY = ""; - @Override - public String toString() { - return super.toString() + '{' + - "typeCat=" + typeCat + - ",typeSchem=" + typeSchem + - ",typeName=" + typeName + - ",attrName=" + attrName + - ",dataType=" + dataType + - ",attrTypeName=" + attrTypeName + - ",attrSize=" + attrSize + - ",decimalDigits=" + decimalDigits + - ",numPrecRadix=" + numPrecRadix + - ",nullable=" + nullable + - ",remarks=" + remarks + - ",attrDef=" + attrDef + - ",sqlDataType=" + sqlDataType + - ",sqlDatetimeSub=" + sqlDatetimeSub + - ",charOctetLength=" + charOctetLength + - ",ordinalPosition=" + ordinalPosition + - ",isNullable=" + isNullable + - ",scopeCatalog=" + scopeCatalog + - ",scopeSchema=" + scopeSchema + - ",scopeTable=" + scopeTable + - ",sourceDataType=" + sourceDataType + - '}'; - } - + // ----------------------------------------------------------------------------------------------------------------- @Override public boolean equals(final Object obj) { if (this == obj) return true; @@ -156,44 +143,33 @@ public int hashCode() { ); } - public String getTypeCat() { - return typeCat; - } - - public void setTypeCat(final String typeCat) { - this.typeCat = typeCat; - } - - public String getTypeSchem() { - return typeSchem; - } - - public void setTypeSchem(final String typeSchem) { - this.typeSchem = typeSchem; - } - - public String getTypeName() { - return typeName; - } - - public void setTypeName(final String typeName) { - this.typeName = typeName; - } - - public String getAttrName() { - return attrName; + // -------------------------------------------------------------------------------------------------------- tableCat + String typeCatNonNull() { + final String typeCat_ = getTypeCat(); + if (typeCat_ != null) { + return typeCat_; + } + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; } - public void setAttrName(final String attrName) { - this.attrName = attrName; + // ------------------------------------------------------------------------------------------------------ tableSchem + String typeSchemNonNull() { + final String typeSchem_ = getTypeSchem(); + if (typeSchem_ != null) { + return typeSchem_; + } + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; } + // ----------------------------------------------------------------------------------------------------------------- + @jakarta.annotation.Nullable @_NullableBySpecification - @_ColumnLabel("TYPE_CAT") + @_ColumnLabel(COLUMN_LABEL_TYPE_CAT) private String typeCat; + @jakarta.annotation.Nullable @_NullableBySpecification - @_ColumnLabel("TYPE_SCHEM") + @_ColumnLabel(COLUMN_LABEL_TYPE_SCHEM) private String typeSchem; @_ColumnLabel("TYPE_NAME") @@ -202,33 +178,41 @@ public void setAttrName(final String attrName) { @_ColumnLabel("ATTR_NAME") private String attrName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel("DATA_TYPE") private Integer dataType; @_ColumnLabel("ATTR_TYPE_NAME") private String attrTypeName; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("ATTR_SIZE") private Integer attrSize; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("DECIMAL_DIGITS") private Integer decimalDigits; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("NUM_PREC_RADIX") private Integer numPrecRadix; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_NULLABLE) private Integer nullable; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("REMARKS") private String remarks; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("ATTR_DEF") private String attrDef; @@ -241,46 +225,36 @@ public void setAttrName(final String attrName) { @_ColumnLabel("SQL_DATETIME_SUB") private Integer sqlDatetimeSub; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("CHAR_OCTET_LENGTH") private Integer charOctetLength; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("ORDINAL_POSITION") private Integer ordinalPosition; - @_ColumnLabel("IS_NULLABLE") + @_ColumnLabel(COLUMN_LABEL_IS_NULLABLE) private String isNullable; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SCOPE_CATALOG") private String scopeCatalog; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SCOPE_SCHEMA") private String scopeSchema; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SCOPE_TABLE") private String scopeTable; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SOURCE_DATA_TYPE") private Integer sourceDataType; - - String typeCatNonNull() { - final String typeCat_ = getTypeCat(); - if (typeCat_ != null) { - return typeCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String typeSchemNonNull() { - final String typeSchem_ = getTypeSchem(); - if (typeSchem_ != null) { - return typeSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/BestRowIdentifier.java b/src/main/java/com/github/jinahya/database/metadata/bind/BestRowIdentifier.java index 6f96e562..88104d23 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/BestRowIdentifier.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/BestRowIdentifier.java @@ -20,9 +20,16 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; /** @@ -34,17 +41,24 @@ * @see PseudoColumn * @see Scope */ +@Setter +@Getter +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class BestRowIdentifier extends AbstractMetadataType implements Comparable { private static final long serialVersionUID = -1512051574198028399L; + // ----------------------------------------------------------------------------------------------------------------- + /** * A comparator compares objects with their value of {@link #getScope()}. */ static final Comparator COMPARING_SCOPE = Comparator.comparingInt(BestRowIdentifier::getScope); + // ----------------------------------------------------------------------------------------------------------- SCOPE public static final String COLUMN_LABEL_SCOPE = "SCOPE"; /** @@ -93,10 +107,13 @@ public int fieldValueAsInt() { private final int fieldValue; } + // ----------------------------------------------------------------------------------------------------- COLUMN_NAME public static final String COLUMN_LABEL_COLUMN_NAME = "COLUMN_NAME"; + // ------------------------------------------------------------------------------------------------------- DATA_TYPE public static final String COLUMN_LABEL_DATA_TYPE = "DATA_TYPE"; + // --------------------------------------------------------------------------------------------------- PSEUDO_COLUMN public static final String COLUMN_LABEL_PSEUDO_COLUMN = "PSEUDO_COLUMN"; /** @@ -145,34 +162,7 @@ public int fieldValueAsInt() { private final int fieldValue; } - @Override - public String toString() { - return super.toString() + '{' + - "scope=" + scope + - ",columnName=" + columnName + - ",dataType=" + dataType + - ",typeName=" + typeName + - ",columnSize=" + columnSize + - ",bufferLength=" + bufferLength + - ",decimalDigits=" + decimalDigits + - ",pseudoColumn=" + pseudoColumn + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof BestRowIdentifier)) return false; - final BestRowIdentifier that = (BestRowIdentifier) obj; - return Objects.equals(scope, that.scope) && - Objects.equals(columnName, that.columnName); - } - - @Override - public int hashCode() { - return Objects.hash(scope, columnName); - } - + // ----------------------------------------------------------------------------------------------------------------- @Override public int compareTo(final BestRowIdentifier o) { if (o == null) { @@ -181,84 +171,63 @@ public int compareTo(final BestRowIdentifier o) { return COMPARING_SCOPE.compare(this, o); } - public Integer getScope() { - return scope; - } - - public void setScope(final Integer scope) { - this.scope = scope; - } - - public Integer getPseudoColumn() { - return pseudoColumn; - } - - public void setPseudoColumn(final Integer pseudoColumn) { - this.pseudoColumn = pseudoColumn; - } - - public String getColumnName() { - return columnName; - } - - public void setColumnName(final String columnName) { - this.columnName = columnName; - } - - public Integer getDataType() { - return dataType; - } - - public void setDataType(final Integer dataType) { - this.dataType = dataType; - } - - public String getTypeName() { - return typeName; - } - - public void setTypeName(final String typeName) { - this.typeName = typeName; - } - - public Integer getColumnSize() { - return columnSize; - } - - public void setColumnSize(final Integer columnSize) { - this.columnSize = columnSize; + // ----------------------------------------------------------------------------------------------------------- scope + Scope getScopeAsEnum() { + return Optional.ofNullable(getScope()) + .map(Scope::valueOfScope) + .orElse(null); } - public Integer getBufferLength() { - return bufferLength; + void setScopeAsEnum(final Scope scopeAsEnum) { + setScope( + Optional.ofNullable(scopeAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) + ); } - public void setBufferLength(final Integer bufferLength) { - this.bufferLength = bufferLength; + // ---------------------------------------------------------------------------------------------------- pseudoColumn + PseudoColumn getPseudoColumnAsEnum() { + return Optional.ofNullable(getPseudoColumn()) + .map(PseudoColumn::valueOfPseudoColumn) + .orElse(null); } - public Integer getDecimalDigits() { - return decimalDigits; + void setPseudoColumnAsEnum(final PseudoColumn pseudoColumnAsEnum) { + setPseudoColumn( + Optional.ofNullable(pseudoColumnAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) + ); } - public void setDecimalDigits(final Integer decimalDigits) { - this.decimalDigits = decimalDigits; - } + // ----------------------------------------------------------------------------------------------------------------- + @Setter(AccessLevel.PACKAGE) + @EqualsAndHashCode.Include + @ToString.Exclude + private Table parent; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_SCOPE) + @EqualsAndHashCode.Include private Integer scope; @_ColumnLabel(COLUMN_LABEL_COLUMN_NAME) + @EqualsAndHashCode.Include private String columnName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_DATA_TYPE) private Integer dataType; @_ColumnLabel("TYPE_NAME") private String typeName; + @Nullable @_NullableBySpecification @_ColumnLabel("COLUMN_SIZE") private Integer columnSize; @@ -267,39 +236,13 @@ public void setDecimalDigits(final Integer decimalDigits) { @_ColumnLabel("BUFFER_LENGTH") private Integer bufferLength; + @Nullable @_NullableBySpecification @_ColumnLabel("DECIMAL_DIGITS") private Integer decimalDigits; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_PSEUDO_COLUMN) private Integer pseudoColumn; - - Scope getScopeAsEnum() { - return Optional.ofNullable(getScope()) - .map(Scope::valueOfScope) - .orElse(null); - } - - void setScopeAsEnum(final Scope scopeAsEnum) { - setScope( - Optional.ofNullable(scopeAsEnum) - .map(_IntFieldEnum::fieldValueAsInt) - .orElse(null) - ); - } - - PseudoColumn getPseudoColumnAsEnum() { - return Optional.ofNullable(getPseudoColumn()) - .map(PseudoColumn::valueOfPseudoColumn) - .orElse(null); - } - - void setPseudoColumnAsEnum(final PseudoColumn pseudoColumnAsEnum) { - setPseudoColumn( - Optional.ofNullable(pseudoColumnAsEnum) - .map(_IntFieldEnum::fieldValueAsInt) - .orElse(null) - ); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Catalog.java b/src/main/java/com/github/jinahya/database/metadata/bind/Catalog.java index 12090bd6..82d329c3 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Catalog.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Catalog.java @@ -20,8 +20,12 @@ * #L% */ +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.util.Comparator; -import java.util.Objects; import java.util.function.Consumer; import static java.util.Comparator.naturalOrder; @@ -33,6 +37,10 @@ * @author Jin Kwon <jinahya_at_gmail.com> * @see Context#getCatalogs(Consumer) */ +@Setter +@Getter +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class Catalog extends AbstractMetadataType { private static final long serialVersionUID = 6239185259128825953L; @@ -46,17 +54,15 @@ public class Catalog extends AbstractMetadataType { static final Comparator LEXICOGRAPHIC_ORDER = Comparator.comparing(Catalog::getTableCat, nullsFirst(naturalOrder())); - /** - * Returns a new instance whose {@code tableCat} is {@value #COLUMN_VALUE_TABLE_CAT_EMPTY}. - * - * @return a new virtual instance. - */ - public static Catalog newVirtualInstance() { + // ----------------------------------------------------------------------------------------------------------------- + static Catalog of(final String tableCat) { final Catalog instance = new Catalog(); - instance.setTableCat(COLUMN_VALUE_TABLE_CAT_EMPTY); + instance.setTableCat(tableCat); return instance; } + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ @@ -65,44 +71,32 @@ public static Catalog newVirtualInstance() { /** * An empty value for {@value #COLUMN_LABEL_TABLE_CAT} column. */ - public static final String COLUMN_VALUE_TABLE_CAT_EMPTY = ""; - - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - '}'; - } + static final String COLUMN_VALUE_TABLE_CAT_EMPTY = ""; - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof Catalog)) return false; - final Catalog that = (Catalog) obj; - return Objects.equals(tableCatNonNull(), that.tableCatNonNull()); - } + // ----------------------------------------------------------------------------------------------------------------- - @Override - public int hashCode() { - return Objects.hash(tableCatNonNull()); + /** + * Returns a new instance whose {@code tableCat} is {@value #COLUMN_VALUE_TABLE_CAT_EMPTY}. + * + * @return a new virtual instance. + */ + static Catalog newVirtualInstance() { + final Catalog instance = new Catalog(); + instance.setTableCat(COLUMN_VALUE_TABLE_CAT_EMPTY); + return instance; } - public String getTableCat() { + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return tableCat; } - public void setTableCat(final String tableCat) { - this.tableCat = tableCat; - } - + // ----------------------------------------------------------------------------------------------------------------- @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) + @EqualsAndHashCode.Exclude private String tableCat; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ != null) { - return tableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/ClientInfoProperty.java b/src/main/java/com/github/jinahya/database/metadata/bind/ClientInfoProperty.java index f6079829..f0ce7353 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/ClientInfoProperty.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/ClientInfoProperty.java @@ -20,9 +20,14 @@ * #L% */ +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; @@ -32,6 +37,10 @@ * @author Jin Kwon <jinahya_at_gmail.com> * @see Context#getClientInfoProperties() */ +@Setter +@Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class ClientInfoProperty extends AbstractMetadataType { private static final long serialVersionUID = -2913230435651853254L; @@ -42,85 +51,42 @@ public class ClientInfoProperty extends AbstractMetadataType { static final Comparator LEXICOGRAPHIC_ORDER = Comparator.comparing(ClientInfoProperty::getName, naturalOrder()); + // ------------------------------------------------------------------------------------------------------------ NAME + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_NAME = "NAME"; + // --------------------------------------------------------------------------------------------------------- MAX_LEN + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_MAX_LEN = "MAX_LEN"; + // --------------------------------------------------------------------------------------------------- DEFAULT_VALUE + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_DEFAULT_VALUE = "DEFAULT_VALUE"; + // ----------------------------------------------------------------------------------------------------- DESCRIPTION + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_DESCRIPTION = "DESCRIPTION"; - @Override - public String toString() { - return super.toString() + '{' + - "name=" + name + - ",maxLen=" + maxLen + - ",defaultValue=" + defaultValue + - ",description=" + description + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof ClientInfoProperty)) return false; - final ClientInfoProperty that = (ClientInfoProperty) obj; - return Objects.equals(name, that.name); - } - - @Override - public int hashCode() { - return Objects.hash(name); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Integer getMaxLen() { - return maxLen; - } - - public void setMaxLen(final Integer maxLen) { - this.maxLen = maxLen; - } - - public String getDefaultValue() { - return defaultValue; - } - - public void setDefaultValue(final String defaultValue) { - this.defaultValue = defaultValue; - } - - public String getDescription() { - return description; - } - - public void setDescription(final String description) { - this.description = description; - } - + // ----------------------------------------------------------------------------------------------------------------- @_ColumnLabel(COLUMN_LABEL_NAME) + @EqualsAndHashCode.Include private String name; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_MAX_LEN) private Integer maxLen; diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Column.java b/src/main/java/com/github/jinahya/database/metadata/bind/Column.java index 3f2bc425..ff9b3349 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Column.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Column.java @@ -20,12 +20,14 @@ * #L% */ +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; import static java.util.Comparator.naturalOrder; @@ -41,6 +43,8 @@ //@ParentOf(ColumnPrivilege.class) @Setter @Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class Column extends AbstractMetadataType { private static final long serialVersionUID = -409653682729081530L; @@ -57,26 +61,36 @@ public class Column extends AbstractMetadataType { .thenComparing(Column::getTableName, nullsFirst(naturalOrder())) .thenComparingInt(Column::getOrdinalPosition); + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_NAME = "TABLE_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_COLUMN_NAME = "COLUMN_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ @@ -128,132 +142,74 @@ public int fieldValueAsInt() { private final int fieldValue; } + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_IS_AUTOINCREMENT = "IS_AUTOINCREMENT"; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_IS_GENERATEDCOLUMN = "IS_GENERATEDCOLUMN"; - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem=" + tableSchem + - ",tableName=" + tableName + - ",columnName=" + columnName + - ",dataType=" + dataType + - ",typeName=" + typeName + - ",columnSize=" + columnSize + - ",bufferLength=" + bufferLength + - ",decimalDigits=" + decimalDigits + - ",numPrecRadix=" + numPrecRadix + - ",nullable=" + nullable + - ",remarks=" + remarks + - ",columnDef=" + columnDef + - ",sqlDataType=" + sqlDataType + - ",sqlDatetimeSub=" + sqlDatetimeSub + - ",charOctetLength=" + charOctetLength + - ",ordinalPosition=" + ordinalPosition + - ",isNullable=" + isNullable + - ",scopeCatalog=" + scopeCatalog + - ",scopeSchema=" + scopeSchema + - ",scopeTable=" + scopeTable + - ",sourceDataType=" + sourceDataType + - ",isAutoincrement=" + isAutoincrement + - ",isGeneratedcolumn=" + isGeneratedcolumn + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof Column)) return false; - final Column that = (Column) obj; - return Objects.equals(tableCatNonNull(), that.tableCatNonNull()) && - Objects.equals(tableSchemNonNull(), that.tableSchemNonNull()) && - Objects.equals(tableName, that.tableName) && - Objects.equals(columnName, that.columnName); - } - - @Override - public int hashCode() { - return Objects.hash( - tableCatNonNull(), - tableSchemNonNull(), - tableName, - columnName - ); - } - - /** - * Returns current value of {@code tableCat} field. - * - * @return current value of {@code tableCat} field. - */ - public String getTableCat() { + // -------------------------------------------------------------------------------------------------------- tableCat + String tableCatNonNull() { + if (tableCat != null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return tableCat; } - /** - * Replaces current value of {@code tableCat} field with specified value. - * - * @param tableCat new value for {@code tableCat} field. - */ - public void setTableCat(final String tableCat) { - this.tableCat = tableCat; - } - - public String getTableSchem() { + // ------------------------------------------------------------------------------------------------------ tableSchem + String tableSchemNonNull() { + if (tableSchem != null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return tableSchem; } - public void setTableSchem(final String tableSchem) { - this.tableSchem = tableSchem; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(final String tableName) { - this.tableName = tableName; - } - - public String getColumnName() { - return columnName; - } - - public void setColumnName(final String columnName) { - this.columnName = columnName; - } - - public Integer getNullable() { - return nullable; + // -------------------------------------------------------------------------------------------------------- nullable + Nullable getNullableAsEnum() { + return Optional.ofNullable(getNullable()) + .map(Nullable::valueOfNullable) + .orElse(null); } - public void setNullable(final Integer nullable) { - this.nullable = nullable; + void setNullableAsEnum(final Nullable nullableAsEnum) { + setNullable( + Optional.ofNullable(nullableAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) + ); } + // ----------------------------------------------------------------------------------------------------------------- + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) + @EqualsAndHashCode.Exclude private String tableCat; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) + @EqualsAndHashCode.Exclude private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; @_ColumnLabel(COLUMN_LABEL_COLUMN_NAME) + @EqualsAndHashCode.Include private String columnName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel("DATA_TYPE") private Integer dataType; @_ColumnLabel("TYPE_NAME") private String typeName; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("COLUMN_SIZE") private Integer columnSize; @@ -262,23 +218,27 @@ public void setNullable(final Integer nullable) { @_ColumnLabel("BUFFER_LENGTH") private Integer bufferLength; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("DECIMAL_DIGITS") private Integer decimalDigits; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("NUM_PREC_RADIX") private Integer numPrecRadix; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_NULLABLE) private Integer nullable; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("REMARKS") private String remarks; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("COLUMN_DEF") private String columnDef; @@ -292,29 +252,34 @@ public void setNullable(final Integer nullable) { private Integer sqlDatetimeSub; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("CHAR_OCTET_LENGTH") private Integer charOctetLength; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("ORDINAL_POSITION") private Integer ordinalPosition; @_ColumnLabel("IS_NULLABLE") private String isNullable; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SCOPE_CATALOG") private String scopeCatalog; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SCOPE_SCHEMA") private String scopeSchema; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SCOPE_TABLE") private String scopeTable; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("SOURCE_DATA_TYPE") private Integer sourceDataType; @@ -324,34 +289,4 @@ public void setNullable(final Integer nullable) { @_ColumnLabel(COLUMN_LABEL_IS_GENERATEDCOLUMN) private String isGeneratedcolumn; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ != null) { - return tableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - if (tableSchem_ != null) { - return tableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } - - Nullable getNullableAsEnum() { - return Optional.ofNullable(getNullable()) - .map(Nullable::valueOfNullable) - .orElse(null); - } - - void setNullableAsEnum(final Nullable nullableAsEnum) { - setNullable( - Optional.ofNullable(nullableAsEnum) - .map(_IntFieldEnum::fieldValueAsInt) - .orElse(null) - ); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/ColumnPrivilege.java b/src/main/java/com/github/jinahya/database/metadata/bind/ColumnPrivilege.java index 3f54f69d..d76239b4 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/ColumnPrivilege.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/ColumnPrivilege.java @@ -20,9 +20,11 @@ * #L% */ +import jakarta.annotation.Nullable; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; @@ -41,6 +43,7 @@ @Setter @Getter @EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class ColumnPrivilege extends AbstractMetadataType { private static final long serialVersionUID = 4384654744147773380L; @@ -53,83 +56,130 @@ public class ColumnPrivilege extends AbstractMetadataType { Comparator.comparing(ColumnPrivilege::getColumnName, nullsFirst(naturalOrder())) .thenComparing(ColumnPrivilege::getPrivilege, nullsFirst(naturalOrder())); + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_TABLE_NAME = "TABLE_NAME"; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_COLUMN_NAME = "COLUMN_NAME"; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_IS_GRANTABLE = "IS_GRANTABLE"; public static final String COLUMN_VALUE_IS_GRANTABLE_YES = "YES"; public static final String COLUMN_VALUE_IS_GRANTABLE_NO = "NO"; - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem=" + tableSchem + - ",tableName=" + tableName + - ",columnName=" + columnName + - ",grantor=" + grantor + - ",grantee=" + grantee + - ",privilege=" + privilege + - ",isGrantable=" + isGrantable + - '}'; + public enum IsGrantable implements _FieldEnum { + + /** + * A value for {@link #COLUMN_VALUE_IS_GRANTABLE_YES}. + */ + YES(COLUMN_VALUE_IS_GRANTABLE_YES), + + /** + * A value for {@link #COLUMN_VALUE_IS_GRANTABLE_NO}. + */ + NO(COLUMN_VALUE_IS_GRANTABLE_NO); + + public static IsGrantable valueOfFieldValue(final String fieldValue) { + return _FieldEnum.valueOfFieldValue(IsGrantable.class, fieldValue); + } + + IsGrantable(final String fieldValue) { + this.fieldValue = fieldValue; + } + + @Override + public String fieldValue() { + return fieldValue; + } + + private final String fieldValue; + } + + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return tableCat; + } + + // ------------------------------------------------------------------------------------------------------ tableSchem + @EqualsAndHashCode.Include + String tableSchemNonNull() { + if (tableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } + return tableSchem; + } + + // ------------------------------------------------------------------------------------------------------- tableName + + // ------------------------------------------------------------------------------------------------------ columnName + + // ----------------------------------------------------------------------------------------------------- isGrantable + + @Nullable + IsGrantable getIsGrantableAsEnum() { + return Optional.ofNullable(getIsGrantable()) + .map(IsGrantable::valueOfFieldValue) + .orElse(null); } + void setIsGrantableAsEnum(@Nullable final IsGrantable isGrantableAsEnum) { + setIsGrantable( + Optional.ofNullable(isGrantableAsEnum) + .map(_FieldEnum::fieldValue) + .orElse(null) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) + @EqualsAndHashCode.Exclude private String tableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) + @EqualsAndHashCode.Exclude private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; @_ColumnLabel(COLUMN_LABEL_COLUMN_NAME) + @EqualsAndHashCode.Include private String columnName; + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("GRANTOR") + @EqualsAndHashCode.Include private String grantor; @_ColumnLabel("GRANTEE") + @EqualsAndHashCode.Include private String grantee; @_ColumnLabel("PRIVILEGE") + @EqualsAndHashCode.Include private String privilege; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_IS_GRANTABLE) private String isGrantable; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - return tableCat_ != null ? tableCat_ : Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - return tableSchem_ != null ? tableSchem_ : Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } - - Boolean getIsGrantableAsBoolean() { - return Optional.ofNullable(getIsGrantable()) - .map(COLUMN_VALUE_IS_GRANTABLE_YES::equalsIgnoreCase) - .orElse(null); - } - - void setIsGrantableAsBoolean(final Boolean isGrantableAsBoolean) { - setIsGrantable( - Optional.ofNullable(isGrantableAsBoolean) - .map(v -> Boolean.TRUE.equals(v) ? COLUMN_VALUE_IS_GRANTABLE_YES : COLUMN_VALUE_IS_GRANTABLE_NO) - .orElse(null) - ); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Context.java b/src/main/java/com/github/jinahya/database/metadata/bind/Context.java index bfa5ec77..36eeb147 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Context.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Context.java @@ -129,8 +129,8 @@ private T bind(final ResultSet results, final Class "java:S1874", // isAccessible "java:S3011" // setAccessible }) - private void bind(final ResultSet results, final Class type, - final Consumer consumer) + private void acceptBound(final ResultSet results, final Class type, + final Consumer consumer) throws SQLException { Objects.requireNonNull(results, "results is null"); Objects.requireNonNull(type, "type is null"); @@ -193,20 +193,7 @@ private > C bind( return collection; } - /** - * Invokes - * {@link DatabaseMetaData#getAttributes(java.lang.String, java.lang.String, java.lang.String, java.lang.String) - * getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern)} method with given arguments, and - * accepts each bound value to specified consumer. - * - * @param catalog a value for {@code catalog} parameter. - * @param schemaPattern a value for {@code schemaPattern} parameter. - * @param typeNamePattern a value for {@code typeNamePattern} parameter. - * @param attributeNamePattern a value for {@code attributeNamePattern} parameter. - * @param consumer the consumer to which bound values are accepted. - * @throws SQLException if a database error occurs. - * @see DatabaseMetaData#getAttributes(String, String, String, String) - */ + // ------------------------------------- getAttributes(catalog, schemaPatter, typeNamePattern, attributeNamePattern) void getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern, final Consumer consumer) throws SQLException { @@ -214,10 +201,25 @@ void getAttributes(final String catalog, final String schemaPattern, final Strin try (ResultSet results = databaseMetaData.getAttributes( catalog, schemaPattern, typeNamePattern, attributeNamePattern)) { assert results != null; - bind(results, Attribute.class, consumer); + acceptBound(results, Attribute.class, consumer); } } + > T getAttributesAndAddEach( + final String catalog, final String schemaPattern, final String typeNamePattern, + final String attributeNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + getAttributes( + catalog, + schemaPattern, + typeNamePattern, + attributeNamePattern, + collection::add + ); + return collection; + } + /** * Invokes * {@link DatabaseMetaData#getAttributes(java.lang.String, java.lang.String, java.lang.String, java.lang.String)} @@ -233,9 +235,13 @@ void getAttributes(final String catalog, final String schemaPattern, final Strin public List getAttributes(final String catalog, final String schemaPattern, final String typeNamePattern, final String attributeNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern, list::add); - return list; + return getAttributesAndAddEach( + catalog, + schemaPattern, + typeNamePattern, + attributeNamePattern, + new ArrayList<>() + ); } List getAttributes(final UDT udt, final String attributeNamePattern) throws SQLException { @@ -243,36 +249,35 @@ List getAttributes(final UDT udt, final String attributeNamePattern) return getAttributes( udt.typeCatNonNull(), udt.typeSchemNonNull(), - Objects.requireNonNull(udt.getTypeName(), "udt.typeName is null"), + udt.getTypeName(), attributeNamePattern ); } - /** - * Invokes - * {@link DatabaseMetaData#getBestRowIdentifier(java.lang.String, java.lang.String, java.lang.String, int, boolean)} - * method with given arguments, and accepts each bound value to specified consumer. - * - * @param catalog a value for {@code catalog} parameter. - * @param schema a value for {@code schema} parameter. - * @param table a value for {@code table} parameter. - * @param scope a value for {@code scope} parameter. - * @param nullable a value for {@code nullable} parameter. - * @param consumer the consumer to which bound values are accepted. - * @throws SQLException if a database error occurs. - * @see DatabaseMetaData#getBestRowIdentifier(String, String, String, int, boolean) - */ - - void getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, - final boolean nullable, final Consumer consumer) + // ----------------------------------------------------------------------------------------------------------------- + void acceptBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, + final boolean nullable, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); + final Table parent = Table.of(catalog, schema, table); try (ResultSet results = databaseMetaData.getBestRowIdentifier(catalog, schema, table, scope, nullable)) { assert results != null; - bind(results, BestRowIdentifier.class, consumer); + acceptBound(results, BestRowIdentifier.class, v -> { + v.setParent(parent); + consumer.accept(v); + }); } } + > T addBestRowIdentifier( + final String catalog, final String schema, final String table, final int scope, final boolean nullable, + final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptBestRowIdentifier(catalog, schema, table, scope, nullable, collection::add); + return collection; + } + /** * Invokes * {@link DatabaseMetaData#getBestRowIdentifier(java.lang.String, java.lang.String, java.lang.String, int, boolean)} @@ -285,42 +290,41 @@ void getBestRowIdentifier(final String catalog, final String schema, final Strin * @param nullable a value for {@code nullable} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getBestRowIdentifier(String, String, String, int, boolean) */ public List getBestRowIdentifier(final String catalog, final String schema, final String table, final int scope, final boolean nullable) throws SQLException { - final List list = new ArrayList<>(); - getBestRowIdentifier(catalog, schema, table, scope, nullable, list::add); - return list; + return addBestRowIdentifier(catalog, schema, table, scope, nullable, new ArrayList<>()); } List getBestRowIdentifier(final Table table, final int scope, final boolean nullable) throws SQLException { Objects.requireNonNull(table, "table is null"); return getBestRowIdentifier( - table.tableCatNonNull(), - table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null"), + table.getTableCat(), + table.getTableSchem(), + table.getTableName(), scope, nullable ); } - /** - * Invokes {@link DatabaseMetaData#getCatalogs()} method, and accepts each bound value to specified consumer. - * - * @param consumer the consumer to which each bound value is accepted. - * @throws SQLException if a database error occurs. - * @see DatabaseMetaData#getCatalogs() - */ + // --------------------------------------------------------------------------------------------------- getCatalogs() void getCatalogs(final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getCatalogs()) { assert results != null; - bind(results, Catalog.class, consumer); + acceptBound(results, Catalog.class, consumer); } } + > T getCatalogsAndAddEachTo(final T collection) throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + getCatalogs(collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getCatalogs()} method, and returns a list of bound values. * @@ -328,11 +332,11 @@ void getCatalogs(final Consumer consumer) throws SQLException { * @throws SQLException if a database error occurs. */ public List getCatalogs() throws SQLException { - final List list = new ArrayList<>(); - getCatalogs(list::add); - return list; + return getCatalogsAndAddEachTo(new ArrayList<>()); } + // --------------------------------------------------------------------------------------- getClientInfoProperties() + /** * Invokes {@link DatabaseMetaData#getClientInfoProperties()} method, and accepts each bound value to specified * consumer. @@ -345,7 +349,7 @@ void getClientInfoProperties(final Consumer consumer Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getClientInfoProperties()) { assert results != null; - bind(results, ClientInfoProperty.class, consumer); + acceptBound(results, ClientInfoProperty.class, consumer); } } @@ -361,29 +365,32 @@ public List getClientInfoProperties() throws SQLException { return list; } - /** - * Invokes - * {@link DatabaseMetaData#getColumnPrivileges(java.lang.String, java.lang.String, java.lang.String, - * java.lang.String)} method with given arguments, and accepts each bound value to specified consumer. - * - * @param catalog a value for {@code catalog} parameter. - * @param schema a value for {@code schema} parameter. - * @param table a value for {@code table} parameter. - * @param columnNamePattern a value for {@code columnNamePattern} parameter. - * @param consumer the consumer to which bound values are accepted. - * @throws SQLException if a database error occurs. - * @see DatabaseMetaData#getColumnPrivileges(String, String, String, String) - */ - void getColumnPrivileges(final String catalog, final String schema, final String table, - final String columnNamePattern, final Consumer consumer) + // -------------------------------------------------- getColumnPrivileges(catalog, schema, table, columnNamePattern) + void acceptColumnPrivileges(final String catalog, final String schema, final String table, + final String columnNamePattern, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getColumnPrivileges(catalog, schema, table, columnNamePattern)) { assert results != null; - bind(results, ColumnPrivilege.class, consumer); + acceptBound(results, ColumnPrivilege.class, consumer); } } + > T addColumnPrivileges( + final String catalog, final String schema, final String table, final String columnNamePattern, + final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptColumnPrivileges( + catalog, + schema, + table, + columnNamePattern, + collection::add + ); + return collection; + } + /** * Invokes * {@link DatabaseMetaData#getColumnPrivileges(java.lang.String, java.lang.String, java.lang.String, @@ -399,22 +406,22 @@ void getColumnPrivileges(final String catalog, final String schema, final String public List getColumnPrivileges(final String catalog, final String schema, final String table, final String columnNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getColumnPrivileges(catalog, schema, table, columnNamePattern, list::add); - return list; + return addColumnPrivileges(catalog, schema, table, columnNamePattern, new ArrayList<>()); } List getColumnPrivileges(final Table table, final String columnNamePattern) throws SQLException { Objects.requireNonNull(table, "table is null"); return getColumnPrivileges( - table.tableCatNonNull(), - table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null"), + table.getTableCat(), + table.getTableSchem(), + table.getTableName(), columnNamePattern ); } + // ----------------------------------------- getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern) + /** * Invokes * {@link DatabaseMetaData#getColumns(String, String, String, String) getColumns(catalog, schemaPattern, * @@ -429,14 +436,14 @@ List getColumnPrivileges(final Table table, final String column * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getColumns(String, String, String, String) */ - void getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, - final String columnNamePattern, final Consumer consumer) + void acceptColumns(final String catalog, final String schemaPattern, final String tableNamePattern, + final String columnNamePattern, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); - try (ResultSet results = databaseMetaData.getColumns(catalog, schemaPattern, tableNamePattern, - columnNamePattern)) { + try (ResultSet results = databaseMetaData.getColumns( + catalog, schemaPattern, tableNamePattern, columnNamePattern)) { assert results != null; - bind(results, Column.class, consumer); + acceptBound(results, Column.class, consumer); } } @@ -453,14 +460,14 @@ void getColumns(final String catalog, final String schemaPattern, final String t * @param collection the collection to which bound values are added. * @return given {@code collection}. * @throws SQLException if a database error occurs. - * @see #getColumns(String, String, String, String, Consumer) + * @see #acceptColumns(String, String, String, String, Consumer) */ - > C getColumns(final String catalog, final String schemaPattern, + > T addColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern, - final C collection) + final T collection) throws SQLException { - getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, - (Consumer) collection::add); + Objects.requireNonNull(collection, "collection is null"); + acceptColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, collection::add); return collection; } @@ -479,13 +486,13 @@ > C getColumns(final String catalog, final public List getColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { - return getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, new ArrayList<>()); + return addColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, new ArrayList<>()); } /** - * Invokes - * {@link DatabaseMetaData#getColumns(String, String, String, String) getColumns(catalog, schemaPattern, * - * tableNamePattern, columnNamePattern)} method with given table's properties, and returns a list of bound values. + * Invokes {@link #getColumns(String, String, String, String)} method with specified table's + * {@link Table#getTableCat() tableCat}, {@link Table#getTableSchem() tableSchem}, + * {@link Table#getTableName() tableName}, and specified column name pattern. * * @param table the table. * @param columnNamePattern a value for {@code columnNamePattern} parameter. @@ -496,13 +503,15 @@ public List getColumns(final String catalog, final String schemaPattern, List getColumns(final Table table, final String columnNamePattern) throws SQLException { Objects.requireNonNull(table, "table is null"); return getColumns( - table.tableCatNonNull(), - table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null"), + table.getTableCat(), + table.getTableSchem(), + table.getTableName(), columnNamePattern ); } + // -------- getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable) + /** * Invokes * {@link DatabaseMetaData#getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String, @@ -513,23 +522,37 @@ List getColumns(final Table table, final String columnNamePattern) throw * @param parentSchema a value for {@code parentSchema} parameter * @param parentTable a value for {@code parentTable} parameter * @param foreignCatalog a value for {@code foreignCatalog} parameter - * @param foreignSchema av value for {@code foreignSchema} parameter + * @param foreignSchema a value for {@code foreignSchema} parameter * @param foreignTable a value for {@code foreignTable} parameter * @param consumer the consumer to which bound values are accepted. * @throws SQLException if a database error occurs. */ - void getCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, - final String foreignCatalog, final String foreignSchema, final String foreignTable, - final Consumer consumer) + void acceptCrossReference(final String parentCatalog, final String parentSchema, final String parentTable, + final String foreignCatalog, final String foreignSchema, final String foreignTable, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getCrossReference( parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable)) { assert results != null; - bind(results, CrossReference.class, consumer); + acceptBound(results, CrossReference.class, consumer); } } + > T addCrossReference( + final String parentCatalog, final String parentSchema, final String parentTable, + final String foreignCatalog, final String foreignSchema, final String foreignTable, + final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptCrossReference( + parentCatalog, parentSchema, parentTable, + foreignCatalog, foreignSchema, foreignTable, + collection::add + ); + return collection; + } + /** * Invokes * {@link DatabaseMetaData#getCrossReference(java.lang.String, java.lang.String, java.lang.String, java.lang.String, @@ -539,7 +562,7 @@ void getCrossReference(final String parentCatalog, final String parentSchema, fi * @param parentSchema a value for {@code parentSchema} parameter * @param parentTable a value for {@code parentTable} parameter * @param foreignCatalog a value for {@code foreignCatalog} parameter - * @param foreignSchema av value for {@code foreignSchema} parameter + * @param foreignSchema a value for {@code foreignSchema} parameter * @param foreignTable a value for {@code foreignTable} parameter * @return a list of bound values. * @throws SQLException if a database error occurs. @@ -548,12 +571,25 @@ public List getCrossReference(final String parentCatalog, final final String parentTable, final String foreignCatalog, final String foreignSchema, final String foreignTable) throws SQLException { - final List list = new ArrayList<>(); - getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable, - list::add); - return list; + return addCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable, + new ArrayList<>()); + } + + List getCrossReference(final Table parentTable, final Table foreighTable) throws SQLException { + Objects.requireNonNull(parentTable, "parentTable is null"); + Objects.requireNonNull(foreighTable, "foreignTable is null"); + return getCrossReference( + parentTable.tableCatNonNull(), + parentTable.tableSchemNonNull(), + parentTable.getTableName(), + foreighTable.tableCatNonNull(), + foreighTable.tableSchemNonNull(), + foreighTable.getTableName() + ); } + // ------------------------------------------------------------------------- getExportedKeys(catalog, schema, table) + /** * Invokes {@link DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String)} method * with given arguments, and accepts each bound value to specified consumer. @@ -565,19 +601,28 @@ public List getCrossReference(final String parentCatalog, final * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getExportedKeys(String, String, String) */ - void getExportedKeys(final String catalog, final String schema, final String table, - final Consumer consumer) + void acceptExportedKeys(final String catalog, final String schema, final String table, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getExportedKeys(catalog, schema, table)) { assert results != null; - bind(results, ExportedKey.class, consumer); + acceptBound(results, ExportedKey.class, consumer); } } + > T addExportedKeys(final String catalog, final String schema, + final String table, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptExportedKeys(catalog, schema, table, collection::add); + return collection; + } + /** - * Invokes {@link DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String)} method - * with given arguments, and returns a list of bound values. + * Invokes + * {@link DatabaseMetaData#getExportedKeys(java.lang.String, java.lang.String, java.lang.String) + * getExportedKeys(catalog, schema, table)} method with given arguments, and returns a list of bound values. * * @param catalog a value for {@code catalog} parameter. * @param schema a value for {@code schema} parameter. @@ -587,9 +632,7 @@ void getExportedKeys(final String catalog, final String schema, final String tab */ public List getExportedKeys(final String catalog, final String schema, final String table) throws SQLException { - final List list = new ArrayList<>(); - getExportedKeys(catalog, schema, table, list::add); - return list; + return addExportedKeys(catalog, schema, table, new ArrayList<>()); } /** @@ -605,10 +648,12 @@ List getExportedKeys(final Table table) throws SQLException { return getExportedKeys( table.tableCatNonNull(), table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null") + table.getTableName() ); } + // ------------------------------------------------------- getFunctions(catalog, schemaPattern, functionNamePattern) + /** * Invokes {@link DatabaseMetaData#getFunctions(String, String, String)} method with given arguments, and accepts * each bound value to specified consumer. @@ -620,34 +665,44 @@ List getExportedKeys(final Table table) throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getFunctions(String, String, String) */ - void getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern, - final Consumer consumer) + void acceptFunctions(final String catalog, final String schemaPattern, final String functionNamePattern, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getFunctions(catalog, schemaPattern, functionNamePattern)) { assert results != null; - bind(results, Function.class, consumer); + acceptBound(results, Function.class, consumer); } } + > T addFunctions(final String catalog, final String schemaPattern, + final String functionNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptFunctions(catalog, schemaPattern, functionNamePattern, collection::add); + return collection; + } + /** - * Invokes {@link DatabaseMetaData#getFunctions(String, String, String)} method with given arguments, and returns a - * list of bound values. + * Invokes + * {@link DatabaseMetaData#getFunctions(String, String, String) getFunctions(catalog, schemaPattern, + * functionNamePattern)} method with given arguments, and returns a list of bound values. * * @param catalog a value for {@code catalog} parameter. * @param schemaPattern a value for {@code schemaPattern} parameter. * @param functionNamePattern a value for {@code functionNamePattern} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getFunctions(String, String, String) */ public List getFunctions(final String catalog, final String schemaPattern, final String functionNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getFunctions(catalog, schemaPattern, functionNamePattern, list::add); - return list; + return addFunctions(catalog, schemaPattern, functionNamePattern, new ArrayList<>()); } + // ------------------------------ getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern) + /** * Invokes {@link DatabaseMetaData#getFunctionColumns(String, String, String, String)} method with specified * arguments, and accepts each bound value to specified consumer. @@ -660,20 +715,31 @@ public List getFunctions(final String catalog, final String schemaPatt * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getFunctionColumns(String, String, String, String) */ - void getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, - final String columnNamePattern, final Consumer consumer) + void acceptFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, + final String columnNamePattern, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getFunctionColumns( catalog, schemaPattern, functionNamePattern, columnNamePattern)) { assert results != null; - bind(results, FunctionColumn.class, consumer); + acceptBound(results, FunctionColumn.class, consumer); } } + > T addFunctionColumns( + final String catalog, final String schemaPattern, final String functionNamePattern, + final String columnNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern, collection::add); + return collection; + } + /** - * Invokes {@link DatabaseMetaData#getFunctionColumns(String, String, String, String)} method with specified - * arguments, and returns a list of bound values. + * Invokes + * {@link DatabaseMetaData#getFunctionColumns(String, String, String, String) getFunctionColumns(catalog, + * schemaPattern, functionNamePattern, columnNamePattern)} method with specified arguments, and returns a list of + * bound values. * * @param catalog a value for {@code catalog} parameter. * @param schemaPattern a value for {@code schemaPattern} parameter. @@ -681,13 +747,12 @@ void getFunctionColumns(final String catalog, final String schemaPattern, final * @param columnNamePattern a value for {@code columnNamePattern} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getFunctionColumns(String, String, String, String) */ public List getFunctionColumns(final String catalog, final String schemaPattern, final String functionNamePattern, final String columnNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern, list::add); - return list; + return addFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern, new ArrayList<>()); } /** @@ -706,11 +771,13 @@ List getFunctionColumns(final Function function, final String co return getFunctionColumns( function.functionCatNonNull(), function.functionSchemNonNull(), - Objects.requireNonNull(function.getFunctionName(), "function.functionName is null"), + function.getFunctionName(), columnNamePattern ); } + // ------------------------------------------------------------------------- getImportedKeys(catalog, schema, table) + /** * Invokes {@link DatabaseMetaData#getImportedKeys(String, String, String)} method with given arguments, and accepts * each bound value to specified consumer. @@ -722,16 +789,24 @@ List getFunctionColumns(final Function function, final String co * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getImportedKeys(String, String, String) */ - void getImportedKeys(final String catalog, final String schema, final String table, - final Consumer consumer) + void acceptImportedKeys(final String catalog, final String schema, final String table, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getImportedKeys(catalog, schema, table)) { assert results != null; - bind(results, ImportedKey.class, consumer); + acceptBound(results, ImportedKey.class, consumer); } } + > T addImportedKeys(final String catalog, final String schema, + final String table, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptImportedKeys(catalog, schema, table, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getImportedKeys(String, String, String)} method with given arguments, and returns * a list of bound values. @@ -741,12 +816,11 @@ void getImportedKeys(final String catalog, final String schema, final String tab * @param table a value for {@code table} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getImportedKeys(String, String, String) */ public List getImportedKeys(final String catalog, final String schema, final String table) throws SQLException { - final List list = new ArrayList<>(); - getImportedKeys(catalog, schema, table, list::add); - return list; + return addImportedKeys(catalog, schema, table, new ArrayList<>()); } /** @@ -762,10 +836,12 @@ List getImportedKeys(final Table table) throws SQLException { return getImportedKeys( table.tableCatNonNull(), table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null") + table.getTableName() ); } + // ------------------------------------------------------- getIndexInfo(catalog, schema, table, unique, approximate) + /** * Invokes {@link DatabaseMetaData#getIndexInfo(String, String, String, boolean, boolean)} method with specified * arguments, and accepts bound value to specified consumer. @@ -779,16 +855,25 @@ List getImportedKeys(final Table table) throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getIndexInfo(String, String, String, boolean, boolean) */ - void getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, - final boolean approximate, final Consumer consumer) + void acceptIndexInfo(final String catalog, final String schema, final String table, final boolean unique, + final boolean approximate, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getIndexInfo(catalog, schema, table, unique, approximate)) { assert results != null; - bind(results, IndexInfo.class, consumer); + acceptBound(results, IndexInfo.class, consumer); } } + > T addIndexInfo(final String catalog, final String schema, + final String table, final boolean unique, + final boolean approximate, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptIndexInfo(catalog, schema, table, unique, approximate, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getIndexInfo(String, String, String, boolean, boolean)} method with specified * arguments, and returns a list of bound values. @@ -800,30 +885,31 @@ void getIndexInfo(final String catalog, final String schema, final String table, * @param approximate a value for {@code approximate} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getIndexInfo(String, String, String, boolean, boolean) */ public List getIndexInfo(final String catalog, final String schema, final String table, final boolean unique, final boolean approximate) throws SQLException { - final List list = new ArrayList<>(); - getIndexInfo(catalog, schema, table, unique, approximate, list::add); - return list; + return addIndexInfo(catalog, schema, table, unique, approximate, new ArrayList<>()); } List getIndexInfo(final Table table, final boolean unique, final boolean approximate) throws SQLException { Objects.requireNonNull(table, "table is null"); return getIndexInfo( - table.tableCatNonNull(), - table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null"), + table.getTableCat(), + table.getTableSchem(), + table.getTableName(), unique, approximate ); } + // -------------------------------------------------------------------------- getPrimaryKeys(catalog, schema, table) + /** - * Invokes {@link DatabaseMetaData#getPrimaryKeys(String, String, String)} method with given arguments, and accepts - * each bound value to specified consumer. + * Invokes {@link DatabaseMetaData#getPrimaryKeys(String, String, String) getPrimaryKeys(catalog, schema, table)} + * method with given arguments, and accepts each bound value to specified consumer. * * @param catalog a value for {@code catalog} parameter. * @param schema a value for {@code schema} parameter. @@ -832,16 +918,24 @@ List getIndexInfo(final Table table, final boolean unique, final bool * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getPrimaryKeys(String, String, String) */ - void getPrimaryKeys(final String catalog, final String schema, final String table, - final Consumer consumer) + void acceptPrimaryKeys(final String catalog, final String schema, final String table, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getPrimaryKeys(catalog, schema, table)) { assert results != null; - bind(results, PrimaryKey.class, consumer); + acceptBound(results, PrimaryKey.class, consumer); } } + > T addPrimaryKeys(final String catalog, final String schema, + final String table, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptPrimaryKeys(catalog, schema, table, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getPrimaryKeys(String, String, String)} method with given arguments, and returns * a list of bound values. @@ -854,9 +948,7 @@ void getPrimaryKeys(final String catalog, final String schema, final String tabl */ public List getPrimaryKeys(final String catalog, final String schema, final String table) throws SQLException { - final List list = new ArrayList<>(); - getPrimaryKeys(catalog, schema, table, list::add); - return list; + return addPrimaryKeys(catalog, schema, table, new ArrayList<>()); } List getPrimaryKeys(final Table table) throws SQLException { @@ -864,10 +956,12 @@ List getPrimaryKeys(final Table table) throws SQLException { return getPrimaryKeys( table.tableCatNonNull(), table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null") + table.getTableName() ); } + // ---------------------------- getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern) + /** * Invokes {@link DatabaseMetaData#getProcedureColumns(String, String, String, String)} method with given arguments * , and accepts each value to specified consumer. @@ -880,17 +974,26 @@ List getPrimaryKeys(final Table table) throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getProcedureColumns(String, String, String, String) */ - void getProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, - final String columnNamePattern, final Consumer consumer) + void acceptProcedureColumns(final String catalog, final String schemaPattern, final String procedureNamePattern, + final String columnNamePattern, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getProcedureColumns( catalog, schemaPattern, procedureNamePattern, columnNamePattern)) { assert results != null; - bind(results, ProcedureColumn.class, consumer); + acceptBound(results, ProcedureColumn.class, consumer); } } + > T addProcedureColumns( + final String catalog, final String schemaPattern, final String procedureNamePattern, + final String columnNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getProcedureColumns(String, String, String, String)} method with given arguments * , and returns a list of bound values. @@ -906,23 +1009,22 @@ public List getProcedureColumns(final String catalog, final Str final String procedureNamePattern, final String columnNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern, list::add); - return list; + return addProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern, new ArrayList<>()); } List getProcedureColumns(final Procedure procedure, final String columnNamePattern) throws SQLException { Objects.requireNonNull(procedure, "procedure is null"); - Objects.requireNonNull(columnNamePattern, "columnNamePattern is null"); return getProcedureColumns( - procedure.procedureCatNonNull(), - procedure.procedureSchemNonNull(), + procedure.getProcedureCat(), + procedure.getProcedureSchem(), procedure.getProcedureName(), columnNamePattern ); } + // ----------------------------------------------------- getProcedures(catalog, schemaPattern, procedureNamePattern) + /** * Invokes {@link DatabaseMetaData#getProcedures(java.lang.String, java.lang.String, java.lang.String)} method with * given arguments, and accepts each bounds value to specified consumer. @@ -934,34 +1036,57 @@ List getProcedureColumns(final Procedure procedure, final Strin * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getProcedures(String, String, String) */ - void getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern, - final Consumer consumer) + void acceptProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getProcedures(catalog, schemaPattern, procedureNamePattern)) { assert results != null; - bind(results, Procedure.class, consumer); + acceptBound(results, Procedure.class, consumer); } } + > T addProcedures(final String catalog, final String schemaPattern, + final String procedureNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptProcedures(catalog, schemaPattern, procedureNamePattern, collection::add); + return collection; + } + /** - * Invokes {@link DatabaseMetaData#getProcedures(java.lang.String, java.lang.String, java.lang.String)} method with - * given arguments, and returns a lsit of bound values. + * Invokes + * {@link DatabaseMetaData#getProcedures(java.lang.String, java.lang.String, java.lang.String) + * getProcedures(catalog, schemaPattern, procedureNamePattern)} method with given arguments, and returns a list of + * bound values. * * @param catalog a value for {@code catalog} parameter. * @param schemaPattern a value for {@code schemaPattern} parameter. * @param procedureNamePattern a value for {@code procedureNamePattern} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getProcedures(String, String, String) */ public List getProcedures(final String catalog, final String schemaPattern, final String procedureNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getProcedures(catalog, schemaPattern, procedureNamePattern, list::add); - return list; + return addProcedures(catalog, schemaPattern, procedureNamePattern, new ArrayList<>()); + } + + List getProcedures(final Catalog catalog, final String procedureNamePattern) + throws SQLException { + Objects.requireNonNull(catalog, "catalog is null"); + return getProcedures(catalog.tableCatNonNull(), null, procedureNamePattern); + } + + List getProcedures(final Schema schema, final String procedureNamePattern) + throws SQLException { + Objects.requireNonNull(schema, "schema is null"); + return getProcedures(schema.tableCatalogNonNull(), schema.tableCatalogNonNull(), procedureNamePattern); } + // ----------------------------- getPseudoColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern) + /** * Invokes * {@link DatabaseMetaData#getPseudoColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)} @@ -975,17 +1100,26 @@ public List getProcedures(final String catalog, final String schemaPa * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getPseudoColumns(String, String, String, String) */ - void getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, - final String columnNamePattern, final Consumer consumer) + void acceptPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, + final String columnNamePattern, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getPseudoColumns( catalog, schemaPattern, tableNamePattern, columnNamePattern)) { assert results != null; - bind(results, PseudoColumn.class, consumer); + acceptBound(results, PseudoColumn.class, consumer); } } + > T addPseudoColumns(final String catalog, final String schemaPattern, + final String tableNamePattern, + final String columnNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, collection::add); + return collection; + } + /** * Invokes * {@link DatabaseMetaData#getPseudoColumns(java.lang.String, java.lang.String, java.lang.String, java.lang.String)} @@ -997,13 +1131,12 @@ void getPseudoColumns(final String catalog, final String schemaPattern, final St * @param columnNamePattern a value for {@code columnNamePattern} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getPseudoColumns(String, String, String, String) */ public List getPseudoColumns(final String catalog, final String schemaPattern, final String tableNamePattern, final String columnNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, list::add); - return list; + return addPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern, new ArrayList<>()); } List getPseudoColumns(final Table table, final String columnNamePattern) @@ -1012,11 +1145,13 @@ List getPseudoColumns(final Table table, final String columnNamePa return getPseudoColumns( table.tableCatNonNull(), table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null"), + table.getTableName(), columnNamePattern ); } + // ---------------------------------------------------------------------------------------------------- getSchemas() + /** * Invokes {@link DatabaseMetaData#getSchemas()} method, and accepts each bound value to specified consumer. * @@ -1024,14 +1159,26 @@ List getPseudoColumns(final Table table, final String columnNamePa * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getSchemas() */ - void getSchemas(final Consumer consumer) throws SQLException { + void acceptSchemas(final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getSchemas()) { assert results != null; - bind(results, Schema.class, consumer); + acceptBound(results, Schema.class, consumer); } } + /** + * Invokes {@link DatabaseMetaData#getSchemas()} method, and add each bound value to specified collection. + * + * @return given {@code collection}. + * @throws SQLException if a database error occurs. + */ + > T addSchemas(final T collection) throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptSchemas(collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getSchemas()} method, and returns a list of bound values. * @@ -1039,11 +1186,11 @@ void getSchemas(final Consumer consumer) throws SQLException { * @throws SQLException if a database error occurs. */ public List getSchemas() throws SQLException { - final List list = new ArrayList<>(); - getSchemas(list::add); - return list; + return addSchemas(new ArrayList<>()); } + // ------------------------------------------------------------------------------ getSchemas(catalog, schemaPattern) + /** * Invokes {@link DatabaseMetaData#getSchemas(String, String)} method with given arguments, and accepts each bound * value to specified consumer. @@ -1054,15 +1201,23 @@ public List getSchemas() throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getSchemas(String, String) */ - void getSchemas(final String catalog, final String schemaPattern, final Consumer consumer) + void acceptSchemas(final String catalog, final String schemaPattern, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getSchemas(catalog, schemaPattern)) { assert results != null; - bind(results, Schema.class, consumer); + acceptBound(results, Schema.class, consumer); } } + > T addSchemas(final String catalog, final String schemaPattern, + final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptSchemas(catalog, schemaPattern, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getSchemas(String, String)} method with given arguments, and returns a list of * bound values. @@ -1073,19 +1228,19 @@ void getSchemas(final String catalog, final String schemaPattern, final Consumer * @throws SQLException if a database error occurs. */ public List getSchemas(final String catalog, final String schemaPattern) throws SQLException { - final List list = new ArrayList<>(); - getSchemas(catalog, schemaPattern, list::add); - return list; + return addSchemas(catalog, schemaPattern, new ArrayList<>()); } List getSchemas(final Catalog catalog, final String schemaPattern) throws SQLException { Objects.requireNonNull(catalog, "catalog is null"); return getSchemas( - Objects.requireNonNull(catalog.getTableCat(), "catalog.tableCat is null"), + catalog.tableCatNonNull(), schemaPattern ); } + // -------------------------------------------------------- getSuperTables(catalog, schemaPattern, tableNamePattern) + /** * Invokes {@link DatabaseMetaData#getSuperTables(String, String, String)} method with given arguments, and accepts * each bounds value to specified consumer. @@ -1097,16 +1252,25 @@ List getSchemas(final Catalog catalog, final String schemaPattern) throw * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getSuperTables(String, String, String) */ - void getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern, - final Consumer consumer) + void acceptSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getSuperTables(catalog, schemaPattern, tableNamePattern)) { assert results != null; - bind(results, SuperTable.class, consumer); + acceptBound(results, SuperTable.class, consumer); } } + > T addSuperTables(final String catalog, final String schemaPattern, + final String tableNamePattern, + final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptSuperTables(catalog, schemaPattern, tableNamePattern, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getSuperTables(String, String, String)} method with given arguments and adds * bounds values to specified collection. @@ -1120,20 +1284,28 @@ void getSuperTables(final String catalog, final String schemaPattern, final Stri public List getSuperTables(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getSuperTables(catalog, schemaPattern, tableNamePattern, list::add); - return list; + return addSuperTables(catalog, schemaPattern, tableNamePattern, new ArrayList<>()); } List getSuperTables(final Schema schema, final String tableNamePattern) throws SQLException { Objects.requireNonNull(schema, "schema is null"); return getSuperTables( schema.tableCatalogNonNull(), - Objects.requireNonNull(schema.getTableSchem(), "schema.tableSchem is null"), + schema.getTableSchem(), tableNamePattern ); } + List getSuperTables(final Table table) throws SQLException { + Objects.requireNonNull(table, "table is null"); + return getSuperTables( + Schema.of(table.getTableCat(), table.getTableSchem()), + table.getTableName() + ); + } + + // ----------------------------------------------------------- getSuperType(catalog, schemaPattern, typeNamePattern) + /** * Invokes {@link DatabaseMetaData#getSuperTypes(String, String, String)} method with given arguments, and accepts * each bound value to specified consumer. @@ -1145,42 +1317,61 @@ List getSuperTables(final Schema schema, final String tableNamePatte * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getSuperTypes(String, String, String) */ - void getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern, - final Consumer consumer) + void acceptSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getSuperTypes(catalog, schemaPattern, typeNamePattern)) { assert results != null; - bind(results, SuperType.class, consumer); + acceptBound(results, SuperType.class, consumer); } } + > T addSuperTypes(final String catalog, final String schemaPattern, + final String typeNamePattern, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptSuperTypes(catalog, schemaPattern, typeNamePattern, collection::add); + return collection; + } + /** - * Invokes {@link DatabaseMetaData#getSuperTypes(String, String, String)} method with given arguments, and returns a - * list of bound values. + * Invokes + * {@link DatabaseMetaData#getSuperTypes(String, String, String) getSuperTypes(catalog, schemaPattern, + * typeNamePattern)} method with given arguments, and returns a list of bound values. * * @param catalog a value for {@code catalog} parameter. * @param schemaPattern a value for {@code schemaPattern} parameter. * @param typeNamePattern a value for {@code typeNamePattern} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getSuperTypes(String, String, String) */ public List getSuperTypes(final String catalog, final String schemaPattern, final String typeNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getSuperTypes(catalog, schemaPattern, typeNamePattern, list::add); - return list; + return addSuperTypes(catalog, schemaPattern, typeNamePattern, new ArrayList<>()); } List getSuperTypes(final Schema schema, final String typeNamePattern) throws SQLException { Objects.requireNonNull(schema, "schema is null"); return getSuperTypes( schema.tableCatalogNonNull(), - Objects.requireNonNull(schema.getTableSchem(), "schema.tableSchem is null"), + schema.getTableSchem(), typeNamePattern ); } + List getSuperTypes(final UDT udt) throws SQLException { + Objects.requireNonNull(udt, "udt is null"); + return getSuperTypes( + udt.typeCatNonNull(), + udt.typeSchemNonNull(), + udt.getTypeName() + ); + } + + // ---------------------------------------------------- getTablePrivileges(catalog, schemaPattern, tableNamePattern) + /** * Invokes {@link DatabaseMetaData#getTablePrivileges(java.lang.String, java.lang.String, java.lang.String)} method * with given arguments, and accepts each bound value to specified consumer. @@ -1192,39 +1383,50 @@ List getSuperTypes(final Schema schema, final String typeNamePattern) * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getTablePrivileges(String, String, String) */ - void getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern, - final Consumer consumer) + void acceptTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern)) { assert results != null; - bind(results, TablePrivilege.class, consumer); + acceptBound(results, TablePrivilege.class, consumer); } } + > T addTablePrivileges(final String catalog, + final String schemaPattern, + final String tableNamePattern, + final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptTablePrivileges(catalog, schemaPattern, tableNamePattern, collection::add); + return collection; + } + /** - * Invokes {@link DatabaseMetaData#getTablePrivileges(java.lang.String, java.lang.String, java.lang.String)} method - * with given arguments, and returns a list of bound values. + * Invokes + * {@link DatabaseMetaData#getTablePrivileges(java.lang.String, java.lang.String, java.lang.String) + * getTablePrivileges(catalog, schemaPattern, tableNamePattern)} method with given arguments, and returns a list of + * bound values. * * @param catalog a value for {@code catalog} parameter. * @param schemaPattern a value for {@code schemaPattern} parameter. * @param tableNamePattern a value for {@code tableNamePattern} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getTablePrivileges(String, String, String) */ public List getTablePrivileges(final String catalog, final String schemaPattern, final String tableNamePattern) throws SQLException { - final List list = new ArrayList<>(); - getTablePrivileges(catalog, schemaPattern, tableNamePattern, list::add); - return list; + return addTablePrivileges(catalog, schemaPattern, tableNamePattern, new ArrayList<>()); } List getTablePrivileges(final Schema schema, final String tableNamePattern) throws SQLException { Objects.requireNonNull(schema, "schema is null"); return getTablePrivileges( schema.tableCatalogNonNull(), - Objects.requireNonNull(schema.getTableSchem(), "schema.tableSchem is null"), + schema.getTableSchem(), tableNamePattern ); } @@ -1234,10 +1436,12 @@ List getTablePrivileges(final Table table) throws SQLException { return getTablePrivileges( table.tableCatNonNull(), table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null") + table.getTableName() ); } + // ------------------------------------------------------------------------------------------------- getTableTypes() + /** * Invokes {@link DatabaseMetaData#getTableTypes()} method, and accepts each bound value to specified consumer. * @@ -1245,14 +1449,20 @@ List getTablePrivileges(final Table table) throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getTableTypes() */ - void getTableTypes(final Consumer consumer) throws SQLException { + void acceptTableTypes(final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getTableTypes()) { assert results != null; - bind(results, TableType.class, consumer); + acceptBound(results, TableType.class, consumer); } } + > T addTableTypes(final T collection) throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptTableTypes(collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getTableTypes()} method, and returns a list of bound values. * @@ -1260,11 +1470,11 @@ void getTableTypes(final Consumer consumer) throws SQLExcepti * @throws SQLException if a database error occurs. */ public List getTableTypes() throws SQLException { - final List list = new ArrayList<>(); - getTableTypes(list::add); - return list; + return addTableTypes(new ArrayList<>()); } + // ------------------------------------------------------ getTables(catalog, schemaPattern, tableNamePattern, types) + /** * Invokes * {@link DatabaseMetaData#getTables(java.lang.String, java.lang.String, java.lang.String, java.lang.String[]) @@ -1279,13 +1489,13 @@ public List getTableTypes() throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getTables(String, String, String, String[]) */ - void getTables(final String catalog, final String schemaPattern, final String tableNamePattern, - final String[] types, final Consumer consumer) + void acceptTables(final String catalog, final String schemaPattern, final String tableNamePattern, + final String[] types, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getTables(catalog, schemaPattern, tableNamePattern, types)) { assert results != null; - bind(results, Table.class, consumer); + acceptBound(results, Table.class, consumer); } } @@ -1302,15 +1512,14 @@ void getTables(final String catalog, final String schemaPattern, final String ta * @param collection the collection to which bound values are added. * @return given {@code collection}. * @throws SQLException if a database error occurs. - * @see #getTables(String, String, String, String[], Consumer) + * @see #acceptTables(String, String, String, String[], Consumer) */ - - public > C getTables(final String catalog, final String schemaPattern, - final String tableNamePattern, final String[] types, - final C collection) + > T addTables(final String catalog, final String schemaPattern, + final String tableNamePattern, final String[] types, + final T collection) throws SQLException { Objects.requireNonNull(collection, "collection is null"); - getTables(catalog, schemaPattern, tableNamePattern, types, (Consumer) collection::add); + acceptTables(catalog, schemaPattern, tableNamePattern, types, collection::add); return collection; } @@ -1326,11 +1535,12 @@ public > C getTables(final String catalog, f * @param types a value for {@code types} parameter. * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getTables(String, String, String, String[]) */ public List getTables(final String catalog, final String schemaPattern, final String tableNamePattern, final String[] types) throws SQLException { - return getTables(catalog, schemaPattern, tableNamePattern, types, new ArrayList<>()); + return addTables(catalog, schemaPattern, tableNamePattern, types, new ArrayList<>()); } List
getTables(final Schema schema, final String tableNamePattern, final String[] types) @@ -1338,12 +1548,14 @@ List
getTables(final Schema schema, final String tableNamePattern, final Objects.requireNonNull(schema, "schema is null"); return getTables( schema.tableCatalogNonNull(), - Objects.requireNonNull(schema.getTableSchem(), "schema.tableSchem is null"), + schema.getTableSchem(), tableNamePattern, types ); } + // --------------------------------------------------------------------------------------------------- getTypeInfo() + /** * Invokes {@link DatabaseMetaData#getTypeInfo()} method, and accepts each bound value to specified consumer. * @@ -1351,14 +1563,20 @@ List
getTables(final Schema schema, final String tableNamePattern, final * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getTypeInfo() */ - void getTypeInfo(final Consumer consumer) throws SQLException { + void acceptTypeInfo(final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getTypeInfo()) { assert results != null; - bind(results, TypeInfo.class, consumer); + acceptBound(results, TypeInfo.class, consumer); } } + > T addTypeInfo(final T collection) throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptTypeInfo(collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getTypeInfo()} method, and returns a list of bound values. * @@ -1366,11 +1584,11 @@ void getTypeInfo(final Consumer consumer) throws SQLException * @throws SQLException if a database error occurs. */ public List getTypeInfo() throws SQLException { - final List list = new ArrayList<>(); - getTypeInfo(list::add); - return list; + return addTypeInfo(new ArrayList<>()); } + // --------------------------------------------------------- getUDTs(catalog, schemaPattern, typeNamePattern, types) + /** * Invokes {@link DatabaseMetaData#getUDTs(java.lang.String, java.lang.String, java.lang.String, int[])} method with * given arguments, and accepts each bound value to specified consumer. @@ -1383,16 +1601,24 @@ public List getTypeInfo() throws SQLException { * @throws SQLException if a database error occurs. * @see DatabaseMetaData#getUDTs(String, String, String, int[]) */ - void getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, - final int[] types, final Consumer consumer) + void acceptUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, + final int[] types, final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getUDTs(catalog, schemaPattern, typeNamePattern, types)) { assert results != null; - bind(results, UDT.class, consumer); + acceptBound(results, UDT.class, consumer); } } + > T addUDTs(final String catalog, final String schemaPattern, + final String typeNamePattern, final int[] types, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptUDTs(catalog, schemaPattern, typeNamePattern, types, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getUDTs(java.lang.String, java.lang.String, java.lang.String, int[])} method with * given arguments, and returns a list of bound values. @@ -1403,16 +1629,16 @@ void getUDTs(final String catalog, final String schemaPattern, final String type * @param types a value for {@code type} parameter * @return a list of bound values. * @throws SQLException if a database error occurs. + * @see DatabaseMetaData#getUDTs(String, String, String, int[]) */ - public List getUDTs(final String catalog, final String schemaPattern, final String typeNamePattern, final int[] types) throws SQLException { - final List list = new ArrayList<>(); - getUDTs(catalog, schemaPattern, typeNamePattern, types, list::add); - return list; + return addUDTs(catalog, schemaPattern, typeNamePattern, types, new ArrayList<>()); } + // ----------------------------------------------------------------------- getVersionColumns(catalog, schema, table) + /** * Invokes {@link DatabaseMetaData#getVersionColumns(java.lang.String, java.lang.String, java.lang.String)} method * with given arguments, and accepts each bound value to specified consumer. @@ -1424,16 +1650,24 @@ public List getUDTs(final String catalog, final String schemaPattern, final * @throws SQLException if a database access error occurs. * @see DatabaseMetaData#getVersionColumns(String, String, String) */ - void getVersionColumns(final String catalog, final String schema, final String table, - final Consumer consumer) + void acceptVersionColumns(final String catalog, final String schema, final String table, + final Consumer consumer) throws SQLException { Objects.requireNonNull(consumer, "consumer is null"); try (ResultSet results = databaseMetaData.getVersionColumns(catalog, schema, table)) { assert results != null; - bind(results, VersionColumn.class, consumer); + acceptBound(results, VersionColumn.class, consumer); } } + > T addVersionColumns(final String catalog, final String schema, + final String table, final T collection) + throws SQLException { + Objects.requireNonNull(collection, "collection is null"); + acceptVersionColumns(catalog, schema, table, collection::add); + return collection; + } + /** * Invokes {@link DatabaseMetaData#getVersionColumns(java.lang.String, java.lang.String, java.lang.String)} method * with given arguments, and returns a list of bound values. @@ -1443,12 +1677,11 @@ void getVersionColumns(final String catalog, final String schema, final String t * @param table a value for {@code table} parameter. * @return a list of bound values. * @throws SQLException if a database access error occurs. + * @see DatabaseMetaData#getVersionColumns(String, String, String) */ public List getVersionColumns(final String catalog, final String schema, final String table) throws SQLException { - final List list = new ArrayList<>(); - getVersionColumns(catalog, schema, table, list::add); - return list; + return addVersionColumns(catalog, schema, table, new ArrayList<>()); } List getVersionColumns(final Table table) throws SQLException { @@ -1456,10 +1689,11 @@ List getVersionColumns(final Table table) throws SQLException { return getVersionColumns( table.tableCatNonNull(), table.tableSchemNonNull(), - Objects.requireNonNull(table.getTableName(), "table.tableName is null") + table.getTableName() ); } + // ----------------------------------------------------------------------------------------------------------------- private Map getLabeledFields(final Class clazz) { Objects.requireNonNull(clazz, "clazz is null"); return Collections.unmodifiableMap( @@ -1467,8 +1701,10 @@ private Map getLabeledFields(final Class clazz) { ); } + // ----------------------------------------------------------------------------------------------------------------- final DatabaseMetaData databaseMetaData; + // ----------------------------------------------------------------------------------------------------------------- private final Map, Map> classesAndLabeledFields = new HashMap<>(); /** diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/CrossReference.java b/src/main/java/com/github/jinahya/database/metadata/bind/CrossReference.java index 720e16b8..572a17e8 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/CrossReference.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/CrossReference.java @@ -20,12 +20,16 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.Positive; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; +import java.util.Optional; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; @@ -38,6 +42,8 @@ */ @Setter @Getter +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class CrossReference extends AbstractMetadataType { private static final long serialVersionUID = -5343386346721125961L; @@ -54,199 +60,125 @@ public class CrossReference extends AbstractMetadataType { .thenComparing(CrossReference::getFktableName, nullsFirst(naturalOrder())) .thenComparingInt(CrossReference::getKeySeq); + // ----------------------------------------------------------------------------------------------------- UPDATE_RULE + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_UPDATE_RULE = "UPDATE_RULE"; - @Override - public String toString() { - return super.toString() + '{' + - "pktableCat=" + pktableCat + - ",pktableSchem=" + pktableSchem + - ",pktableName=" + pktableName + - ",pkcolumnName=" + pkcolumnName + - ",fktableCat=" + fktableCat + - ",fktableSchem=" + fktableSchem + - ",fktableName=" + fktableName + - ",fkcolumnName=" + fkcolumnName + - ",keySeq=" + keySeq + - ",updateRule=" + updateRule + - ",deleteRule=" + deleteRule + - ",fkName=" + fkName + - ",pkName=" + pkName + - ",deferrability=" + deferrability + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof CrossReference)) return false; - final CrossReference that = (CrossReference) obj; - return Objects.equals(pktableCatNonNull(), that.pktableCatNonNull()) && - Objects.equals(pktableSchemNonNull(), that.pktableSchemNonNull()) && - Objects.equals(pktableName, that.pktableName) && - Objects.equals(pkcolumnName, that.pkcolumnName) && - Objects.equals(fktableCatNonNull(), that.fktableCatNonNull()) && - Objects.equals(fktableSchemNonNull(), that.fktableSchemNonNull()) && - Objects.equals(fktableName, that.fktableName) && - Objects.equals(fkcolumnName, that.fkcolumnName); - } - - @Override - public int hashCode() { - return Objects.hash( - pktableCatNonNull(), pktableSchemNonNull(), pktableName, pkcolumnName, - fktableCatNonNull(), fktableSchemNonNull(), fktableName, fkcolumnName - ); - } - - public String getPktableCat() { + // ------------------------------------------------------------------------------------------------------ pkTableCat + @EqualsAndHashCode.Include + String pktableCatNonNull() { + if (pktableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return pktableCat; } - public void setPktableCat(final String pktableCat) { - this.pktableCat = pktableCat; - } - - public String getPktableSchem() { + // ---------------------------------------------------------------------------------------------------- pkTableSchem + @EqualsAndHashCode.Include + String pktableSchemNonNull() { + if (pktableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return pktableSchem; } - public void setPktableSchem(final String pktableSchem) { - this.pktableSchem = pktableSchem; - } - - public String getPktableName() { - return pktableName; - } - - public void setPktableName(final String pktableName) { - this.pktableName = pktableName; - } - - public String getPkcolumnName() { - return pkcolumnName; - } - - public void setPkcolumnName(final String pkcolumnName) { - this.pkcolumnName = pkcolumnName; - } - - public String getFktableCat() { + // ------------------------------------------------------------------------------------------------------ fktableCat + @EqualsAndHashCode.Include + String fktableCatNonNull() { + if (fktableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return fktableCat; } - public void setFktableCat(final String fktableCat) { - this.fktableCat = fktableCat; - } - - public String getFktableSchem() { + // ---------------------------------------------------------------------------------------------------- fktableSchem + @EqualsAndHashCode.Include + String fktableSchemNonNull() { + if (fktableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return fktableSchem; } - public void setFktableSchem(final String fktableSchem) { - this.fktableSchem = fktableSchem; + // ------------------------------------------------------------------------------------------------------ updateRule + TableKey.TableKeyUpdateRule getUpdateRuleAsEnum() { + return Optional.ofNullable(getUpdateRule()) + .map(TableKey.TableKeyUpdateRule::valueOfUpdateRule) + .orElse(null); } - public String getFktableName() { - return fktableName; - } - - public void setFktableName(final String fktableName) { - this.fktableName = fktableName; - } - - public String getFkcolumnName() { - return fkcolumnName; + void setUpdateRuleAsEnum(final TableKey.TableKeyUpdateRule updateRuleAsEnum) { + setUpdateRule( + Optional.ofNullable(updateRuleAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) + ); } - public void setFkcolumnName(final String fkcolumnName) { - this.fkcolumnName = fkcolumnName; - } + // ------------------------------------------------------------------------------------------------------ deleteRule + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("PKTABLE_CAT") private String pktableCat; + @Nullable @_NullableBySpecification @_ColumnLabel("PKTABLE_SCHEM") private String pktableSchem; @_ColumnLabel("PKTABLE_NAME") + @EqualsAndHashCode.Include private String pktableName; @_ColumnLabel("PKCOLUMN_NAME") + @EqualsAndHashCode.Include private String pkcolumnName; + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("FKTABLE_CAT") private String fktableCat; + @Nullable @_NullableBySpecification @_ColumnLabel("FKTABLE_SCHEM") private String fktableSchem; @_ColumnLabel("FKTABLE_NAME") + @EqualsAndHashCode.Include private String fktableName; @_ColumnLabel("FKCOLUMN_NAME") + @EqualsAndHashCode.Include private String fkcolumnName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @Positive @_ColumnLabel("KEY_SEQ") private Integer keySeq; - @_NotNull - @_ColumnLabel("UPDATE_RULE") + @_ColumnLabel(COLUMN_LABEL_UPDATE_RULE) private Integer updateRule; - @_NotNull @_ColumnLabel("DELETE_RULE") private Integer deleteRule; + @Nullable @_NullableBySpecification @_ColumnLabel("FK_NAME") private String fkName; + @Nullable @_NullableBySpecification @_ColumnLabel("PK_NAME") private String pkName; - @_NotNull @_ColumnLabel("DEFERRABILITY") private Integer deferrability; - - String pktableCatNonNull() { - final String pktableCat_ = getPktableCat(); - if (pktableCat_ != null) { - return pktableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String pktableSchemNonNull() { - final String pktableSchem_ = getPktableSchem(); - if (pktableSchem_ != null) { - return pktableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } - - String fktableCatNonNull() { - final String fktableCat_ = getFktableCat(); - if (fktableCat_ != null) { - return fktableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String fktableSchemNonNull() { - final String fktableSchem_ = getFktableSchem(); - if (fktableSchem_ != null) { - return fktableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/ExportedKey.java b/src/main/java/com/github/jinahya/database/metadata/bind/ExportedKey.java index 1499b873..b9101de8 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/ExportedKey.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/ExportedKey.java @@ -20,6 +20,9 @@ * #L% */ +import lombok.EqualsAndHashCode; +import lombok.ToString; + import java.sql.DatabaseMetaData; import java.util.Comparator; @@ -31,6 +34,8 @@ * @see Context#getExportedKeys(String, String, String) * @see ImportedKey */ +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class ExportedKey extends TableKey { private static final long serialVersionUID = -6561660015694928357L; @@ -38,22 +43,4 @@ public class ExportedKey extends TableKey { static final Comparator CASE_INSENSITIVE_ORDER = comparingFktableCaseInsensitive(); static final Comparator LEXICOGRAPHIC_ORDER = comparingFktableLexicographic(); - - @Override - public String toString() { - return super.toString() + '{' + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof ExportedKey)) return false; - return equals_((ExportedKey) obj); - } - - @Override - public int hashCode() { - return super.hashCode(); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Function.java b/src/main/java/com/github/jinahya/database/metadata/bind/Function.java index e0a6006c..721954b5 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Function.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Function.java @@ -20,6 +20,8 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.EqualsAndHashCode; import java.sql.DatabaseMetaData; @@ -119,12 +121,12 @@ public void setRemarks(String remarks) { this.remarks = remarks; } - @_NotNull + @_NonNullBySpecification public Integer getFunctionType() { return functionType; } - public void setFunctionType(@_NotNull final Integer functionType) { + public void setFunctionType(@_NonNullBySpecification final Integer functionType) { this.functionType = functionType; } @@ -136,10 +138,12 @@ public void setSpecificName(final String specificName) { this.specificName = specificName; } + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_FUNCTION_CAT) private String functionCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_FUNCTION_SCHEM) private String functionSchem; @@ -152,7 +156,8 @@ public void setSpecificName(final String specificName) { @_ColumnLabel("REMARKS") private String remarks; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("FUNCTION_TYPE") private Integer functionType; diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/FunctionColumn.java b/src/main/java/com/github/jinahya/database/metadata/bind/FunctionColumn.java index fa2605dc..66a9db7d 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/FunctionColumn.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/FunctionColumn.java @@ -20,6 +20,8 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -162,10 +164,12 @@ public void setSpecificName(final String specificName) { this.specificName = specificName; } + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_FUNCTION_CAT) private String functionCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_FUNCTION_SCHEM) private String functionSchem; @@ -176,36 +180,41 @@ public void setSpecificName(final String specificName) { @_ColumnLabel(COLUMN_LABEL_COLUMN_NAME) private String columnName; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("COLUMN_TYPE") private Integer columnType; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("DATA_TYPE") private Integer dataType; @_ColumnLabel("TYPE_NAME") private String typeName; + @Nullable @_NullableBySpecification @_ColumnLabel("PRECISION") private Integer precision; @_NullableByVendor("PostgreSQL") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("LENGTH") private Integer length; + @Nullable @_NullableBySpecification @_ColumnLabel("SCALE") private Integer scale; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("RADIX") private Integer radix; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("NULLABLE") private Integer nullable; @@ -213,11 +222,13 @@ public void setSpecificName(final String specificName) { @_ColumnLabel("REMARKS") private String remarks; + @Nullable @_NullableBySpecification @_ColumnLabel("CHAR_OCTET_LENGTH") private Integer charOctetLength; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("ORDINAL_POSITION") private Integer ordinalPosition; diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/ImportedKey.java b/src/main/java/com/github/jinahya/database/metadata/bind/ImportedKey.java index 55277e80..5f9180a5 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/ImportedKey.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/ImportedKey.java @@ -20,6 +20,9 @@ * #L% */ +import lombok.EqualsAndHashCode; +import lombok.ToString; + import java.sql.DatabaseMetaData; import java.util.Comparator; @@ -30,6 +33,8 @@ * @see Context#getImportedKeys(String, String, String) * @see ExportedKey */ +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class ImportedKey extends TableKey { private static final long serialVersionUID = -1900794151555506751L; @@ -37,22 +42,4 @@ public class ImportedKey extends TableKey { static final Comparator CASE_INSENSITIVE_ORDER = comparingPktableCaseInsensitive(); static final Comparator LEXICOGRAPHIC_ORDER = comparingPktableLexicographic(); - - @Override - public String toString() { - return super.toString() + '{' + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof ImportedKey)) return false; - return equals_((ImportedKey) obj); - } - - @Override - public int hashCode() { - return super.hashCode(); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/IndexInfo.java b/src/main/java/com/github/jinahya/database/metadata/bind/IndexInfo.java index ae38dab4..e4e5585f 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/IndexInfo.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/IndexInfo.java @@ -20,9 +20,12 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; @@ -40,7 +43,8 @@ */ @Setter @Getter -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class IndexInfo extends AbstractMetadataType { private static final long serialVersionUID = 924040226611181424L; @@ -49,100 +53,32 @@ public class IndexInfo extends AbstractMetadataType { Comparator.comparing(IndexInfo::getNonUnique, nullsFirst(naturalOrder())) .thenComparing(IndexInfo::getType, nullsFirst(naturalOrder())) .thenComparing(IndexInfo::getIndexName, nullsFirst(String.CASE_INSENSITIVE_ORDER)) - .thenComparingInt(IndexInfo::getOrdinalPosition); + .thenComparing(IndexInfo::getOrdinalPosition, nullsFirst(naturalOrder())); static final Comparator LEXICOGRAPHIC_ORDER = Comparator.comparing(IndexInfo::getNonUnique, nullsFirst(naturalOrder())) .thenComparing(IndexInfo::getType, nullsFirst(naturalOrder())) .thenComparing(IndexInfo::getIndexName, nullsFirst(naturalOrder())) - .thenComparingInt(IndexInfo::getOrdinalPosition); + .thenComparing(IndexInfo::getOrdinalPosition, nullsFirst(naturalOrder())); + // ------------------------------------------------------------------------------------------------------- TABLE_CAT public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; + // ----------------------------------------------------------------------------------------------------- TABLE_SCHEM public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; + // ------------------------------------------------------------------------------------------------------ TABLE_NAME public static final String COLUMN_LABEL_TABLE_NAME = "TABLE_NAME"; + // ------------------------------------------------------------------------------------------------------------ TYPE public static final String COLUMN_LABEL_TYPE = "TYPE"; - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem=" + tableSchem + - ",tableName=" + tableName + - ",nonUnique=" + nonUnique + - ",indexQualifier=" + indexQualifier + - ",indexName=" + indexName + - ",type=" + type + - ",ordinalPosition=" + ordinalPosition + - ",columnName=" + columnName + - ",ascOrDesc=" + ascOrDesc + - ",cardinality=" + cardinality + - ",pages=" + pages + - ",filterCondition=" + filterCondition + - '}'; - } - - @_NullableBySpecification - @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) - private String tableCat; - - @_NullableBySpecification - @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) - private String tableSchem; - - @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) - private String tableName; - - @_NotNull - @_ColumnLabel("NON_UNIQUE") - private Boolean nonUnique; - - @_NullableBySpecification - @_ColumnLabel("INDEX_QUALIFIER") - private String indexQualifier; - - @_NullableBySpecification - @_ColumnLabel("INDEX_NAME") - private String indexName; - - @_NotNull - @_ColumnLabel(COLUMN_LABEL_TYPE) - private Integer type; - - @_NotNull - @_ColumnLabel("ORDINAL_POSITION") - private Integer ordinalPosition; - - @_NullableBySpecification - @_ColumnLabel("COLUMN_NAME") - private String columnName; - - @_NullableBySpecification - @_ColumnLabel("ASC_OR_DESC") - private String ascOrDesc; - - @_NullableByVendor("Apache Derby") - @_NotNull - @_ColumnLabel("CARDINALITY") - private Long cardinality; - - @_NullableByVendor("Apache Derby") - @_NotNull - @_ColumnLabel("PAGES") - private Long pages; - - @_NullableBySpecification - @_ColumnLabel("FILTER_CONDITION") - private String filterCondition; - /** * Constants for the {@code type} attribute binds {@value #COLUMN_LABEL_TYPE} column. * * @author Jin Kwon <onacit_at_gmail.com> */ - enum Type implements _IntFieldEnum { + public enum Type implements _IntFieldEnum { /** * The constant for the @@ -182,17 +118,106 @@ public int fieldValueAsInt() { private final int fieldValue; } + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return tableCat; + } + + // ------------------------------------------------------------------------------------------------------ tableSchem + @EqualsAndHashCode.Include + String tableSchemNonNull() { + if (tableSchem == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return tableSchem; + } + + // ------------------------------------------------------------------------------------------------------------ type Type getTypeAsEnum() { return Optional.ofNullable(getType()) .map(Type::valueOfType) .orElse(null); } - void setTypeAsEnum(Type typeAsEnum) { + void setTypeAsEnum(final Type typeAsEnum) { setType( Optional.ofNullable(typeAsEnum) .map(_IntFieldEnum::fieldValueAsInt) .orElse(null) ); } + + // ----------------------------------------------------------------------------------------------------------------- + @Nullable + @_NullableBySpecification + @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) + private String tableCat; + + @Nullable + @_NullableBySpecification + @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) + private String tableSchem; + + @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include + private String tableName; + + @NotNull + @_NonNullBySpecification + @_ColumnLabel("NON_UNIQUE") + @EqualsAndHashCode.Include + private Boolean nonUnique; + + @Nullable + @_NullableBySpecification + @_ColumnLabel("INDEX_QUALIFIER") + private String indexQualifier; + + @Nullable + @_NullableBySpecification + @_ColumnLabel("INDEX_NAME") + @EqualsAndHashCode.Include + private String indexName; + + @NotNull + @_NonNullBySpecification + @_ColumnLabel(COLUMN_LABEL_TYPE) + @EqualsAndHashCode.Include + private Integer type; + + @NotNull + @_NonNullBySpecification + @_ColumnLabel("ORDINAL_POSITION") + @EqualsAndHashCode.Include + private Integer ordinalPosition; + + @Nullable + @_NullableBySpecification + @_ColumnLabel("COLUMN_NAME") + private String columnName; + + @Nullable + @_NullableBySpecification + @_ColumnLabel("ASC_OR_DESC") + private String ascOrDesc; + + @_NullableByVendor("Apache Derby") + @_NonNullBySpecification + @_ColumnLabel("CARDINALITY") + @EqualsAndHashCode.Include + private Long cardinality; + + @_NullableByVendor("Apache Derby") + @_NonNullBySpecification + @_ColumnLabel("PAGES") + private Long pages; + + @Nullable + @_NullableBySpecification + @_ColumnLabel("FILTER_CONDITION") + private String filterCondition; } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/PrimaryKey.java b/src/main/java/com/github/jinahya/database/metadata/bind/PrimaryKey.java index 9af56eca..33286841 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/PrimaryKey.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/PrimaryKey.java @@ -20,9 +20,16 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; @@ -32,162 +39,116 @@ * @author Jin Kwon <jinahya_at_gmail.com> * @see Context#getPrimaryKeys(String, String, String) */ +@Setter +@Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class PrimaryKey extends AbstractMetadataType { private static final long serialVersionUID = 3159826510060898330L; - static final Comparator CASE_INSENSITIVE_ORDER - = Comparator.comparing(PrimaryKey::getColumnName, String.CASE_INSENSITIVE_ORDER); + // ----------------------------------------------------------------------------------------------------------------- + static final Comparator CASE_INSENSITIVE_ORDER = +// Comparator.comparing(PrimaryKey::getTableCat, nullsFirst(String.CASE_INSENSITIVE_ORDER)) +// .thenComparing(PrimaryKey::getTableSchem, nullsFirst(String.CASE_INSENSITIVE_ORDER)) +// .thenComparing(PrimaryKey::getTableName, String.CASE_INSENSITIVE_ORDER) +// .thenComparing(PrimaryKey::getColumnName, String.CASE_INSENSITIVE_ORDER); + Comparator.comparing(PrimaryKey::getColumnName, String.CASE_INSENSITIVE_ORDER); + + static final Comparator LEXICOGRAPHIC_ORDER = +// Comparator.comparing(PrimaryKey::getColumnName, nullsFirst(naturalOrder())) +// .thenComparing(PrimaryKey::getColumnName, nullsFirst(naturalOrder())) +// .thenComparing(PrimaryKey::getColumnName, naturalOrder()) +// .thenComparing(PrimaryKey::getColumnName, naturalOrder()); + Comparator.comparing(PrimaryKey::getColumnName, naturalOrder()); - static final Comparator LEXICOGRAPHIC_ORDER - = Comparator.comparing(PrimaryKey::getColumnName, naturalOrder()); + // ------------------------------------------------------------------------------------------------------- TABLE_CAT /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; + // ----------------------------------------------------------------------------------------------------- TABLE_SCHEM + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; + // ------------------------------------------------------------------------------------------------------ TABLE_NAME + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_NAME = "TABLE_NAME"; + // ----------------------------------------------------------------------------------------------------- COLUMN_NAME + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_COLUMN_NAME = "COLUMN_NAME"; + // --------------------------------------------------------------------------------------------------------- KEY_SEQ + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_KEY_SEQ = "KEY_SEQ"; + // --------------------------------------------------------------------------------------------------------- PK_NAME + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_PK_NAME = "PK_NAME"; - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem=" + tableSchem + - ",tableName=" + tableName + - ",columnName=" + columnName + - ",keySeq=" + keySeq + - ",pkName=" + pkName + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof PrimaryKey)) return false; - final PrimaryKey that = (PrimaryKey) obj; - return Objects.equals(tableCatNonNull(), that.tableCatNonNull()) && - Objects.equals(tableSchemNonNull(), that.tableSchemNonNull()) && - Objects.equals(tableName, that.tableName) && - Objects.equals(columnName, that.columnName); - } - - @Override - public int hashCode() { - return Objects.hash( - tableCatNonNull(), - tableSchemNonNull(), - tableName, - columnName - ); - } - - public String getTableCat() { + // -------------------------------------------------------------------------------------------------------- tableCat + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return tableCat; } - public void setTableCat(final String tableCat) { - this.tableCat = tableCat; - } - - public String getTableSchem() { + // ------------------------------------------------------------------------------------------------------ tableSchem + String tableSchemNonNull() { + if (tableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return tableSchem; } - public void setTableSchem(final String tableSchem) { - this.tableSchem = tableSchem; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(final String tableName) { - this.tableName = tableName; - } - - public String getColumnName() { - return columnName; - } - - public void setColumnName(final String columnName) { - this.columnName = columnName; - } - - public Integer getKeySeq() { - return keySeq; - } - - public void setKeySeq(final Integer keySeq) { - this.keySeq = keySeq; - } - - public String getPkName() { - return pkName; - } - - public void setPkName(final String pkName) { - this.pkName = pkName; - } - + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) private String tableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; @_ColumnLabel(COLUMN_LABEL_COLUMN_NAME) + @EqualsAndHashCode.Include private String columnName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @Positive + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_KEY_SEQ) private Integer keySeq; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_PK_NAME) + @EqualsAndHashCode.Include private String pkName; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ != null) { - return tableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - if (tableSchem_ != null) { - return tableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Procedure.java b/src/main/java/com/github/jinahya/database/metadata/bind/Procedure.java index 72f39245..4eada898 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Procedure.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Procedure.java @@ -20,9 +20,15 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; import static java.util.Comparator.naturalOrder; @@ -36,10 +42,15 @@ * @see Context#getFunctionColumns(String, String, String, String) * @see ProcedureColumn */ +@Setter +@Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class Procedure extends AbstractMetadataType { private static final long serialVersionUID = -6262056388403934829L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparing(Procedure::getProcedureCat, nullsFirst(String.CASE_INSENSITIVE_ORDER)) .thenComparing(Procedure::getProcedureSchem, nullsFirst(String.CASE_INSENSITIVE_ORDER)) @@ -52,18 +63,10 @@ public class Procedure extends AbstractMetadataType { .thenComparing(Procedure::getProcedureName, nullsFirst(naturalOrder())) .thenComparing(Procedure::getSpecificName, nullsFirst(naturalOrder())); + // -------------------------------------------------------------------------------------------------- PROCEDURE_TYPE + /** * A colum label of {@value}. - *

- *

- * kind of procedure: - *
    - *
  • {@link DatabaseMetaData#procedureResultUnknown procedureResultUnknown} - Cannot determine if a return value will be returned
  • - *
  • {@link DatabaseMetaData#procedureNoResult procedureNoResult} - Does not return a return value
  • - *
  • {@link DatabaseMetaData#procedureReturnsResult procedureReturnsResult} - Returns a return value
  • - *
- *
*/ public static final String COLUMN_LABEL_PROCEDURE_TYPE = "PROCEDURE_TYPE"; @@ -111,118 +114,14 @@ public int fieldValueAsInt() { private final int fieldValue; } + // --------------------------------------------------------------------------------------------------- SPECIFIC_NAME + /** * A colum label of {@value}. - *

- *

The - * name which uniquely identifies this procedure within its schema.
*/ public static final String COLUMN_LABEL_SPECIFIC_NAME = "SPECIFIC_NAME"; - @Override - public String toString() { - return "Procedure{" + - "procedureCat=" + procedureCat + - ",procedureSchem=" + procedureSchem + - ",procedureName=" + procedureName + - ",remarks=" + remarks + - ",procedureType=" + procedureType + - ",specificName=" + specificName + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof Procedure)) return false; - final Procedure that = (Procedure) obj; - return Objects.equals(procedureCatNonNull(), that.procedureCatNonNull()) && - Objects.equals(procedureSchemNonNull(), that.procedureSchemNonNull()) && - Objects.equals(procedureName, that.procedureName) && - Objects.equals(specificName, that.specificName); - } - - @Override - public int hashCode() { - return Objects.hash( - procedureCatNonNull(), - procedureSchemNonNull(), - procedureName, - specificName - ); - } - - public String getProcedureCat() { - return procedureCat; - } - - public void setProcedureCat(final String procedureCat) { - this.procedureCat = procedureCat; - } - - public String getProcedureSchem() { - return procedureSchem; - } - - public void setProcedureSchem(final String procedureSchem) { - this.procedureSchem = procedureSchem; - } - - public Integer getProcedureType() { - return procedureType; - } - - public void setProcedureType(final Integer procedureType) { - this.procedureType = procedureType; - } - - public String getProcedureName() { - return procedureName; - } - - public void setProcedureName(final String procedureName) { - this.procedureName = procedureName; - } - - public String getRemarks() { - return remarks; - } - - public void setRemarks(final String remarks) { - this.remarks = remarks; - } - - public String getSpecificName() { - return specificName; - } - - public void setSpecificName(final String specificName) { - this.specificName = specificName; - } - - @_NullableBySpecification - @_ColumnLabel("PROCEDURE_CAT") - private String procedureCat; - - @_NullableBySpecification - @_ColumnLabel("PROCEDURE_SCHEM") - private String procedureSchem; - - @_ColumnLabel("PROCEDURE_NAME") - private String procedureName; - - @_NullableByVendor("HSQL") - @_ColumnLabel("REMARKS") - private String remarks; - - @_NotNull - @_ColumnLabel("PROCEDURE_TYPE") - private Integer procedureType; - - @_ColumnLabel(COLUMN_LABEL_SPECIFIC_NAME) - private String specificName; - + // ---------------------------------------------------------------------------------------------------- procedureCat String procedureCatNonNull() { final String procedureCat_ = getProcedureCat(); if (procedureCat_ != null) { @@ -231,6 +130,7 @@ String procedureCatNonNull() { return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; } + // -------------------------------------------------------------------------------------------------- procedureSchem String procedureSchemNonNull() { final String procedureSchem_ = getProcedureSchem(); if (procedureSchem_ != null) { @@ -239,6 +139,7 @@ String procedureSchemNonNull() { return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; } + // --------------------------------------------------------------------------------------------------- procedureType ProcedureType getProcedureTypeAsEnum() { return Optional.ofNullable(getProcedureType()) .map(ProcedureType::valueOfProcedureType) @@ -252,4 +153,33 @@ void setProcedureTypeAsEnum(final ProcedureType procedureTypeAsEnum) { .orElse(null) ); } + + // ----------------------------------------------------------------------------------------------------------------- + @Nullable + @_NullableBySpecification + @_ColumnLabel("PROCEDURE_CAT") + @EqualsAndHashCode.Include + private String procedureCat; + + @Nullable + @_NullableBySpecification + @_ColumnLabel("PROCEDURE_SCHEM") + @EqualsAndHashCode.Include + private String procedureSchem; + + @_ColumnLabel("PROCEDURE_NAME") + private String procedureName; + + @_NullableByVendor("HSQL") + @_ColumnLabel("REMARKS") + private String remarks; + + @NotNull + @_NonNullBySpecification + @_ColumnLabel("PROCEDURE_TYPE") + private Integer procedureType; + + @_ColumnLabel(COLUMN_LABEL_SPECIFIC_NAME) + @EqualsAndHashCode.Include + private String specificName; } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/ProcedureColumn.java b/src/main/java/com/github/jinahya/database/metadata/bind/ProcedureColumn.java index 33b21084..5f9e8591 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/ProcedureColumn.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/ProcedureColumn.java @@ -20,13 +20,15 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; @@ -41,11 +43,13 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) @ToString(callSuper = true) public class ProcedureColumn extends AbstractMetadataType { private static final long serialVersionUID = 3894753719381358829L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparing(ProcedureColumn::getProcedureCat, nullsFirst(String.CASE_INSENSITIVE_ORDER)) .thenComparing(ProcedureColumn::getProcedureSchem, nullsFirst(String.CASE_INSENSITIVE_ORDER)) @@ -58,33 +62,32 @@ public class ProcedureColumn extends AbstractMetadataType { .thenComparing(ProcedureColumn::getProcedureName, nullsFirst(naturalOrder())) .thenComparing(ProcedureColumn::getSpecificName, nullsFirst(naturalOrder())); - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof ProcedureColumn)) return false; - final ProcedureColumn that = (ProcedureColumn) o; - return Objects.equals(columnType, that.columnType) && - Objects.equals(procedureCatNonNull(), that.procedureCatNonNull()) && - Objects.equals(procedureSchemNonNull(), that.procedureSchemNonNull()) && - Objects.equals(columnName, that.columnName) && - Objects.equals(specificName, that.specificName); + // ---------------------------------------------------------------------------------------------------- procedureCat + @EqualsAndHashCode.Include + String procedureCatNonNull() { + if (procedureCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return procedureCat; } - @Override - public int hashCode() { - return Objects.hash( - procedureCatNonNull(), - procedureSchemNonNull(), - columnName, - columnType, - specificName - ); + // -------------------------------------------------------------------------------------------------- procedureSchem + @EqualsAndHashCode.Include + String procedureSchemNonNull() { + final String procedureSchem_ = getProcedureSchem(); + if (procedureSchem_ != null) { + return procedureSchem_; + } + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; } + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("PROCEDURE_CAT") private String procedureCat; + @Nullable @_NullableBySpecification @_ColumnLabel("PROCEDURE_SCHEM") private String procedureSchem; @@ -93,39 +96,45 @@ public int hashCode() { private String procedureName; @_ColumnLabel("COLUMN_NAME") + @EqualsAndHashCode.Include private String columnName; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("COLUMN_TYPE") private Integer columnType; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("DATA_TYPE") private Integer dataType; @_ColumnLabel("TYPE_NAME") private String typeName; + @Nullable @_NullableBySpecification @_ColumnLabel("PRECISION") private Integer precision; @_NullableByVendor("HSQL Database Engine") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("LENGTH") private Integer length; // https://issues.apache.org/jira/browse/DERBY-7103 + @Nullable @_NullableBySpecification @_ColumnLabel("SCALE") private Integer scale; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("RADIX") private Integer radix; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("NULLABLE") private Integer nullable; @@ -133,6 +142,7 @@ public int hashCode() { @_ColumnLabel("REMARKS") private String remarks; + @Nullable @_NullableBySpecification @_ColumnLabel("COLUMN_DEF") private String columnDef; @@ -145,11 +155,13 @@ public int hashCode() { @_ColumnLabel("SQL_DATETIME_SUB") private Integer sqlDatetimeSub; + @Nullable @_NullableBySpecification @_ColumnLabel("CHAR_OCTET_LENGTH") private Integer charOctetLength; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("ORDINAL_POSITION") private Integer ordinalPosition; @@ -157,21 +169,6 @@ public int hashCode() { private String isNullable; @_ColumnLabel("SPECIFIC_NAME") + @EqualsAndHashCode.Include private String specificName; - - String procedureCatNonNull() { - final String procedureCat_ = getProcedureCat(); - if (procedureCat_ != null) { - return procedureCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String procedureSchemNonNull() { - final String procedureSchem_ = getProcedureSchem(); - if (procedureSchem_ != null) { - return procedureSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/PseudoColumn.java b/src/main/java/com/github/jinahya/database/metadata/bind/PseudoColumn.java index 80c40063..15009f68 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/PseudoColumn.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/PseudoColumn.java @@ -20,13 +20,15 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; @@ -38,11 +40,13 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) @ToString(callSuper = true) public class PseudoColumn extends AbstractMetadataType { private static final long serialVersionUID = -5612575879670895510L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparing(PseudoColumn::tableCatNonNull, nullsFirst(String.CASE_INSENSITIVE_ORDER)) .thenComparing(PseudoColumn::tableSchemNonNull, nullsFirst(String.CASE_INSENSITIVE_ORDER)) @@ -55,6 +59,7 @@ public class PseudoColumn extends AbstractMetadataType { .thenComparing(PseudoColumn::getTableName, nullsFirst(naturalOrder())) .thenComparing(PseudoColumn::getColumnName, nullsFirst(naturalOrder())); + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; @@ -63,100 +68,88 @@ public class PseudoColumn extends AbstractMetadataType { public static final String COLUMN_LABEL_COLUMN_NAME = "COLUMN_NAME"; - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof PseudoColumn)) return false; - final PseudoColumn that = (PseudoColumn) obj; - return Objects.equals(tableCatNonNull(), that.tableCatNonNull()) && - Objects.equals(tableSchemNonNull(), that.tableSchemNonNull()) && - Objects.equals(tableName, that.tableName) && - Objects.equals(columnName, that.columnName); - } + // ----------------------------------------------------------------------------------------------------- IS_NULLABLE + public static final String COLUMN_LABEL_COLUMN_IS_NULLABLE = "IS_NULLABLE"; - @Override - public int hashCode() { - return Objects.hash( - tableCatNonNull(), - tableSchemNonNull(), - tableName, - columnName - ); - } + public static final String COLUMN_VALUE_COLUMN_IS_NULLABLE_YES = "YES"; - public void setTableCat(final String tableCat) { - this.tableCat = tableCat; - } + public static final String COLUMN_VALUE_COLUMN_IS_NULLABLE_NO = "NO"; - public void setTableSchem(final String tableSchem) { - this.tableSchem = tableSchem; - } + public static final String COLUMN_VALUE_COLUMN_IS_NULLABLE_EMPTY = ""; - public void setTableName(final String tableName) { - this.tableName = tableName; + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + final String tableCat_ = getTableCat(); + if (tableCat_ == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return tableCat_; } - public void setColumnName(final String columnName) { - this.columnName = columnName; + // ------------------------------------------------------------------------------------------------------ tableSchem + @EqualsAndHashCode.Include + String tableSchemNonNull() { + final String tableSchem_ = getTableSchem(); + if (tableSchem_ == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } + return tableSchem_; } + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) private String tableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; @_ColumnLabel(COLUMN_LABEL_COLUMN_NAME) + @EqualsAndHashCode.Include private String columnName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel("DATA_TYPE") private Integer dataType; + @Nullable @_NullableBySpecification @_ColumnLabel("COLUMN_SIZE") private Integer columnSize; + @Nullable @_NullableBySpecification @_ColumnLabel("DECIMAL_DIGITS") private Integer decimalDigits; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("NUM_PREC_RADIX") private Integer numPrecRadix; @_ColumnLabel("COLUMN_USAGE") private String columnUsage; + @Nullable @_NullableBySpecification @_ColumnLabel("REMARKS") private String remarks; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("CHAR_OCTET_LENGTH") private Integer charOctetLength; @_ColumnLabel("IS_NULLABLE") private String isNullable; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ == null) { - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - return tableCat_; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - if (tableSchem_ == null) { - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } - return tableSchem_; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Schema.java b/src/main/java/com/github/jinahya/database/metadata/bind/Schema.java index cdd701ac..8a84c827 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Schema.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Schema.java @@ -20,8 +20,13 @@ * #L% */ +import jakarta.annotation.Nullable; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; @@ -33,10 +38,15 @@ * @author Jin Kwon <jinahya_at_gmail.com> * @see Context#getSchemas(String, String) */ +@Setter +@Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class Schema extends AbstractMetadataType { private static final long serialVersionUID = 7457236468401244963L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparing(Schema::getTableCatalog, nullsFirst(String.CASE_INSENSITIVE_ORDER)) .thenComparing(Schema::getTableSchem, nullsFirst(String.CASE_INSENSITIVE_ORDER)); @@ -45,24 +55,30 @@ public class Schema extends AbstractMetadataType { Comparator.comparing(Schema::getTableCatalog, nullsFirst(naturalOrder())) .thenComparing(Schema::getTableSchem, nullsFirst(naturalOrder())); + // ----------------------------------------------------------------------------------------------------------------- + /** * Returns a new instance whose {@code tableCatalog} is {@value Catalog#COLUMN_VALUE_TABLE_CAT_EMPTY} and whose * {@code tableSchem} is {@value #COLUMN_VALUE_TABLE_SCHEM_EMPTY}. * * @return a new virtual instance. */ - public static Schema newVirtualInstance() { + static Schema newVirtualInstance() { final Schema instance = new Schema(); instance.setTableCatalog(Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY); instance.setTableSchem(Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY); return instance; } + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_CATALOG = "TABLE_CATALOG"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ @@ -71,61 +87,35 @@ public static Schema newVirtualInstance() { /** * A column value of {@value} for {@value #COLUMN_LABEL_TABLE_SCHEM}. */ - public static final String COLUMN_VALUE_TABLE_SCHEM_EMPTY = ""; - - @Override - public String toString() { - return super.toString() + '{' + - "tableCatalog=" + tableCatalog + - ",tableSchem=" + tableSchem + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof Schema)) return false; - final Schema that = (Schema) obj; - return Objects.equals(tableCatalogNonNull(), that.tableCatalogNonNull()) && - Objects.equals(tableSchem, that.tableSchem); - } + static final String COLUMN_VALUE_TABLE_SCHEM_EMPTY = ""; - @Override - public int hashCode() { - return Objects.hash( - tableCatalogNonNull(), - tableSchem - ); - } - - public String getTableCatalog() { - return tableCatalog; - } - - public void setTableCatalog(final String tableCatalog) { - this.tableCatalog = tableCatalog; + // ----------------------------------------------------------------------------------------------------------------- + static Schema of(final String tableCatalog, final String tableSchem) { + final Schema instance = new Schema(); + instance.setTableCatalog(tableCatalog); + instance.setTableSchem(tableSchem); + return instance; } - public String getTableSchem() { - return tableSchem; + // ---------------------------------------------------------------------------------------------------- tableCatalog + @EqualsAndHashCode.Include + String tableCatalogNonNull() { + final String tableCatalog_ = getTableCatalog(); + if (tableCatalog_ != null) { + return tableCatalog_; + } + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; } - public void setTableSchem(final String tableSchem) { - this.tableSchem = tableSchem; - } + // ------------------------------------------------------------------------------------------------------ tableSchem + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CATALOG) private String tableCatalog; @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) + @EqualsAndHashCode.Include private String tableSchem; - - String tableCatalogNonNull() { - final String tableCatalog_ = getTableCatalog(); - if (tableCatalog_ != null) { - return tableCatalog_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/SuperTable.java b/src/main/java/com/github/jinahya/database/metadata/bind/SuperTable.java index a95edef1..54430fd8 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/SuperTable.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/SuperTable.java @@ -20,7 +20,11 @@ * #L% */ -import java.util.Objects; +import jakarta.annotation.Nullable; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; /** * A entity class for binding results of the @@ -29,10 +33,15 @@ * @author Jin Kwon <jinahya_at_gmail.com> * @see Context#getSuperTables(String, String, String) */ +@Setter +@Getter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class SuperTable extends AbstractMetadataType { private static final long serialVersionUID = 3579710773784268831L; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; @@ -41,96 +50,40 @@ public class SuperTable extends AbstractMetadataType { public static final String COLUMN_LABEL_SUPERTABLE_NAME = "SUPERTABLE_NAME"; - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem" + tableSchem + - ",tableName=" + tableName + - ",supertableName='" + supertableName + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof SuperTable)) return false; - SuperTable that = (SuperTable) obj; - return Objects.equals(tableCatNonNull(), that.tableCatNonNull()) && - Objects.equals(tableSchemNonNull(), that.tableSchemNonNull()) && - Objects.equals(tableName, that.tableName) && - Objects.equals(supertableName, that.supertableName); - } - - @Override - public int hashCode() { - return Objects.hash( - tableCatNonNull(), - tableSchemNonNull(), - tableName, - supertableName - ); - } - - public String getTableCat() { + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return tableCat; } - public void setTableCat(final String tableCat) { - this.tableCat = tableCat; - } - - public String getTableSchem() { + // ------------------------------------------------------------------------------------------------------ tableSchem + @EqualsAndHashCode.Include + String tableSchemNonNull() { + if (tableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return tableSchem; } - public void setTableSchem(final String tableSchem) { - this.tableSchem = tableSchem; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(final String tableName) { - this.tableName = tableName; - } - - public String getSupertableName() { - return supertableName; - } - - public void setSupertableName(final String supertableName) { - this.supertableName = supertableName; - } - + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) private String tableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; @_ColumnLabel(COLUMN_LABEL_SUPERTABLE_NAME) + @EqualsAndHashCode.Include private String supertableName; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ != null) { - return tableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - if (tableSchem_ != null) { - return tableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/SuperType.java b/src/main/java/com/github/jinahya/database/metadata/bind/SuperType.java index abd0fab2..90384a61 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/SuperType.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/SuperType.java @@ -20,11 +20,13 @@ * #L% */ +import jakarta.annotation.Nullable; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; -import java.util.Objects; /** * A class for binding results of the @@ -35,140 +37,75 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class SuperType extends AbstractMetadataType { private static final long serialVersionUID = 4603878785941565029L; - @Override - public String toString() { - return super.toString() + '{' + - "typeCat=" + typeCat + - ",typeSchem=" + typeSchem + - ",typeName=" + typeName + - ",supertypeCat=" + supertypeCat + - ",supertypeSchem=" + supertypeSchem + - ",supertypeName=" + supertypeName + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof SuperType)) return false; - final SuperType that = (SuperType) obj; - return Objects.equals(typeCatNonNull(), that.typeCatNonNull()) && - Objects.equals(typeSchemNonNull(), that.typeSchemNonNull()) && - Objects.equals(typeName, that.typeName); - } - - @Override - public int hashCode() { - return Objects.hash( - typeCatNonNull(), - typeSchemNonNull(), - typeName - ); - } - - public String getTypeCat() { + // --------------------------------------------------------------------------------------------------------- typeCat + @EqualsAndHashCode.Include + String typeCatNonNull() { + if (typeCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return typeCat; } - public void setTypeCat(final String typeCat) { - this.typeCat = typeCat; - } - - public String getTypeSchem() { + // ------------------------------------------------------------------------------------------------------- typeSchem + @EqualsAndHashCode.Include + String typeSchemNonNull() { + if (typeSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return typeSchem; } - public void setTypeSchem(final String typeSchem) { - this.typeSchem = typeSchem; - } - - public String getTypeName() { - return typeName; - } - - public void setTypeName(final String typeName) { - this.typeName = typeName; - } - - public String getSupertypeCat() { + // ---------------------------------------------------------------------------------------------------- superTypeCat + @EqualsAndHashCode.Include + String supertypeCatNonNull() { + if (supertypeCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return supertypeCat; } - public void setSupertypeCat(final String supertypeCat) { - this.supertypeCat = supertypeCat; - } - - public String getSupertypeSchem() { + // -------------------------------------------------------------------------------------------------- superTypeSchem + @EqualsAndHashCode.Include + String supertypeSchemNonNull() { + if (supertypeSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return supertypeSchem; } - public void setSupertypeSchem(final String supertypeSchem) { - this.supertypeSchem = supertypeSchem; - } - - public String getSupertypeName() { - return supertypeName; - } - - public void setSupertypeName(final String supertypeName) { - this.supertypeName = supertypeName; - } - + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("TYPE_CAT") private String typeCat; + @Nullable @_NullableBySpecification @_ColumnLabel("TYPE_SCHEM") private String typeSchem; @_ColumnLabel("TYPE_NAME") + @EqualsAndHashCode.Include private String typeName; + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("SUPERTYPE_CAT") private String supertypeCat; + @Nullable @_NullableBySpecification @_ColumnLabel("SUPERTYPE_SCHEM") private String supertypeSchem; @_ColumnLabel("SUPERTYPE_NAME") + @EqualsAndHashCode.Include private String supertypeName; - - String typeCatNonNull() { - final String typeCat_ = getTypeCat(); - if (typeCat_ != null) { - return typeCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String typeSchemNonNull() { - final String typeSchem_ = getTypeSchem(); - if (typeSchem_ != null) { - return typeSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } - - String supertypeCatNonNull() { - final String supertypeCat_ = getSupertypeCat(); - if (supertypeCat_ != null) { - return supertypeCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String supertypeSchemNonNull() { - final String supertypeSchem_ = getSupertypeSchem(); - if (supertypeSchem_ != null) { - return supertypeSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Table.java b/src/main/java/com/github/jinahya/database/metadata/bind/Table.java index 57bfeb13..d00c5784 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Table.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Table.java @@ -20,11 +20,14 @@ * #L% */ +import jakarta.annotation.Nullable; +import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; +import lombok.ToString; import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; @@ -39,32 +42,42 @@ */ @Setter @Getter +@NoArgsConstructor +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) public class Table extends AbstractMetadataType { private static final long serialVersionUID = 6590036695540141125L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator
CASE_INSENSITIVE_ORDER = Comparator.comparing(Table::getTableType, nullsFirst(String.CASE_INSENSITIVE_ORDER)) - .thenComparing(Table::tableCatNonNull, String.CASE_INSENSITIVE_ORDER) - .thenComparing(Table::tableSchemNonNull, String.CASE_INSENSITIVE_ORDER) + .thenComparing(Table::tableCatNonNull, nullsFirst(String.CASE_INSENSITIVE_ORDER)) + .thenComparing(Table::tableSchemNonNull, nullsFirst(String.CASE_INSENSITIVE_ORDER)) .thenComparing(Table::getTableName, String.CASE_INSENSITIVE_ORDER); static final Comparator
LEXICOGRAPHIC_ORDER = Comparator.comparing(Table::getTableType, nullsFirst(naturalOrder())) - .thenComparing(Table::tableCatNonNull) - .thenComparing(Table::tableSchemNonNull) + .thenComparing(Table::tableCatNonNull, nullsFirst(naturalOrder())) + .thenComparing(Table::tableSchemNonNull, nullsFirst(naturalOrder())) .thenComparing(Table::getTableName); + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_CAT = "TABLE_CAT"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_LABEL_TABLE_SCHEM = "TABLE_SCHEM"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ @@ -75,124 +88,102 @@ public class Table extends AbstractMetadataType { */ public static final String COLUMN_LABEL_TABLE_TYPE = "TABLE_TYPE"; - /** - * Creates a new instance. - */ - public Table() { - super(); - } - - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem=" + tableSchem + - ",tableName=" + tableName + - ",tableType=" + tableType + - ",remarks=" + remarks + - ",typeCat=" + typeCat + - ",typeSchem=" + typeSchem + - ",typeName=" + typeName + - ",selfReferencingColName=" + selfReferencingColName + - ",refGeneration=" + refGeneration + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof Table)) return false; - final Table that = (Table) obj; - return Objects.equals(tableCatNonNull(), that.getTableName()) && - Objects.equals(tableSchemNonNull(), that.tableSchemNonNull()) && - Objects.equals(tableName, that.tableName); - } - - @Override - public int hashCode() { - return Objects.hash( - tableCatNonNull(), - tableSchemNonNull(), - tableName - ); + // ----------------------------------------------------------------------------------------------------------------- + static Table of(final String tableCat, final String tableSchem, final String tableName) { + final Table instance = new Table(); + instance.setTableCat(tableCat); + instance.setTableSchem(tableSchem); + instance.setTableName(tableName); + return instance; } - public String getTableCat() { + // ----------------------------------------------------------------------------------------------------------------- +// @Override +// public boolean equals(final Object obj) { +// if (this == obj) return true; +// if (!(obj instanceof Table)) return false; +// final Table that = (Table) obj; +// return Objects.equals(tableCatNonNull(), that.getTableName()) && +// Objects.equals(tableSchemNonNull(), that.tableSchemNonNull()) && +// Objects.equals(tableName, that.tableName); +// } +// +// @Override +// public int hashCode() { +// return Objects.hash( +// tableCatNonNull(), +// tableSchemNonNull(), +// tableName +// ); +// } + + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } return tableCat; } - public void setTableCat(final String tableCat) { - this.tableCat = tableCat; - } - - public String getTableSchem() { + // ------------------------------------------------------------------------------------------------------- tableShem + @EqualsAndHashCode.Include + String tableSchemNonNull() { + if (tableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } return tableSchem; } - public void setTableSchem(final String tableSchem) { - this.tableSchem = tableSchem; - } - - public String getTableName() { - return tableName; - } - - public void setTableName(final String tableName) { - this.tableName = tableName; - } - + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) + @EqualsAndHashCode.Include private String tableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) + @EqualsAndHashCode.Exclude private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; + // ----------------------------------------------------------------------------------------------------------------- @_NullableByVendor("MariaDB") @_ColumnLabel(COLUMN_LABEL_TABLE_TYPE) private String tableType; + @Nullable @_NullableBySpecification @_ColumnLabel("REMARKS") private String remarks; + @Nullable @_NullableBySpecification @_ColumnLabel("TYPE_CAT") private String typeCat; + @Nullable @_NullableBySpecification @_ColumnLabel("TYPE_SCHEM") private String typeSchem; + @Nullable @_NullableBySpecification @_ColumnLabel("TYPE_NAME") private String typeName; + @Nullable @_NullableBySpecification @_ColumnLabel("SELF_REFERENCING_COL_NAME") private String selfReferencingColName; + @Nullable @_NullableBySpecification @_ColumnLabel("REF_GENERATION") private String refGeneration; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ != null) { - return tableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - if (tableSchem_ != null) { - return tableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TableKey.java b/src/main/java/com/github/jinahya/database/metadata/bind/TableKey.java index 8a37e1dc..052aeaf8 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TableKey.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/TableKey.java @@ -20,16 +20,18 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; +import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; -import static java.util.Comparator.naturalOrder; -import static java.util.Comparator.nullsFirst; - /** * An abstract class for binding results of the * {@link java.sql.DatabaseMetaData#getExportedKeys(String, String, String)} method or the @@ -40,10 +42,13 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public abstract class TableKey> extends AbstractMetadataType { private static final long serialVersionUID = 6713872409315471232L; + // ----------------------------------------------------------------------------------------------------------------- static > Comparator comparingPktableCaseInsensitive() { return Comparator.comparing(TableKey::pktableCatNonNull, String.CASE_INSENSITIVE_ORDER) .thenComparing(TableKey::pktableSchemNonNull, String.CASE_INSENSITIVE_ORDER) @@ -72,61 +77,186 @@ static > Comparator comparingFktableLexicographic() { .thenComparingInt(TableKey::getKeySeq); } + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_PKTABLE_CAT = "PKTABLE_CAT"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_PKTABLE_SCHEM = "PKTABLE_SCHEM"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_PKTABLE_NAME = "PKTABLE_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_PKCOLUMN_NAME = "PKCOLUMN_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_FKTABLE_CAT = "FKTABLE_CAT"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_FKTABLE_SCHEM = "FKTABLE_SCHEM"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_FKTABLE_NAME = "FKTABLE_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_FKCOLUMN_NAME = "FKCOLUMN_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_KEY_SEQ = "KEY_SEQ"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_UPDATE_RULE = "UPDATE_RULE"; + /** + * Constants for values of {@value TableKey#COLUMN_NAME_UPDATE_RULE} column. + * + * @author Jin Kwon <onacit_at_gmail.com> + * @see ExportedKey + * @see ImportedKey + */ + public enum TableKeyUpdateRule implements _IntFieldEnum { + + /** + * Constants for {@link DatabaseMetaData#importedKeyCascade}({@value DatabaseMetaData#importedKeyCascade}). + */ + IMPORTED_KEY_CASCADE(DatabaseMetaData.importedKeyCascade), // 0 + + /** + * Constants for {@link DatabaseMetaData#importedKeyRestrict}({@value DatabaseMetaData#importedKeyRestrict}). + */ + IMPORTED_KEY_RESTRICT(DatabaseMetaData.importedKeyRestrict), // 1 + + /** + * Constants for {@link DatabaseMetaData#importedKeySetNull}({@value DatabaseMetaData#importedKeySetNull}). + */ + IMPORTED_KEY_SET_NULL(DatabaseMetaData.importedKeySetNull), // 2 + + /** + * Constants for {@link DatabaseMetaData#importedKeyNoAction}({@value DatabaseMetaData#importedKeyNoAction}). + */ + IMPORTED_KEY_NO_ACTION(DatabaseMetaData.importedKeyNoAction), // 3 + + /** + * Constants for + * {@link DatabaseMetaData#importedKeySetDefault}({@value DatabaseMetaData#importedKeySetDefault}). + */ + IMPORTED_KEY_SET_DEFAULT(DatabaseMetaData.importedKeySetDefault); // 4 + + public static TableKeyUpdateRule valueOfUpdateRule(final int updateRule) { + return _IntFieldEnum.valueOfFieldValue(TableKeyUpdateRule.class, updateRule); + } + + TableKeyUpdateRule(final int fieldValue) { + this.fieldValue = fieldValue; + } + + @Override + public int fieldValueAsInt() { + return fieldValue; + } + + private final int fieldValue; + } + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_DELETE_RULE = "DELETE_RULE"; + /** + * Constants for values of {@value TableKey#COLUMN_NAME_DELETE_RULE} column. + * + * @author Jin Kwon <onacit_at_gmail.com> + * @see ExportedKey + * @see ImportedKey + */ + public enum TableKeyDeleteRule implements _IntFieldEnum { + + /** + * Constants for {@link DatabaseMetaData#importedKeyCascade}({@value DatabaseMetaData#importedKeyCascade}). + */ + IMPORTED_KEY_CASCADE(DatabaseMetaData.importedKeyCascade), // 0 + + /** + * Constants for {@link DatabaseMetaData#importedKeyRestrict}({@value DatabaseMetaData#importedKeyRestrict}). + */ + IMPORTED_KEY_RESTRICT(DatabaseMetaData.importedKeyRestrict), // 1 + + /** + * Constants for {@link DatabaseMetaData#importedKeySetNull}({@value DatabaseMetaData#importedKeySetNull}). + */ + IMPORTED_KEY_SET_NULL(DatabaseMetaData.importedKeySetNull), // 2 + + /** + * Constants for {@link DatabaseMetaData#importedKeyNoAction}({@value DatabaseMetaData#importedKeyNoAction}). + */ + IMPORTED_KEY_NO_ACTION(DatabaseMetaData.importedKeyNoAction), // 3 + + /** + * Constants for + * {@link DatabaseMetaData#importedKeySetDefault}({@value DatabaseMetaData#importedKeySetDefault}). + */ + IMPORTED_KEY_SET_DEFAULT(DatabaseMetaData.importedKeySetDefault); // 4 + + public static TableKeyDeleteRule valueOfDeleteRule(final int deleteRule) { + return _IntFieldEnum.valueOfFieldValue(TableKeyDeleteRule.class, deleteRule); + } + + TableKeyDeleteRule(final int fieldValue) { + this.fieldValue = fieldValue; + } + + @Override + public int fieldValueAsInt() { + return fieldValue; + } + + private final int fieldValue; + } + + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ @@ -137,197 +267,206 @@ static > Comparator comparingFktableLexicographic() { */ public static final String COLUMN_NAME_PK_NAME = "PK_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ public static final String COLUMN_NAME_DEFERRABILITY = "DEFERRABILITY"; - @Override - public String toString() { - return super.toString() + '{' + - "pktableCat=" + pktableCat + - ",pktableSchem=" + pktableSchem + - ",pktableName=" + pktableName + - ",pkcolumnName=" + pkcolumnName + - ",fktableCat=" + fktableCat + - ",fktableSchem=" + fktableSchem + - ",fktableName=" + fktableName + - ",fkcolumnName=" + fkcolumnName + - ",keySeq=" + keySeq + - ",updateRule=" + updateRule + - ",deleteRule=" + deleteRule + - ",fkName=" + fkName + - ",pkName=" + pkName + - ",deferrability=" + deferrability + - '}'; + /** + * Constants for values of {@value TableKey#COLUMN_NAME_DEFERRABILITY} column. + * + * @author Jin Kwon <onacit_at_gmail.com> + * @see ExportedKey + * @see ImportedKey + */ + public enum TableKeyDeferrability implements _IntFieldEnum { + + /** + * Constants for + * {@link DatabaseMetaData#importedKeyInitiallyDeferred}({@value + * DatabaseMetaData#importedKeyInitiallyDeferred}). + */ + IMPORTED_KEY_INITIALLY_DEFERRED(DatabaseMetaData.importedKeyInitiallyDeferred), // 5 + + /** + * Constants for + * {@link DatabaseMetaData#importedKeyInitiallyImmediate}({@value + * DatabaseMetaData#importedKeyInitiallyImmediate}). + */ + IMPORTED_KEY_INITIALLY_IMMEDIATE(DatabaseMetaData.importedKeyInitiallyImmediate), // 6 + + /** + * Constants for + * {@link DatabaseMetaData#importedKeyNotDeferrable}({@value DatabaseMetaData#importedKeyNotDeferrable}). + */ + IMPORTED_KEY_SET_NOT_DEFERRABLE(DatabaseMetaData.importedKeyNotDeferrable); // 7 + + public static TableKeyDeferrability valueOfDeferrability(final int deferrability) { + return _IntFieldEnum.valueOfFieldValue(TableKeyDeferrability.class, deferrability); + } + + TableKeyDeferrability(final int fieldValue) { + this.fieldValue = fieldValue; + } + + @Override + public int fieldValueAsInt() { + return fieldValue; + } + + private final int fieldValue; + } + + // ------------------------------------------------------------------------------------------------------ pktableCat + @EqualsAndHashCode.Include + String pktableCatNonNull() { + if (pktableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return pktableCat; } - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof TableKey)) return false; - final TableKey that = (TableKey) obj; - return equals_(that); + // ---------------------------------------------------------------------------------------------------- pktableSchem + @EqualsAndHashCode.Include + String pktableSchemNonNull() { + if (pktableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } + return pktableSchem; } - @SuppressWarnings({"java:S100"}) - boolean equals_(final TableKey that) { - assert that != null; - return Objects.equals(pktableCatNonNull(), that.pktableCatNonNull()) && - Objects.equals(pktableSchemNonNull(), that.pktableSchemNonNull()) && - Objects.equals(pktableName, that.pktableName) && - Objects.equals(pkcolumnName, that.pkcolumnName) && - Objects.equals(fktableCatNonNull(), that.fktableCatNonNull()) && - Objects.equals(fktableSchemNonNull(), that.fktableSchemNonNull()) && - Objects.equals(fktableName, that.fktableName) && - Objects.equals(fkcolumnName, that.fkcolumnName); + // ------------------------------------------------------------------------------------------------------ fktableCat + @EqualsAndHashCode.Include + String fktableCatNonNull() { + if (fktableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return fktableCat; } - @Override - public int hashCode() { - return Objects.hash( - pktableCatNonNull(), pktableSchemNonNull(), pktableName, pkcolumnName, - fktableCatNonNull(), fktableSchemNonNull(), fktableName, fkcolumnName + // ---------------------------------------------------------------------------------------------------- fktableSchem + @EqualsAndHashCode.Include + String fktableSchemNonNull() { + if (fktableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } + return fktableSchem; + } + + // ------------------------------------------------------------------------------------------------------ updateRule + TableKeyUpdateRule getUpdateRuleAsEnum() { + return Optional.ofNullable(getUpdateRule()) + .map(TableKeyUpdateRule::valueOfUpdateRule) + .orElse(null); + } + + void setUpdateRuleAsEnum(final TableKeyUpdateRule updateRuleAsEnum) { + setUpdateRule( + Optional.ofNullable(updateRuleAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) ); } - public Integer getDeleteRule() { - return deleteRule; + // ------------------------------------------------------------------------------------------------------ deleteRule + TableKeyDeleteRule getDeleteRuleAsEnum() { + return Optional.ofNullable(getDeleteRule()) + .map(TableKeyDeleteRule::valueOfDeleteRule) + .orElse(null); } - public void setDeleteRule(final Integer deleteRule) { - this.deleteRule = deleteRule; + void setDeleteRuleAsEnum(final TableKeyDeleteRule deleteRuleAsEnum) { + setDeleteRule( + Optional.ofNullable(deleteRuleAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) + ); } - /** - * Returns current value of {@link #COLUMN_NAME_DEFERRABILITY} column value. - * - * @return current value of {@link #COLUMN_NAME_DEFERRABILITY} column value. - */ - public Integer getDeferrability() { - return deferrability; + // --------------------------------------------------------------------------------------------------- deferrability + TableKeyDeferrability getDeferrabilityAsEnum() { + return Optional.ofNullable(getDeferrability()) + .map(v -> TableKeyDeferrability.valueOfDeferrability(getDeferrability())) + .orElse(null); } - /** - * Replaces current value of {@link #COLUMN_NAME_DEFERRABILITY} column value with specified value. - * - * @param deferrability new value for the {@link #COLUMN_NAME_DEFERRABILITY} column value. - */ - public void setDeferrability(final Integer deferrability) { - this.deferrability = deferrability; + void setDeferrabilityAsEnum(final TableKeyDeferrability deferrabilityAsEnum) { + setDeferrability( + Optional.ofNullable(deferrabilityAsEnum) + .map(TableKeyDeferrability::fieldValueAsInt) + .orElse(null) + ); } + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_NAME_PKTABLE_CAT) private String pktableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_NAME_PKTABLE_SCHEM) private String pktableSchem; @_ColumnLabel(COLUMN_NAME_PKTABLE_NAME) + @EqualsAndHashCode.Include private String pktableName; @_ColumnLabel(COLUMN_NAME_PKCOLUMN_NAME) + @EqualsAndHashCode.Include private String pkcolumnName; + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_NAME_FKTABLE_CAT) private String fktableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_NAME_FKTABLE_SCHEM) private String fktableSchem; @_ColumnLabel(COLUMN_NAME_FKTABLE_NAME) + @EqualsAndHashCode.Include private String fktableName; @_ColumnLabel(COLUMN_NAME_FKCOLUMN_NAME) + @EqualsAndHashCode.Include private String fkcolumnName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @Positive + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_NAME_KEY_SEQ) private Integer keySeq; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_NAME_UPDATE_RULE) private Integer updateRule; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_NAME_DELETE_RULE) private Integer deleteRule; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_NAME_FK_NAME) private String fkName; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_NAME_PK_NAME) private String pkName; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_NAME_DEFERRABILITY) private Integer deferrability; - - String pktableCatNonNull() { - final String pktableCat_ = getPktableCat(); - return pktableCat_ == null ? Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY : pktableCat_; - } - - String pktableSchemNonNull() { - final String pktableSchem_ = getPktableSchem(); - return pktableSchem_ == null ? Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY : pktableSchem_; - } - - String fktableCatNonNull() { - final String fktableCat_ = getFktableCat(); - return fktableCat_ == null ? Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY : fktableCat_; - } - - String fktableSchemNonNull() { - final String fktableSchem_ = getFktableSchem(); - return fktableSchem_ == null ? Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY : fktableSchem_; - } - - TableKeyUpdateRule getUpdateRuleAsEnum() { - return Optional.ofNullable(getUpdateRule()) - .map(TableKeyUpdateRule::valueOfUpdateRule) - .orElse(null); - } - - void setUpdateRuleAsEnum(final TableKeyUpdateRule updateRuleAsEnum) { - setUpdateRule( - Optional.ofNullable(updateRuleAsEnum) - .map(_IntFieldEnum::fieldValueAsInt) - .orElse(null) - ); - } - - TableKeyDeleteRule getDeleteRuleAsEnum() { - return Optional.ofNullable(getDeleteRule()) - .map(TableKeyDeleteRule::valueOfDeleteRule) - .orElse(null); - } - - void setDeleteRuleAsEnum(final TableKeyDeleteRule deleteRuleAsEnum) { - setDeleteRule( - Optional.ofNullable(deleteRuleAsEnum) - .map(_IntFieldEnum::fieldValueAsInt) - .orElse(null) - ); - } - - TableKeyDeferrability getDeferrabilityAsEnum() { - return Optional.ofNullable(getDeferrability()) - .map(v -> TableKeyDeferrability.valueOfDeferrability(getDeferrability())) - .orElse(null); - } - - void setDeferrabilityAsEnum(final TableKeyDeferrability deferrabilityAsEnum) { - setDeferrability( - Optional.ofNullable(deferrabilityAsEnum) - .map(TableKeyDeferrability::fieldValueAsInt) - .orElse(null) - ); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrability.java b/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrability.java deleted file mode 100644 index 55dc2c91..00000000 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrability.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.github.jinahya.database.metadata.bind; - -/*- - * #%L - * database-metadata-bind - * %% - * Copyright (C) 2011 - 2019 Jinahya, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import java.sql.DatabaseMetaData; - -/** - * Constants for values of {@value TableKey#COLUMN_NAME_DEFERRABILITY} column. - * - * @author Jin Kwon <onacit_at_gmail.com> - * @see ExportedKey - * @see ImportedKey - */ -public enum TableKeyDeferrability implements _IntFieldEnum { - - /** - * Constants for - * {@link DatabaseMetaData#importedKeyInitiallyDeferred}({@value DatabaseMetaData#importedKeyInitiallyDeferred}). - */ - IMPORTED_KEY_INITIALLY_DEFERRED(DatabaseMetaData.importedKeyInitiallyDeferred), // 5 - - /** - * Constants for - * {@link DatabaseMetaData#importedKeyInitiallyImmediate}({@value DatabaseMetaData#importedKeyInitiallyImmediate}). - */ - IMPORTED_KEY_INITIALLY_IMMEDIATE(DatabaseMetaData.importedKeyInitiallyImmediate), // 6 - - /** - * Constants for - * {@link DatabaseMetaData#importedKeyNotDeferrable}({@value DatabaseMetaData#importedKeyNotDeferrable}). - */ - IMPORTED_KEY_SET_NOT_DEFERRABLE(DatabaseMetaData.importedKeyNotDeferrable); // 7 - - public static TableKeyDeferrability valueOfDeferrability(final int deferrability) { - return _IntFieldEnum.valueOfFieldValue(TableKeyDeferrability.class, deferrability); - } - - TableKeyDeferrability(final int fieldValue) { - this.fieldValue = fieldValue; - } - - @Override - public int fieldValueAsInt() { - return fieldValue; - } - - private final int fieldValue; -} diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRule.java b/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRule.java deleted file mode 100644 index 0207b03c..00000000 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRule.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.github.jinahya.database.metadata.bind; - -/*- - * #%L - * database-metadata-bind - * %% - * Copyright (C) 2011 - 2019 Jinahya, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import java.sql.DatabaseMetaData; - -/** - * Constants for values of {@value TableKey#COLUMN_NAME_DELETE_RULE} column. - * - * @author Jin Kwon <onacit_at_gmail.com> - * @see ExportedKey - * @see ImportedKey - */ -public enum TableKeyDeleteRule implements _IntFieldEnum { - - /** - * Constants for {@link DatabaseMetaData#importedKeyCascade}({@value DatabaseMetaData#importedKeyCascade}). - */ - IMPORTED_KEY_CASCADE(DatabaseMetaData.importedKeyCascade), // 0 - - /** - * Constants for {@link DatabaseMetaData#importedKeyRestrict}({@value DatabaseMetaData#importedKeyRestrict}). - */ - IMPORTED_KEY_RESTRICT(DatabaseMetaData.importedKeyRestrict), // 1 - - /** - * Constants for {@link DatabaseMetaData#importedKeySetNull}({@value DatabaseMetaData#importedKeySetNull}). - */ - IMPORTED_KEY_SET_NULL(DatabaseMetaData.importedKeySetNull), // 2 - - /** - * Constants for {@link DatabaseMetaData#importedKeyNoAction}({@value DatabaseMetaData#importedKeyNoAction}). - */ - IMPORTED_KEY_NO_ACTION(DatabaseMetaData.importedKeyNoAction), // 3 - - /** - * Constants for {@link DatabaseMetaData#importedKeySetDefault}({@value DatabaseMetaData#importedKeySetDefault}). - */ - IMPORTED_KEY_SET_DEFAULT(DatabaseMetaData.importedKeySetDefault); // 4 - - public static TableKeyDeleteRule valueOfDeleteRule(final int deleteRule) { - return _IntFieldEnum.valueOfFieldValue(TableKeyDeleteRule.class, deleteRule); - } - - TableKeyDeleteRule(final int fieldValue) { - this.fieldValue = fieldValue; - } - - @Override - public int fieldValueAsInt() { - return fieldValue; - } - - private final int fieldValue; -} diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRule.java b/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRule.java deleted file mode 100644 index 8ae3ecc9..00000000 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRule.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.github.jinahya.database.metadata.bind; - -/*- - * #%L - * database-metadata-bind - * %% - * Copyright (C) 2011 - 2019 Jinahya, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import java.sql.DatabaseMetaData; - -/** - * Constants for values of {@value TableKey#COLUMN_NAME_UPDATE_RULE} column. - * - * @author Jin Kwon <onacit_at_gmail.com> - * @see ExportedKey - * @see ImportedKey - */ -public enum TableKeyUpdateRule implements _IntFieldEnum { - - /** - * Constants for {@link DatabaseMetaData#importedKeyCascade}({@value DatabaseMetaData#importedKeyCascade}). - */ - IMPORTED_KEY_CASCADE(DatabaseMetaData.importedKeyCascade), // 0 - - /** - * Constants for {@link DatabaseMetaData#importedKeyRestrict}({@value DatabaseMetaData#importedKeyRestrict}). - */ - IMPORTED_KEY_RESTRICT(DatabaseMetaData.importedKeyRestrict), // 1 - - /** - * Constants for {@link DatabaseMetaData#importedKeySetNull}({@value DatabaseMetaData#importedKeySetNull}). - */ - IMPORTED_KEY_SET_NULL(DatabaseMetaData.importedKeySetNull), // 2 - - /** - * Constants for {@link DatabaseMetaData#importedKeyNoAction}({@value DatabaseMetaData#importedKeyNoAction}). - */ - IMPORTED_KEY_NO_ACTION(DatabaseMetaData.importedKeyNoAction), // 3 - - /** - * Constants for {@link DatabaseMetaData#importedKeySetDefault}({@value DatabaseMetaData#importedKeySetDefault}). - */ - IMPORTED_KEY_SET_DEFAULT(DatabaseMetaData.importedKeySetDefault); // 4 - - public static TableKeyUpdateRule valueOfUpdateRule(final int updateRule) { - return _IntFieldEnum.valueOfFieldValue(TableKeyUpdateRule.class, updateRule); - } - - TableKeyUpdateRule(final int fieldValue) { - this.fieldValue = fieldValue; - } - - @Override - public int fieldValueAsInt() { - return fieldValue; - } - - private final int fieldValue; -} diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TablePrivilege.java b/src/main/java/com/github/jinahya/database/metadata/bind/TablePrivilege.java index f2ece1fc..ec86e5f0 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TablePrivilege.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/TablePrivilege.java @@ -20,9 +20,11 @@ * #L% */ +import jakarta.annotation.Nullable; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.Comparator; @@ -38,11 +40,13 @@ */ @Setter @Getter -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class TablePrivilege extends AbstractMetadataType { private static final long serialVersionUID = -2142097373603478881L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparing(TablePrivilege::getTableCat, nullsFirst(String.CASE_INSENSITIVE_ORDER)) .thenComparing(TablePrivilege::getTableSchem, nullsFirst(String.CASE_INSENSITIVE_ORDER)) @@ -55,6 +59,8 @@ public class TablePrivilege extends AbstractMetadataType { .thenComparing(TablePrivilege::getTableName, nullsFirst(naturalOrder())) .thenComparing(TablePrivilege::getPrivilege, nullsFirst(naturalOrder())); + // ----------------------------------------------------------------------------------------------------------------- + /** * The column label of {@value}. */ @@ -70,30 +76,41 @@ public class TablePrivilege extends AbstractMetadataType { */ public static final String COLUMN_LABEL_TABLE_NAME = "TABLE_NAME"; - @Override - public String toString() { - return super.toString() + '{' + - "tableCat=" + tableCat + - ",tableSchem=" + tableSchem + - ",tableName=" + tableName + - ",grantor=" + grantor + - ",grantee=" + grantee + - ",privilege=" + privilege + - ",isGrantable=" + isGrantable + - '}'; + // -------------------------------------------------------------------------------------------------------- tableCat + @EqualsAndHashCode.Include + String tableCatNonNull() { + if (tableCat == null) { + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; + } + return tableCat; + } + + // ------------------------------------------------------------------------------------------------------ tableSchem + @EqualsAndHashCode.Include + String tableSchemNonNull() { + if (tableSchem == null) { + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; + } + return tableSchem; } + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_CAT) private String tableCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TABLE_SCHEM) private String tableSchem; @_ColumnLabel(COLUMN_LABEL_TABLE_NAME) + @EqualsAndHashCode.Include private String tableName; + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel("GRANTOR") private String grantor; @@ -102,25 +119,11 @@ public String toString() { private String grantee; @_ColumnLabel("PRIVILEGE") + @EqualsAndHashCode.Include private String privilege; + @Nullable @_NullableBySpecification @_ColumnLabel("IS_GRANTABLE") private String isGrantable; - - String tableCatNonNull() { - final String tableCat_ = getTableCat(); - if (tableCat_ != null) { - return tableCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String tableSchemNonNull() { - final String tableSchem_ = getTableSchem(); - if (tableSchem_ != null) { - return tableSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TableType.java b/src/main/java/com/github/jinahya/database/metadata/bind/TableType.java index 286b53ec..1e2f58a7 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TableType.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/TableType.java @@ -20,8 +20,12 @@ * #L% */ +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + import java.util.Comparator; -import java.util.Objects; /** * A class for binding results of the {@link java.sql.DatabaseMetaData#getTableTypes()}. @@ -29,45 +33,24 @@ * @author Jin Kwon <jinahya_at_gmail.com> * @see Context#getTableTypes() */ +@Setter +@Getter +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) public class TableType extends AbstractMetadataType { private static final long serialVersionUID = -7630634982776331078L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparing(TableType::getTableType, String.CASE_INSENSITIVE_ORDER); static final Comparator LEXICOGRAPHIC_ORDER = Comparator.comparing(TableType::getTableType); + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_TABLE_TYPE = "TABLE_TYPE"; - @Override - public String toString() { - return super.toString() + '{' + - "tableType=" + tableType + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof TableType)) return false; - final TableType that = (TableType) obj; - return Objects.equals(tableType, that.tableType); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), tableType); - } - - public String getTableType() { - return tableType; - } - - public void setTableType(final String tableType) { - this.tableType = tableType; - } - + // ----------------------------------------------------------------------------------------------------------------- @SuppressWarnings({ "java:S1700" }) diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/TypeInfo.java b/src/main/java/com/github/jinahya/database/metadata/bind/TypeInfo.java index 3519c18a..19dad8d6 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/TypeInfo.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/TypeInfo.java @@ -20,13 +20,14 @@ * #L% */ +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; /** @@ -37,13 +38,17 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class TypeInfo extends AbstractMetadataType { private static final long serialVersionUID = -3964147654019495313L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator COMPARING_DATA_TYPE = Comparator.comparingInt(TypeInfo::getDataType); + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ @@ -74,6 +79,8 @@ public class TypeInfo extends AbstractMetadataType { */ public static final String COLUMN_LABEL_CREATE_PARAMS = "CREATE_PARAMS"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. * @@ -124,11 +131,15 @@ public int fieldValueAsInt() { private final int fieldValue; } + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_CASE_SENSITIVE = "CASE_SENSITIVE"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. * @@ -184,60 +195,64 @@ public int fieldValueAsInt() { private final int fieldValue; } - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof TypeInfo)) return false; - final TypeInfo that = (TypeInfo) obj; - return Objects.equals(dataType, that.dataType) && - Objects.equals(typeName, that.typeName); - } - - @Override - public int hashCode() { - return Objects.hash(typeName, dataType); - } - - public Integer getSearchable() { - return searchable; + // ------------------------------------------------------------------------------------------------------ searchable + Searchable getSearchableAsEnum() { + return Optional.ofNullable(getSearchable()) + .map(Searchable::valueOfSearchable) + .orElse(null); } - public void setSearchable(final Integer searchable) { - this.searchable = searchable; + void setSearchableAsEnum(final Searchable searchableAsEnum) { + setSearchable( + Optional.ofNullable(searchableAsEnum) + .map(_IntFieldEnum::fieldValueAsInt) + .orElse(null) + ); } + // ----------------------------------------------------------------------------------------------------------------- @_ColumnLabel(COLUMN_LABEL_TYPE_NAME) + @EqualsAndHashCode.Include private String typeName; - @_NotNull + // ----------------------------------------------------------------------------------------------------------------- + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_DATA_TYPE) private Integer dataType; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_PRECISION) private Integer precision; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_LITERAL_PREFIX) private String literalPrefix; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_LITERAL_SUFFIX) private String literalSuffix; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_CREATE_PARAMS) private String createParams; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_NULLABLE) private Integer nullable; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_CASE_SENSITIVE) private Boolean caseSensitive; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_SEARCHABLE) private Integer searchable; @@ -245,26 +260,28 @@ public void setSearchable(final Integer searchable) { @_ColumnLabel("UNSIGNED_ATTRIBUTE") private Boolean unsignedAttribute; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("FIXED_PREC_SCALE") private Boolean fixedPrecScale; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("AUTO_INCREMENT") private Boolean autoIncrement; + @jakarta.annotation.Nullable @_NullableBySpecification @_ColumnLabel("LOCAL_TYPE_NAME") private String localTypeName; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("MINIMUM_SCALE") private Integer minimumScale; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("MAXIMUM_SCALE") private Integer maximumScale; @@ -277,21 +294,7 @@ public void setSearchable(final Integer searchable) { private Integer sqlDatetimeSub; @_NullableByVendor("Apache Derby") - @_NotNull + @_NonNullBySpecification @_ColumnLabel("NUM_PREC_RADIX") private Integer numPrecRadix; - - Searchable getSearchableAsEnum() { - return Optional.ofNullable(getSearchable()) - .map(Searchable::valueOfSearchable) - .orElse(null); - } - - void setSearchableAsEnum(final Searchable searchableAsEnum) { - setSearchable( - Optional.ofNullable(searchableAsEnum) - .map(_IntFieldEnum::fieldValueAsInt) - .orElse(null) - ); - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/UDT.java b/src/main/java/com/github/jinahya/database/metadata/bind/UDT.java index 19cc07e8..aaaa1fc5 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/UDT.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/UDT.java @@ -20,12 +20,15 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; import java.util.Comparator; -import java.util.Objects; import static java.util.Comparator.naturalOrder; import static java.util.Comparator.nullsFirst; @@ -38,10 +41,13 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class UDT extends AbstractMetadataType { private static final long serialVersionUID = 8665246093405057553L; + // ----------------------------------------------------------------------------------------------------------------- static final Comparator CASE_INSENSITIVE_ORDER = Comparator.comparingInt(UDT::getDataType) .thenComparing(UDT::typeCatNonNull, String.CASE_INSENSITIVE_ORDER) @@ -54,114 +60,83 @@ public class UDT extends AbstractMetadataType { .thenComparing(UDT::typeSchemNonNull, naturalOrder()) .thenComparing(UDT::getTypeName, nullsFirst(naturalOrder())); + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_TYPE_CAT = "TYPE_CAT"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_TYPE_SCHEM = "TYPE_SCHEM"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_TYPE_NAME = "TYPE_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_CLASS_NAME = "CLASS_NAME"; + // ----------------------------------------------------------------------------------------------------------------- + /** * A column label of {@value}. */ public static final String COLUMN_LABEL_DATA_TYPE = "DATA_TYPE"; - @Override - public String toString() { - return super.toString() + '{' + - "typeCat=" + typeCat + - ",typeSchem=" + typeSchem + - ",typeName=" + typeName + - ",className=" + className + - ",dataType=" + dataType + - ",remarks=" + remarks + - ",baseType=" + baseType + - '}'; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof UDT)) return false; - final UDT that = (UDT) obj; - return Objects.equals(dataType, that.dataType) && - Objects.equals(typeCatNonNull(), that.typeCatNonNull()) && - Objects.equals(typeSchemNonNull(), that.typeSchemNonNull()) && - Objects.equals(typeName, that.typeName); - } - - @Override - public int hashCode() { - return Objects.hash( - typeCatNonNull(), - typeSchemNonNull(), - typeName, - dataType - ); - } - - public String getTypeCat() { - return typeCat; - } - - public void setTypeCat(final String typeCat) { - this.typeCat = typeCat; - } - - public String getTypeSchem() { - return typeSchem; - } - - public void setTypeSchem(final String typeSchem) { - this.typeSchem = typeSchem; - } - - public String getTypeName() { - return typeName; - } - - public void setTypeName(final String typeName) { - this.typeName = typeName; - } - - @_NotNull - public Integer getDataType() { - return dataType; + // --------------------------------------------------------------------------------------------------------- typeCat + @EqualsAndHashCode.Include + String typeCatNonNull() { + final String typeCat_ = getTypeCat(); + if (typeCat_ != null) { + return typeCat_; + } + return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; } - public void setDataType(@_NotNull final Integer dataType) { - this.dataType = dataType; + // ------------------------------------------------------------------------------------------------------- typeSchem + @EqualsAndHashCode.Include + String typeSchemNonNull() { + final String typeSchem_ = getTypeSchem(); + if (typeSchem_ != null) { + return typeSchem_; + } + return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; } + // ----------------------------------------------------------------------------------------------------------------- + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TYPE_CAT) private String typeCat; + @Nullable @_NullableBySpecification @_ColumnLabel(COLUMN_LABEL_TYPE_SCHEM) private String typeSchem; @_ColumnLabel(COLUMN_LABEL_TYPE_NAME) + @EqualsAndHashCode.Include private String typeName; + // ----------------------------------------------------------------------------------------------------------------- @_NullableByVendor("PostgreSQL") @_ColumnLabel(COLUMN_LABEL_CLASS_NAME) private String className; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel(COLUMN_LABEL_DATA_TYPE) private Integer dataType; @@ -169,23 +144,8 @@ public void setDataType(@_NotNull final Integer dataType) { @_ColumnLabel("REMARKS") private String remarks; + @Nullable @_NullableBySpecification @_ColumnLabel("BASE_TYPE") private Integer baseType; - - String typeCatNonNull() { - final String typeCat_ = getTypeCat(); - if (typeCat_ != null) { - return typeCat_; - } - return Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY; - } - - String typeSchemNonNull() { - final String typeSchem_ = getTypeSchem(); - if (typeSchem_ != null) { - return typeSchem_; - } - return Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY; - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/Utils.java b/src/main/java/com/github/jinahya/database/metadata/bind/Utils.java index 04ffd2b9..fe1b7020 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/Utils.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/Utils.java @@ -93,10 +93,6 @@ static void setFieldValue(final Field field, final Object obj, final ResultSet r final Class fieldType = field.getType(); assert !fieldType.isPrimitive(); final Object value = results.getObject(label); - assert value != null || - (field.isAnnotationPresent(_NullableBySpecification.class) || - field.isAnnotationPresent(_NullableByVendor.class)) - : String.format("null value; label: %1$s, field: %2$s", label, field); try { field.set(obj, value); return; diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/VersionColumn.java b/src/main/java/com/github/jinahya/database/metadata/bind/VersionColumn.java index 8b552283..e60f4c03 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/VersionColumn.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/VersionColumn.java @@ -20,11 +20,14 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.sql.DatabaseMetaData; -import java.util.Objects; import java.util.Optional; /** @@ -35,10 +38,13 @@ */ @Setter @Getter +@EqualsAndHashCode(callSuper = true, onlyExplicitlyIncluded = true) +@ToString(callSuper = true) public class VersionColumn extends AbstractMetadataType { private static final long serialVersionUID = 3587959398829593292L; + // ----------------------------------------------------------------------------------------------------------------- public static final String COLUMN_LABEL_PSEUDO_COLUMN = "PSEUDO_COLUMN"; /** @@ -88,75 +94,55 @@ public int fieldValueAsInt() { private final int fieldValue; } - @Override - public String toString() { - return super.toString() + '{' + - "scope=" + scope + - ",columnName=" + columnName + - ",dataType=" + dataType + - ",typeName=" + typeName + - ",columnSize=" + columnSize + - ",bufferLength=" + bufferLength + - ",decimalDigits=" + decimalDigits + - ",pseudoColumn=" + pseudoColumn + - '}'; + // ----------------------------------------------------------------------------------------------------------------- + PseudoColumn getPseudoColumnAsEnum() { + return Optional.ofNullable(getPseudoColumn()) + .map(PseudoColumn::valueOfPseudoColumn) + .orElse(null); } - @Override - public boolean equals(final Object obj) { - if (this == obj) return true; - if (!(obj instanceof VersionColumn)) return false; - final VersionColumn that = (VersionColumn) obj; - return Objects.equals(columnName, that.columnName); + void setPseudoColumnAsEnum(final PseudoColumn pseudoColumnAsEnum) { + setPseudoColumn( + Optional.ofNullable(pseudoColumnAsEnum) + .map(PseudoColumn::fieldValueAsInt) + .orElse(null) + ); } - @Override - public int hashCode() { - return Objects.hash(columnName); - } + // ----------------------------------------------------------------------------------------------------------------- + @EqualsAndHashCode.Include + private Table parent; + // ----------------------------------------------------------------------------------------------------------------- @_NotUsedBySpecification @_ColumnLabel("SCOPE") private Integer scope; @_ColumnLabel("COLUMN_NAME") + @EqualsAndHashCode.Include private String columnName; - @_NotNull + @NotNull + @_NonNullBySpecification @_ColumnLabel("DATA_TYPE") private Integer dataType; @_ColumnLabel("TYPE_NAME") private String typeName; + @Nullable @_NullableBySpecification @_ColumnLabel("COLUMN_SIZE") private Integer columnSize; - @_NullableByVendor("PostgreSQL") - @_NotNull @_ColumnLabel("BUFFER_LENGTH") private Integer bufferLength; + @Nullable @_NullableBySpecification @_ColumnLabel("DECIMAL_DIGITS") private Integer decimalDigits; - @_NotNull @_ColumnLabel(COLUMN_LABEL_PSEUDO_COLUMN) private Integer pseudoColumn; - - PseudoColumn getPseudoColumnAsEnum() { - return Optional.ofNullable(getPseudoColumn()) - .map(PseudoColumn::valueOfPseudoColumn) - .orElse(null); - } - - void setPseudoColumnAsEnum(final PseudoColumn pseudoColumnAsEnum) { - setPseudoColumn( - Optional.ofNullable(pseudoColumnAsEnum) - .map(PseudoColumn::fieldValueAsInt) - .orElse(null) - ); - } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/EmptyTest.java b/src/main/java/com/github/jinahya/database/metadata/bind/_NonNull.java similarity index 63% rename from src/test/java/com/github/jinahya/database/metadata/bind/EmptyTest.java rename to src/main/java/com/github/jinahya/database/metadata/bind/_NonNull.java index bfb983be..f7debe8b 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/EmptyTest.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/_NonNull.java @@ -4,7 +4,7 @@ * #%L * database-metadata-bind * %% - * Copyright (C) 2011 - 2021 Jinahya, Inc. + * Copyright (C) 2011 - 2019 Jinahya, Inc. * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,19 +20,20 @@ * #L% */ -import org.junit.jupiter.api.Test; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** - * Just an empty test. + * A marker annotation for columns whose value may be not {@code null}. * * @author Jin Kwon <onacit_at_gmail.com> */ -public class EmptyTest { +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.ANNOTATION_TYPE}) +@interface _NonNull { - /** - * Does nothing. - */ - @Test - public void doNothing() { - } } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/_NotNull.java b/src/main/java/com/github/jinahya/database/metadata/bind/_NonNullBySpecification.java similarity index 96% rename from src/main/java/com/github/jinahya/database/metadata/bind/_NotNull.java rename to src/main/java/com/github/jinahya/database/metadata/bind/_NonNullBySpecification.java index 992ae92f..c0894f4c 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/_NotNull.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/_NonNullBySpecification.java @@ -32,8 +32,9 @@ * @author Jin Kwon <onacit_at_gmail.com> */ @Documented +@_NonNull @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) -@interface _NotNull { +@interface _NonNullBySpecification { } diff --git a/src/main/java/com/github/jinahya/database/metadata/bind/_NullableBySpecification.java b/src/main/java/com/github/jinahya/database/metadata/bind/_NullableBySpecification.java index 3fa245ea..1063115c 100644 --- a/src/main/java/com/github/jinahya/database/metadata/bind/_NullableBySpecification.java +++ b/src/main/java/com/github/jinahya/database/metadata/bind/_NullableBySpecification.java @@ -31,8 +31,8 @@ * * @author Jin Kwon <onacit_at_gmail.com> */ -@_Nullable @Documented +@_Nullable @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) @interface _NullableBySpecification { diff --git a/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_$_IT.java b/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_$_IT.java index c2e16892..82eeb552 100644 --- a/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_$_IT.java +++ b/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_$_IT.java @@ -88,7 +88,7 @@ R applyContextChecked(final CheckedFunction1 f @Test void test() throws SQLException { applyContextChecked(c -> { - ContextTests.test(c); + ContextTestUtils.test(c); return null; }); } @@ -96,7 +96,7 @@ void test() throws SQLException { @Test void getColumns__() { applyContextChecked(c -> { - ContextTests.getColumns__(c, null, null, "%", "%"); + ContextTestUtils.getColumns__(c, null, null, "%", "%"); return null; }); } @@ -104,7 +104,7 @@ void getColumns__() { @Test void getTables__() { applyContextChecked(c -> { - ContextTests.getTables__(c, null, null, "%", null); + ContextTestUtils.getTables__(c, null, null, "%", null); return null; }); } diff --git a/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_MySQL_IT.java b/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_MySQL_IT.java index 5311a435..73284f31 100644 --- a/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_MySQL_IT.java +++ b/src/test/java-testcontainers/com/github/jinahya/database/metadata/bind/TestContainers_MySQL_IT.java @@ -21,27 +21,46 @@ */ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.testcontainers.containers.MySQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.shaded.org.awaitility.Awaitility; import org.testcontainers.utility.DockerImageName; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; +import java.time.Duration; -@Testcontainers +//@Testcontainers @Slf4j class TestContainers_MySQL_IT extends TestContainers_$_IT { - @Container - private static final MySQLContainer CONTAINER; + // @Container + private static MySQLContainer CONTAINER; - static { + @BeforeAll + static void start() { final DockerImageName NAME = DockerImageName.parse("mysql:latest"); CONTAINER = new MySQLContainer<>(NAME); + CONTAINER.start(); + final var timeout = Duration.ofSeconds(10L); + log.debug("awaiting for {}", timeout); + Awaitility.await() + .atMost(timeout) + .pollDelay(Duration.ofSeconds(1L)) + .untilAsserted(() -> { + Assertions.assertTrue(CONTAINER.isRunning()); + }); } + @AfterAll + static void stop() { + CONTAINER.stop(); + } + + // ----------------------------------------------------------------------------------------------------------------- @Override Connection connect() throws SQLException { final var url = CONTAINER.getJdbcUrl(); diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/AttributeTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/AttributeTest.java index 85f7bd96..659c924f 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/AttributeTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/AttributeTest.java @@ -37,8 +37,8 @@ class NullableTest extends _IntFieldEnumTest { } @Override - Attribute typeInstance() { - final Attribute instance = super.typeInstance(); + Attribute newTypeInstance() { + final Attribute instance = super.newTypeInstance(); instance.setAttrName(""); instance.setTypeName(""); instance.setOrdinalPosition(1); diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/BestRowIdentifierTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/BestRowIdentifierTest.java index 43a05dd4..5bdaebd9 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/BestRowIdentifierTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/BestRowIdentifierTest.java @@ -66,7 +66,7 @@ class PseudoColumnAsEnumTest { @DisplayName("getPseudoColumnAsEnum()") @Test void getPseudoColumnAsEnum__() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); final var pseudoColumnAsEnum = spy.getPseudoColumnAsEnum(); verify(spy, times(1)).getPseudoColumn(); } @@ -74,7 +74,7 @@ void getPseudoColumnAsEnum__() { @DisplayName("setPseudoColumnAsEnum(null)") @Test void setPseudoColumnAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setPseudoColumnAsEnum(null); verify(spy, times(1)).setPseudoColumn(null); } @@ -83,7 +83,7 @@ void setPseudoColumnAsEnum_Null_Null() { @EnumSource(BestRowIdentifier.PseudoColumn.class) @ParameterizedTest void setPseudoColumnAsEnum__(final BestRowIdentifier.PseudoColumn pseudoColumnAsEnum) { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setPseudoColumnAsEnum(pseudoColumnAsEnum); verify(spy, times(1)).setPseudoColumn(pseudoColumnAsEnum.fieldValueAsInt()); } @@ -96,7 +96,7 @@ class ScopeAsEnumTest { @DisplayName("getScopeAsEnum()") @Test void getScopeAsEnum__() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); final var scopeAsEnum = spy.getScopeAsEnum(); assertThat(scopeAsEnum).isNull(); verify(spy, times(1)).getScope(); @@ -105,7 +105,7 @@ void getScopeAsEnum__() { @DisplayName("setScopeAsEnum(null)") @Test void setScopeAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setScopeAsEnum(null); verify(spy, times(1)).setScope(null); } @@ -114,7 +114,7 @@ void setScopeAsEnum_Null_Null() { @EnumSource(BestRowIdentifier.Scope.class) @ParameterizedTest void setScopeAsEnum__(final BestRowIdentifier.Scope scopeAsEnum) { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setScopeAsEnum(scopeAsEnum); verify(spy, times(1)).setScope(scopeAsEnum.fieldValueAsInt()); } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/CatalogTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/CatalogTest.java index ae0e8618..32c79426 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/CatalogTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/CatalogTest.java @@ -20,16 +20,29 @@ * #L% */ +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + class CatalogTest extends AbstractMetadataTypeTest { CatalogTest() { super(Catalog.class); } + // ----------------------------------------------------------------------------------------------------------------- @Override - Catalog typeInstance() { - final Catalog instance = super.typeInstance(); + Catalog newTypeInstance() { + final Catalog instance = super.newTypeInstance(); instance.setTableCat(Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY); return instance; } + + // ----------------------------------------------------------------------------------------------------------------- + @Test + void __() { + final Catalog i1 = new Catalog(); + final Catalog i2 = new Catalog(); + assertThat(i2).isEqualTo(i1); + } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ColumnPrivilegeTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/ColumnPrivilegeTest.java index 8a5f4a1f..c1b1a84e 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ColumnPrivilegeTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ColumnPrivilegeTest.java @@ -20,48 +20,9 @@ * #L% */ -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - class ColumnPrivilegeTest extends AbstractMetadataTypeTest { ColumnPrivilegeTest() { super(ColumnPrivilege.class); } - - @Nested - class IsGrantableAsBooleanTest { - - @Test - void getIsGrantableAsBoolean__() { - final var spy = typeSpy(); - final var isGrantableAsBoolean = spy.getIsGrantableAsBoolean(); - assertThat(isGrantableAsBoolean).isNull(); - verify(spy, times(1)).getIsGrantable(); - } - - @Test - void setIsGrantableAsBoolean__Null() { - final var spy = typeSpy(); - spy.setIsGrantableAsBoolean(null); - verify(spy, times(1)) - .setIsGrantable(null); - } - - @ValueSource(booleans = {false, true}) - @ParameterizedTest - void setIsGrantableAsBoolean__(final boolean grantableAsBoolean) { - final var spy = typeSpy(); - spy.setIsGrantableAsBoolean(grantableAsBoolean); - verify(spy, times(1)) - .setIsGrantable(grantableAsBoolean ? ColumnPrivilege.COLUMN_VALUE_IS_GRANTABLE_YES : - ColumnPrivilege.COLUMN_VALUE_IS_GRANTABLE_NO); - } - } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ColumnTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/ColumnTest.java index 6e4a0fec..54bf4b82 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ColumnTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ColumnTest.java @@ -45,8 +45,8 @@ class NullableTest extends _IntFieldEnumTest { } @Override - Column typeInstance() { - final var instance = super.typeInstance(); + Column newTypeInstance() { + final var instance = super.newTypeInstance(); instance.setTableName(""); instance.setColumnName(""); instance.setOrdinalPosition(1); @@ -59,14 +59,14 @@ class NullableAsEnumTest { @Test void getNullableAsEnum__() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); final var nullableAsEnum = spy.getNullableAsEnum(); verify(spy, times(1)).getNullable(); } @Test void setNullableAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setNullableAsEnum(null); verify(spy, times(1)).setNullable(null); } @@ -74,7 +74,7 @@ void setNullableAsEnum_Null_Null() { @EnumSource(Column.Nullable.class) @ParameterizedTest void setNullableAsEnum__(final Column.Nullable nullableAsEnum) { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setNullableAsEnum(nullableAsEnum); verify(spy, times(1)) .setNullable(nullableAsEnum.fieldValueAsInt()); diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ContextTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/ContextTest.java index f68e9361..3fdba410 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ContextTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ContextTest.java @@ -21,15 +21,14 @@ */ import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.sql.DatabaseMetaData; import java.sql.ResultSet; -import java.util.Arrays; import java.util.List; -import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -42,6 +41,7 @@ @Slf4j class ContextTest { + @DisplayName("...(...)ResultSet") @Test void assertAllMethodsBound() throws ReflectiveOperationException { for (final Method method : DatabaseMetaData.class.getMethods()) { @@ -58,16 +58,15 @@ void assertAllMethodsBound() throws ReflectiveOperationException { if (!ResultSet.class.isAssignableFrom(method.getReturnType())) { continue; } + log.debug("method: {}", method); final var name = method.getName(); { - final Class[] types = Arrays.copyOf(method.getParameterTypes(), method.getParameterCount() + 1); - types[types.length - 1] = Consumer.class; - final Method bound = Context.class.getDeclaredMethod(name, types); - assertThat(bound.getReturnType()).isEqualTo(void.class); - } - { - final Method bound = Context.class.getMethod(name, method.getParameterTypes()); - assertThat(bound.getReturnType()).isEqualTo(List.class); + final Method found = Context.class.getMethod(name, method.getParameterTypes()); + assertThat(found.getModifiers()).satisfies(m -> { + assertThat(Modifier.isStatic(m)).isFalse(); + assertThat(Modifier.isPublic(m)).isTrue(); + }); + assertThat(found.getReturnType()).isEqualTo(List.class); } } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ContextTestUtils.java b/src/test/java/com/github/jinahya/database/metadata/bind/ContextTestUtils.java index 108358fc..18524f3e 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ContextTestUtils.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ContextTestUtils.java @@ -20,11 +20,1447 @@ * #L% */ +import io.vavr.CheckedConsumer; +import io.vavr.CheckedFunction1; import lombok.extern.slf4j.Slf4j; +import org.junit.platform.commons.util.ReflectionUtils; +import java.sql.JDBCType; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLSyntaxErrorException; +import java.sql.Types; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + +/** + * An abstract test class for in-memory databases. + * + * @author Jin Kwon <onacit at gmail.com> + */ @Slf4j final class ContextTestUtils { + private static final boolean READ_TABLE_PRIVILEGES = false; + + private static final boolean READ_COLUMN_PRIVILEGES = false; + + static void info(final Context context) throws SQLException { + Objects.requireNonNull(context, "context is null"); + databaseProductName = context.databaseMetaData.getDatabaseProductName(); + log.info("databaseProductName: {}", databaseProductName); + log.info("databaseProductVersion: {}", context.databaseMetaData.getDatabaseProductVersion()); + log.info("databaseMajorVersion: {}", context.databaseMetaData.getDatabaseMajorVersion()); + log.info("databaseMinorVersion: {}", context.databaseMetaData.getDatabaseMinorVersion()); + log.info("driverName: {}", context.databaseMetaData.getDriverName()); + log.info("driverVersion: {}", context.databaseMetaData.getDriverVersion()); + log.info("driverMajorVersion: {}", context.databaseMetaData.getDriverMajorVersion()); + log.info("driverMinorVersion: {}", context.databaseMetaData.getDriverMinorVersion()); + log.info("catalogSeparator: {}", context.databaseMetaData.getCatalogSeparator()); + log.info("catalogTerm: {}", context.databaseMetaData.getCatalogTerm()); + log.info("schemaTerm: {}", context.databaseMetaData.getSchemaTerm()); + } + + private static T common(final T value) { + Objects.requireNonNull(value, "value is null"); + { + final var string = value.toString(); + } + { + final var hashCode = value.hashCode(); + } + if (value instanceof MetadataType) { + final var unmappedValues = ((MetadataType) value).getUnmappedValues(); + if (!unmappedValues.isEmpty()) { + log.warn("unmapped values of {}: {}", value.getClass().getSimpleName(), unmappedValues); + } + } + // .toBuilder().build() + ReflectionUtils.findMethod(value.getClass(), "toBuilder") + .map(m -> { + try { + return m.invoke(value); + } catch (final ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + }) + .flatMap(b -> ReflectionUtils.findMethod(b.getClass(), "build") + .map(m -> { + try { + return m.invoke(b); + } catch (final ReflectiveOperationException row) { + throw new RuntimeException(row); + } + }) + ); + return value; + } + + private static void thrown(final String message, final Throwable throwable) { + Objects.requireNonNull(message, "message is null"); + Objects.requireNonNull(throwable, "throwable is null"); + if (throwable instanceof SQLFeatureNotSupportedException) { + return; + } + log.error("{}", message, throwable); + } + + // ----------------------------------------------------------------------------------------------------------------- + + // ----------------------------------------------------------------------------------------------------------------- + private static String databaseProductName; + + private static void checked(final Context context, + final CheckedFunction1 function, + final CheckedConsumer consumer) + throws Throwable { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(function, "function is null"); + Objects.requireNonNull(context, "context is null"); + final R r; + try { + r = function.apply(context); + } catch (final Throwable e) { + if (e instanceof SQLFeatureNotSupportedException sqlfnse) { + log.error("sql feature not supported", sqlfnse); + return; + } + throw new RuntimeException(e); + } + consumer.accept(r); + } + + static void test(final Context context) throws SQLException { + Objects.requireNonNull(context, "context is null"); + + { + databaseProductName = context.databaseMetaData.getDatabaseProductName(); + info(context); + } + // ---------------------------------------------------------------------------------------------------- catalogs + try { + final var catalogs = context.getCatalogs(); + if (catalogs.isEmpty()) { + log.info("no catalogs retrieved"); + catalogs.add(Catalog.of("")); + } + catalogs(context, catalogs); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // -------------------------------------------------------------------------------------------- clientProperties + try { + final var clientInfoProperties = context.getClientInfoProperties(); + clientInfoProperties(context, clientInfoProperties); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // --------------------------------------------------------------------------------------------------- functions + try { + final var functions = context.getFunctions(null, null, "%"); + functions(context, functions); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // -------------------------------------------------------------------------------------------------- procedures + try { + final var procedures = context.getProcedures(null, null, "%"); + procedures(context, procedures); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ----------------------------------------------------------------------------------------------------- schemas + try { + final var schemas = context.getSchemas(); + if (schemas.isEmpty()) { + schemas.add(Schema.newVirtualInstance()); + } + schemas(context, schemas); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ----------------------------------------------------------------------------------------------------- schemas + try { + final var schemas = context.getSchemas((String) null, null); + if (schemas.isEmpty()) { + schemas.add(Schema.newVirtualInstance()); + } + schemas(context, schemas); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // -------------------------------------------------------------------------------------------------- tableTypes + try { + final var tableTypes = context.getTableTypes(); + tableTypes(context, tableTypes); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ------------------------------------------------------------------------------------------------------ tables + try { + final var tables = context.getTables(null, null, "%", null); + tables(context, tables); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ---------------------------------------------------------------------------------------------------- typeInfo + try { + final var typeInfo = context.getTypeInfo(); + typeInfo(context, typeInfo); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // -------------------------------------------------------------------------------------------------------- udts + try { + final var udts = context.getUDTs(null, null, "%", null); + udts(context, udts); + } catch (final SQLException sqle) { + thrown("failed; getUDTs", sqle); + } + // -------------------------------------------------------------------------------------------- numericFunctions + try { + final Set NumericFunctions = context.getNumericFunctions(); + log.debug("numericFunctions: {}", NumericFunctions); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ---------------------------------------------------------------------------------------------- getSQLKeywords + try { + final Set SQLKeywords = context.getSQLKeywords(); + log.debug("SQLKeywords: {}", SQLKeywords); + } catch (final SQLException sqle) { + thrown("failed; getSQLKeywords", sqle); + } + // ------------------------------------------------------------------------------------------ getStringFunctions + try { + final Set stringFunctions = context.getStringFunctions(); + log.debug("stringFunctions: {}", stringFunctions); + } catch (final SQLException sqle) { + thrown("failed; getStringFunctions", sqle); + } + // ------------------------------------------------------------------------------------------ getSystemFunctions + try { + final Set systemFunctions = context.getSystemFunctions(); + log.debug("system functions: {}", systemFunctions); + } catch (final SQLException sqle) { + thrown("failed; getSystemFunctions", sqle); + } + // ---------------------------------------------------------------------------------------- getTimeDateFunctions + try { + final Set timeDateFunction = context.getTimeDateFunctions(); + log.debug("time date functions: {}", timeDateFunction); + } catch (final SQLException sqle) { + thrown("failed; getTimeDateFunctions", sqle); + } + } + + static void attributes(final Context context, final List attributes) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(attributes, "attributes is null"); + { + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(attributes) + .doesNotContainNull() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Attribute.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Attribute.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var attribute : attributes) { + MetadataTypeTestUtils.verifyAccessors(attribute); + attribute(context, attribute); + } + } + + static void attribute(final Context context, final Attribute attribute) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(attribute, "attribute is null"); + { + assertThat(attribute.getTypeName()).isNotNull(); + assertThat(attribute.getAttrName()).isNotNull(); + final var dataType = attribute.getDataType(); + assertDoesNotThrow(() -> JDBCType.valueOf(dataType)); + assertThat(attribute.getAttrTypeName()).isNotNull(); + assertDoesNotThrow(() -> Attribute.Nullable.valueOfNullable(attribute.getNullable())); + assertThat(attribute.getIsNullable()).isNotNull(); + } + { + common(attribute); + } + } + + static void bestRowIdentifier(final Context context, final List bestRowIdentifier) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(bestRowIdentifier, "bestRowIdentifier is null"); + assertThat(bestRowIdentifier) + .doesNotHaveDuplicates() + .isSortedAccordingTo(BestRowIdentifier.COMPARING_SCOPE); + assertThat(bestRowIdentifier).isSorted(); + for (final var bestRowIdentifier_ : bestRowIdentifier) { + MetadataTypeTestUtils.verifyAccessors(bestRowIdentifier_); + bestRowIdentifier(context, bestRowIdentifier_); + } + } + + static void bestRowIdentifier(final Context context, final BestRowIdentifier bestRowIdentifier) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(bestRowIdentifier, "bestRowIdentifier is null"); + { + final var scope = bestRowIdentifier.getScope(); + assertDoesNotThrow(() -> BestRowIdentifier.Scope.valueOfScope(scope)); + assertThat(bestRowIdentifier.getColumnName()).isNotNull(); + assertDoesNotThrow(() -> JDBCType.valueOf(bestRowIdentifier.getDataType())); + assertThat(bestRowIdentifier.getTypeName()).isNotNull(); + final int pseudoColumn = bestRowIdentifier.getPseudoColumn(); + assertDoesNotThrow(() -> BestRowIdentifier.PseudoColumn.valueOfPseudoColumn(pseudoColumn)); + } + { + common(bestRowIdentifier); + } + } + + static void catalogs(final Context context, final List catalogs) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(catalogs, "catalogs is null"); + assertThat(catalogs) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Catalog.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Catalog.LEXICOGRAPHIC_ORDER) + ); + for (final var catalog : catalogs) { + MetadataTypeTestUtils.verifyAccessors(catalog); + catalog(context, catalog); + } + } + + static void catalog(final Context context, final Catalog catalog) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(catalog, "catalog is null"); + MetadataTypeTestUtils.verify(catalog); + { + assertThat(catalog.getTableCat()).isNotNull(); + } + common(catalog); + // ----------------------------------------------------------------------------------------------------- schemas + try { + final var schemas = context.getSchemas(catalog, "%"); + schemas(context, schemas); + } catch (final SQLException sqle) { + thrown("failed: getSchemas", sqle); + } + // -------------------------------------------------------------------------------------------------- procedures + final var procedures = context.getProcedures(catalog, "%"); + procedures(context, procedures); + // ------------------------------------------------------------------------------------------------- superTables + try { + final var superTables = context.getSuperTables(catalog.tableCatNonNull(), "%", "%"); + superTables(context, superTables); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // -------------------------------------------------------------------------------------------------- superTypes + final var superTypes = context.getSuperTypes(catalog.getTableCat(), "%", "%"); + superTypes(context, superTypes); + // --------------------------------------------------------------------------------------------- tablePrivileges + if (READ_TABLE_PRIVILEGES) { + try { + final var tablePrivileges = context.getTablePrivileges( + Optional.ofNullable(catalog.getTableCat()).orElse(Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY), + "%", + "%" + ); + tablePrivileges(context, tablePrivileges); + } catch (final SQLException sqle) { + thrown("failed; getTablePrivileges", sqle); + } + } + } + + private static void clientInfoProperties(final Context context, + final List clientInfoProperties) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(clientInfoProperties, "clientInfoProperties is null"); + assertThat(clientInfoProperties) + .doesNotHaveDuplicates(); + for (final var clientInfoProperty : clientInfoProperties) { + MetadataTypeTestUtils.verifyAccessors(clientInfoProperty); + clientInfoProperty(context, clientInfoProperty); + } + } + + private static void clientInfoProperty(final Context context, final ClientInfoProperty clientInfoProperty) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(clientInfoProperty, "clientInfoProperty is null"); + common(clientInfoProperty); + } + + static void columns(final Context context, final List columns) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(columns, "columns is null"); + assertThat(columns).doesNotHaveDuplicates(); + { + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(columns).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Column.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Column.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var column : columns) { + MetadataTypeTestUtils.verifyAccessors(column); + column(context, column); + } + } + + static void column(final Context context, final Column column) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(column, "column is null"); + { + assertThat(column.getTableName()).isNotNull(); + assertThat(column.getColumnName()).isNotNull(); +// assertDoesNotThrow(() -> JDBCType.valueOf(column.getDataType())); + assertThat(column.getOrdinalPosition()).isPositive(); + assertThat(column.getIsNullable()).isNotNull(); + assertThat(column.getIsAutoincrement()).isNotNull(); + assertThat(column.getIsGeneratedcolumn()).isNotNull(); + } + { + final var value = Column.Nullable.valueOfNullable(column.getNullable()); + } + } + + static void columnPrivileges(final Context context, final List columnPrivileges) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(columnPrivileges, "columnPrivileges is null"); + assertThat(columnPrivileges) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.LEXICOGRAPHIC_ORDER) + ); + for (final var columnPrivilege : columnPrivileges) { + MetadataTypeTestUtils.verifyAccessors(columnPrivilege); + columnPrivilege(context, columnPrivilege); + } + } + + static void columnPrivilege(final Context context, final ColumnPrivilege columnPrivilege) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(columnPrivilege, "columnPrivilege is null"); + common(columnPrivilege); + } + + static void crossReference(final Context context, final CrossReference crossReference) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(crossReference, "crossReference is null"); + common(crossReference); + MetadataTypeTestUtils.verify(crossReference); + } + + private static void exportedKeys(final Context context, final List exportedKeys) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(exportedKeys, "exportedKeys is null"); + assertThat(exportedKeys) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ExportedKey.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ExportedKey.LEXICOGRAPHIC_ORDER) + ); + for (final var exportedKey : exportedKeys) { + exportedKey(context, exportedKey); + } + } + + private static void exportedKey(final Context context, final ExportedKey exportedKey) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(exportedKey, "exportedKey is null"); + } + + private static void functions(final Context context, final List functions) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(functions, "functions is null"); + assertThat(functions).doesNotHaveDuplicates().satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Function.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Function.LEXICOGRAPHIC_ORDER) + ); + for (final var function : functions) { + MetadataTypeTestUtils.verifyAccessors(function); + function(context, function); + } + } + + private static void function(final Context context, final Function function) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(function, "function is null"); + common(function); + try { + final var functionColumns = context.getFunctionColumns(function, "%"); + functionColumns(context, function, functionColumns); + } catch (final SQLException sqle) { + thrown("failed; getFunctionColumns", sqle); + } + } + + private static void functionColumns(final Context context, final Function function, + final List functionColumns) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(function, "function is null"); + Objects.requireNonNull(functionColumns, "functionColumns is null"); + { + final var databaseProductNames = Set.of( + DatabaseProductNames.POSTGRE_SQL + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(functionColumns).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(FunctionColumn.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(FunctionColumn.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var functionColumn : functionColumns) { + MetadataTypeTestUtils.verifyAccessors(functionColumn); + functionColumn(context, function, functionColumn); + } + } + + private static void functionColumn(final Context context, final Function function, + final FunctionColumn functionColumn) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(function, "function is null"); + Objects.requireNonNull(functionColumn, "functionColumn is null"); + common(functionColumn); + final var columnType = FunctionColumn.ColumnType.valueOfColumnType(functionColumn.getColumnType()); + } + + static void importedKeys(final Context context, final List importedKeys) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(importedKeys, "importedKeys is null"); + assertThat(importedKeys) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ImportedKey.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ImportedKey.LEXICOGRAPHIC_ORDER) + ); + for (final var importedKey : importedKeys) { + importedKey(context, importedKey); + } + } + + static void importedKey(final Context context, final ImportedKey importedKey) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(importedKey, "importedKey is null"); + MetadataTypeTestUtils.verify(importedKey); + } + + static void indexInfo(final Context context, final IndexInfo indexInfo) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(indexInfo, "indexInfo is null"); + common(indexInfo); + MetadataTypeTestUtils.verify(indexInfo); + } + + private static void procedures(final Context context, final List procedures) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(procedures, "procedures is null"); + { + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(procedures) + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Procedure.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Procedure.LEXICOGRAPHIC_ORDER) + ); + } + } + { + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE + ); + if (!databaseProductNames.contains(databaseProductName)) { +// assertThat(procedures) +// .extracting(Procedure::getProcedureId) +// .satisfiesAnyOf( +// l -> assertThat(l).isSortedAccordingTo(ProcedureId.CASE_INSENSITIVE_ORDER), +// l -> assertThat(l).isSortedAccordingTo(ProcedureId.LEXICOGRAPHIC_ORDER) +// ); + } + } + for (final var procedure : procedures) { + MetadataTypeTestUtils.verifyAccessors(procedure); + procedure(context, procedure); + } + } + + private static void procedure(final Context context, final Procedure procedure) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(procedure, "procedure is null"); + common(procedure); + MetadataTypeTestUtils.verify(procedure); + try { + final var procedureColumns = context.getProcedureColumns(procedure, "%"); + assertThat(procedureColumns).doesNotHaveDuplicates(); + procedureColumns(context, procedureColumns); + } catch (final SQLException sqle) { + thrown("failed; getProcedureColumns", sqle); + } + } + + private static void procedureColumns(final Context context, final List procedureColumns) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(procedureColumns, "procedureColumns is null"); + assertThat(procedureColumns) + .isSortedAccordingTo(ProcedureColumn.CASE_INSENSITIVE_ORDER); + for (final var procedureColumn : procedureColumns) { + MetadataTypeTestUtils.verifyAccessors(procedureColumn); + procedureColumn(context, procedureColumn); + } + } + + private static void procedureColumn(final Context context, final ProcedureColumn procedureColumn) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(procedureColumn, "procedureColumn is null"); + common(procedureColumn); + } + + static void schemas(final Context context, final List schemas) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(schemas, "schemas is null"); + assertThat(schemas) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Schema.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Schema.CASE_INSENSITIVE_ORDER) + ); + for (final var schema : schemas) { + schema(context, schema); + } + } + + static void schema(final Context context, final Schema schema) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(schema, "schema is null"); + MetadataTypeTestUtils.verify(schema); + { + assertThat(schema.getTableSchem()).isNotNull(); + } + common(schema); + // ------------------------------------------------------------------------------------------------- superTables + try { + final var superTables = context.getSuperTables(schema, "%"); + superTables(context, superTables); + } catch (final SQLException sqle) { + thrown("failed; getSuperTables", sqle); + } + // -------------------------------------------------------------------------------------------------- superTypes + try { + final var superTypes = context.getSuperTypes(schema, "%"); + superTypes(context, superTypes); + } catch (final SQLException sqle) { + thrown("failed: getSuperTypes", sqle); + } + // -------------------------------------------------------------------------------------------------- procedures + final var procedures = context.getProcedures(schema, "%"); + procedures(context, procedures); + // --------------------------------------------------------------------------------------------- tablePrivileges + if (READ_TABLE_PRIVILEGES) { + try { + final var tablePrivileges = context.getTablePrivileges(schema, "%"); + tablePrivileges(context, tablePrivileges); + } catch (final SQLException sqle) { + thrown("failed; getTablePrivileges", sqle); + } + } + } + + static void superTypes(final Context context, final List superTypes) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(superTypes, "superTypes is null"); + for (final var superType : superTypes) { + MetadataTypeTestUtils.verifyAccessors(superType); + superType(context, superType); + } + } + + static void superType(final Context context, final SuperType superType) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(superType, "superType is null"); + { + assertThat(superType.getTypeName()).isNotNull(); + assertThat(superType.getSupertypeName()).isNotNull(); + } + { + common(superType); + } + } + + static void tables(final Context context, final List tables) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(tables, "tables is null"); + assertThat(tables) + .doesNotHaveDuplicates(); +// .satisfiesAnyOf( +// l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), +// l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) +// ); + if (!databaseProductName.equals(DatabaseProductNames.MARIA_DB) && + !databaseProductName.equals(DatabaseProductNames.POSTGRE_SQL)) { + // https://jira.mariadb.org/browse/CONJ-1156 + assertThat(tables) + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) + ); + } + for (final var table : tables) { + table(context, table); + } + if (!databaseProductName.equals(DatabaseProductNames.POSTGRE_SQL)) { + for (final var parentTable : tables) { // table 많으면 오래 걸린다. + for (final var foreignTable : tables) { + final var crossReference = context.getCrossReference(parentTable, foreignTable); + assertThat(crossReference) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + cr -> assertThat(cr).isSortedAccordingTo(CrossReference.CASE_INSENSITIVE_ORDER), + cr -> assertThat(cr).isSortedAccordingTo(CrossReference.LEXICOGRAPHIC_ORDER) + ); + for (final var v : crossReference) { + crossReference(context, v); + } + } + } + } + } + + static void table(final Context context, final Table table) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(table, "table is null"); + common(table); + MetadataTypeTestUtils.verify(table); + // ------------------------------------------------------------------------------------------- bestRowIdentifier + for (final var scope : BestRowIdentifier.Scope.values()) { + for (final boolean nullable : new boolean[] {true, false}) { + try { + final var bestRowIdentifier = + context.getBestRowIdentifier(table, scope.fieldValueAsInt(), nullable); + bestRowIdentifier(context, bestRowIdentifier); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } catch (final SQLSyntaxErrorException sqlsee) { // MySQL + log.error("syntax error", sqlsee); + } + } + } + // ----------------------------------------------------------------------------------------------------- columns + try { + final var columns = context.getColumns(table, "%"); + columns(context, columns); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // -------------------------------------------------------------------------------------------- columnPrivileges + if (READ_COLUMN_PRIVILEGES) { + try { + final var columnPrivileges = context.getColumnPrivileges(table, "%"); + assertThat(columnPrivileges).doesNotHaveDuplicates(); + columnPrivileges(context, columnPrivileges); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + } + // ------------------------------------------------------------------------------------------------ exportedKeys + try { + final var exportedKeys = context.getExportedKeys(table); + exportedKeys(context, exportedKeys); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ------------------------------------------------------------------------------------------------ importedKeys + try { + final var importedKeys = context.getImportedKeys(table); + importedKeys(context, importedKeys); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // --------------------------------------------------------------------------------------------------- indexInfo + try { + for (final boolean unique : new boolean[] {true, false}) { + for (final boolean approximate : new boolean[] {true, false}) { + final var indexInfo = context.getIndexInfo(table, unique, approximate); + assertThat(indexInfo) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(IndexInfo.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(IndexInfo.LEXICOGRAPHIC_ORDER) + ); + for (final var v : indexInfo) { + indexInfo(context, v); + } + } + } + } catch (final SQLException sqle) { + thrown("failed; getIndexInfo", sqle); + } + // ------------------------------------------------------------------------------------------------- primaryKeys + try { + final var primaryKeys = context.getPrimaryKeys(table); + primaryKeys(context, primaryKeys); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ----------------------------------------------------------------------------------------------- pseudoColumns + try { + final var pseudoColumns = context.getPseudoColumns(table, "%"); + pseudoColumns(context, pseudoColumns); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // ------------------------------------------------------------------------------------------------- superTables + try { + final var superTables = context.getSuperTables(table); + superTables(context, superTables); + } catch (SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + // --------------------------------------------------------------------------------------------- tablePrivileges + if (READ_TABLE_PRIVILEGES) { + try { + final var tablePrivileges = context.getTablePrivileges(table); + tablePrivileges(context, tablePrivileges); + } catch (final SQLException sqle) { + thrown("failed; getTablePrivileges", sqle); + } + } + // ---------------------------------------------------------------------------------------------- versionColumns + try { + final var versionColumns = context.getVersionColumns(table); + versionColumns(context, versionColumns); + } catch (final SQLException sqle) { + thrown("failed; getVersionColumns", sqle); + } + } + + private static void primaryKeys(final Context context, final List primaryKeys) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(primaryKeys, "primaryKeys is null"); + assertThat(primaryKeys) + .doesNotHaveDuplicates(); + if (!databaseProductName.equals(DatabaseProductNames.POSTGRE_SQL)) { + assertThat(primaryKeys) + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(PrimaryKey.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(PrimaryKey.LEXICOGRAPHIC_ORDER) + ); + } + for (final var primaryKey : primaryKeys) { + primaryKey(context, primaryKey); + } + } + + private static void primaryKey(final Context context, final PrimaryKey primaryKey) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(primaryKey, "primaryKey is null"); + MetadataTypeTestUtils.verify(primaryKey); + } + + private static void pseudoColumns(final Context context, final List pseudoColumns) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(pseudoColumns, "pseudoColumns is null"); + assertThat(pseudoColumns) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(PseudoColumn.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(PseudoColumn.LEXICOGRAPHIC_ORDER) + ); + for (final var pseudoColumn : pseudoColumns) { + pseudoColumn(context, pseudoColumn); + } + } + + static void pseudoColumn(final Context context, final PseudoColumn pseudoColumn) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(pseudoColumn, "pseudoColumn is null"); + common(pseudoColumn); + MetadataTypeTestUtils.verify(pseudoColumn); + } + + static void superTables(final Context context, final List superTables) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(superTables, "superTables is null"); + for (final var superTable : superTables) { + MetadataTypeTestUtils.verifyAccessors(superTable); + superTable(context, superTable); + } + } + + static void superTable(final Context context, final SuperTable superTable) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(superTable, "superTable is null"); + } + + static void tablePrivileges(final Context context, final List tablePrivileges) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(tablePrivileges, "tablePrivileges is null"); + assertThat(tablePrivileges).doesNotHaveDuplicates(); + { + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(tablePrivileges).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(TablePrivilege.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(TablePrivilege.CASE_INSENSITIVE_ORDER) + ); + } + } + for (final var tablePrivilege : tablePrivileges) { + tablePrivilege(context, tablePrivilege); + } + } + + static void tablePrivilege(final Context context, final TablePrivilege tablePrivilege) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(tablePrivilege, "tablePrivilege is null"); + common(tablePrivilege); + MetadataTypeTestUtils.verify(tablePrivilege); + } + + static void tableTypes(final Context context, final List tableTypes) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(tableTypes, "tableTypes is null"); + assertThat(tableTypes) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(TableType.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(TableType.LEXICOGRAPHIC_ORDER) + ); + for (final var tableType : tableTypes) { + MetadataTypeTestUtils.verifyAccessors(tableType); + tableType(context, tableType); + } + } + + static void tableType(final Context context, final TableType tableType) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(tableType, "tableType is null"); + MetadataTypeTestUtils.verify(tableType); + { + assertThat(tableType.getTableType()).isNotNull(); + } + { + common(tableType); + } + } + + static void typeInfo(final Context context, final List typeInfo) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(typeInfo, "typeInfo is null"); + { + final var databaseProductNames = Set.of( + DatabaseProductNames.MY_SQL // https://bugs.mysql.com/bug.php?id=109931 + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(typeInfo).isSortedAccordingTo(TypeInfo.COMPARING_DATA_TYPE); + } + } + for (final var typeInfo_ : typeInfo) { + MetadataTypeTestUtils.verifyAccessors(typeInfo_); + typeInfo(context, typeInfo_); + } + } + + static void typeInfo(final Context context, final TypeInfo typeInfo) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(typeInfo, "typeInfo is null"); + { + assertThat(typeInfo.getTypeName()).isNotNull(); + assertDoesNotThrow(() -> JDBCType.valueOf(typeInfo.getDataType())); + assertDoesNotThrow(() -> TypeInfo.Nullable.valueOfNullable(typeInfo.getNullable())); + assertDoesNotThrow(() -> TypeInfo.Searchable.valueOfSearchable(typeInfo.getSearchable())); + } + { + common(typeInfo); + } + { + final var value = TypeInfo.Nullable.valueOfNullable(typeInfo.getNullable()); + } + { + final var value = TypeInfo.Searchable.valueOfSearchable(typeInfo.getSearchable()); + } + } + + static void udts(final Context context, final List udts) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(udts, "udts is null"); + { + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(udts).doesNotContainNull().satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(UDT.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(UDT.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var udt : udts) { + MetadataTypeTestUtils.verifyAccessors(udt); + udt(context, udt); + } + } + + static void udt(final Context context, final UDT udt) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(udt, "udt is null"); + { + assertThat(udt.getTypeName()).isNotNull(); +// assertThat(udt.getClassName()).isNotNull(); + assertThat(udt.getDataType()).isIn(Types.JAVA_OBJECT, Types.STRUCT, Types.DISTINCT); + assertDoesNotThrow(() -> JDBCType.valueOf(udt.getDataType())); + } + // -------------------------------------------------------------------------------------------------- attributes + try { + final var attributes = context.getAttributes(udt, "%"); + attributes(context, attributes); + } catch (final SQLException sqle) { + log.error("failed; getAttributes({}, {})", udt, "%", sqle); + } + + // -------------------------------------------------------------------------------------------------- superTypes + try { + final var superTypes = context.getSuperTypes(udt); + superTypes(context, superTypes); + } catch (final SQLException sqle) { + log.error("failed; getSuperTypes({})", udt, sqle); + } + } + + static void versionColumns(final Context context, final List versionColumns) + throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(versionColumns, "versionColumns is null"); + assertThat(versionColumns).doesNotHaveDuplicates().satisfiesAnyOf(l -> { + }); + for (final var versionColumn : versionColumns) { + MetadataTypeTestUtils.verifyAccessors(versionColumn); + versionColumn(context, versionColumn); + } + } + + static void versionColumn(final Context context, final VersionColumn versionColumn) throws SQLException { + Objects.requireNonNull(context, "context is null"); + Objects.requireNonNull(versionColumn, "versionColumn is null"); + { + assertDoesNotThrow(() -> JDBCType.valueOf(versionColumn.getDataType())); + assertThat(versionColumn.getTypeName()).isNotNull(); + assertDoesNotThrow(() -> VersionColumn.PseudoColumn.valueOfPseudoColumn(versionColumn.getPseudoColumn())); + } + { + common(versionColumn); + } + MetadataTypeTestUtils.verify(versionColumn); + } + + static void testOrdering(final Context context) throws SQLException { + { + databaseProductName = context.databaseMetaData.getDatabaseProductName(); + info(context); + } + try { + final var attributes = context.getAttributes(null, null, "%", "%"); + assertThat(attributes) + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Attribute.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Attribute.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed; getAttributes", sqle); + } + try { + for (final var scope : BestRowIdentifier.Scope.values()) { + for (final boolean nullable : new boolean[] {true, false}) { + final var bestRowIdentifier = + context.getBestRowIdentifier(null, null, "%", scope.fieldValueAsInt(), nullable); + assertThat(bestRowIdentifier).isSorted(); + assertThat(bestRowIdentifier) + .isSortedAccordingTo(BestRowIdentifier.COMPARING_SCOPE); + } + } + } catch (final SQLException sqle) { + thrown("failed; getBestRowIdentifier", sqle); + } + try { + final var catalogs = context.getCatalogs(); + assertThat(catalogs).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Catalog.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Catalog.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed; getCatalogs", sqle); + } + try { + final var clientInfoProperties = context.getClientInfoProperties(); + final var databaseProductNames = Set.of( + DatabaseProductNames.MARIA_DB + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(clientInfoProperties).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ClientInfoProperty.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ClientInfoProperty.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getCatalogs", sqle); + } + if (READ_COLUMN_PRIVILEGES) { + try { + final var columnPrivileges = context.getColumnPrivileges(null, null, "%", "%"); + assertThat(columnPrivileges).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed; getColumnPrivileges", sqle); + } + } + try { + final var columns = context.getColumns(null, null, "%", "%"); + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE, + DatabaseProductNames.MARIA_DB + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(columns).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Column.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Column.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getColumns", sqle); + } + try { + final var functionColumns = context.getFunctionColumns(null, null, "%", "%"); + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(functionColumns).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(FunctionColumn.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(FunctionColumn.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getFunctionColumns", sqle); + } + try { + final var functions = context.getFunctions(null, null, "%"); + assertThat(functions).doesNotHaveDuplicates(); + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(functions).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Function.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Function.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getFunctionColumns", sqle); + } + try { + final var procedureColumns = context.getProcedureColumns(null, null, "%", "%"); + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(procedureColumns).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ProcedureColumn.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ProcedureColumn.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getProcedureColumns", sqle); + } + try { + final var procedures = context.getProcedures(null, null, "%"); + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(procedures).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Procedure.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Procedure.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getProcedureColumns", sqle); + } + try { + final var schemas = context.getSchemas((String) null, "%"); + final var databaseProductNames = Set.of( + "" + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(schemas).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Schema.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Schema.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getSchemas", sqle); + } + try { + final var superTables = context.getSuperTables(null, "%", "%"); + assertThat(superTables).doesNotHaveDuplicates(); + } catch (final SQLFeatureNotSupportedException sqlfnse) { + log.error("not supported", sqlfnse); + } + try { + final var superTypes = context.getSuperTypes(null, "%", "%"); + assertThat(superTypes).doesNotHaveDuplicates(); + } catch (final SQLException sqle) { + thrown("failed; getSuperTypes", sqle); + } + if (READ_TABLE_PRIVILEGES) { + try { + final var tablePrivileges = context.getTablePrivileges(null, null, "%"); + assertThat(tablePrivileges).doesNotHaveDuplicates(); + assertThat(tablePrivileges).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(TablePrivilege.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(TablePrivilege.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed; getTablePrivileges", sqle); + } + } + try { + final var tables = context.getTables(null, null, "%", null); + assertThat(tables).doesNotHaveDuplicates(); + { + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE + , DatabaseProductNames.MARIA_DB + , DatabaseProductNames.POSTGRE_SQL + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(tables).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var table : tables) { + try { + for (final var scope : BestRowIdentifier.Scope.values()) { + for (final boolean nullable : new boolean[] {true, false}) { + final var bestRowIdentifier = + context.getBestRowIdentifier(table, scope.fieldValueAsInt(), nullable); + assertThat(bestRowIdentifier) + .doesNotHaveDuplicates() + .isSortedAccordingTo(BestRowIdentifier.COMPARING_SCOPE); + if (false && !bestRowIdentifier.isEmpty()) { // 'actual...' + assertThat(bestRowIdentifier) + .extracting(BestRowIdentifier::getScope) + .containsOnly(scope.fieldValueAsInt()); + } + } + } + } catch (final SQLException sqle) { + thrown("failed: getBestRowIdentifier", sqle); + } + if (READ_COLUMN_PRIVILEGES) { + try { + final var columnPrivileges = context.getColumnPrivileges(table, "%"); + assertThat(columnPrivileges) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed: getColumnPrivileges", sqle); + } + } + try { + final var exportedKeys = context.getExportedKeys(table); + assertThat(exportedKeys) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ExportedKey.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ExportedKey.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed: getExportedKeys", sqle); + } + try { + final var importedKeys = context.getImportedKeys(table); + assertThat(importedKeys) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(ImportedKey.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(ImportedKey.LEXICOGRAPHIC_ORDER) + ); + } catch (final SQLException sqle) { + thrown("failed: getImportedKeys", sqle); + } + try { + for (final boolean unique : new boolean[] {false, true}) { + for (final boolean approximate : new boolean[] {false, true}) { + final var indexInfo = context.getIndexInfo(table, unique, approximate); + assertThat(indexInfo) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(IndexInfo.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(IndexInfo.LEXICOGRAPHIC_ORDER) + ); + } + } + } catch (final SQLException sqle) { + thrown("failed: getIndexInfo", sqle); + } + try { + final var primaryKeys = context.getPrimaryKeys(table); + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE + , DatabaseProductNames.MY_SQL + , DatabaseProductNames.POSTGRE_SQL + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(primaryKeys) + .doesNotHaveDuplicates() + .satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(PrimaryKey.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(PrimaryKey.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed: getPrimaryKeys", sqle); + } + try { + final var versionColumns = context.getVersionColumns(table); // unordered + } catch (final SQLException sqle) { + thrown("failed: getVersionColumns", sqle); + } + } + } catch (final SQLException sqle) { + thrown("failed; getTables", sqle); + } + try { + final var typeInfo = context.getTypeInfo(); + assertThat(typeInfo).doesNotHaveDuplicates(); + final var databaseProductNames = Set.of( + DatabaseProductNames.H2 + , DatabaseProductNames.HSQL_DATABASE_ENGINE + , DatabaseProductNames.MY_SQL + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(typeInfo).isSortedAccordingTo(TypeInfo.COMPARING_DATA_TYPE); + } + } catch (final SQLException sqle) { + thrown("failed; getTypeInfo", sqle); + } + try { + final var udts = context.getUDTs(null, null, "%", null); + assertThat(udts).doesNotHaveDuplicates(); + final var databaseProductNames = Set.of( +// DatabaseProductNames.H2, +// DatabaseProductNames.HSQL_DATABASE_ENGINE + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(udts).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(UDT.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(UDT.LEXICOGRAPHIC_ORDER) + ); + } + } catch (final SQLException sqle) { + thrown("failed; getTypeInfo", sqle); + } + } + + static List
getTables__(final Context context, final String catalog, final String schemaPattern, + final String tableNamePattern, final String[] types) + throws SQLException { + { + info(context); + } + final var tables = context.getTables(catalog, schemaPattern, tableNamePattern, types); + assertThat(tables).doesNotHaveDuplicates(); + { + final var databaseProductNames = Set.of( + // https://sourceforge.net/p/hsqldb/bugs/1672/ + DatabaseProductNames.HSQL_DATABASE_ENGINE + , DatabaseProductNames.MARIA_DB + , DatabaseProductNames.POSTGRE_SQL + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(tables).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var table : tables) { + common(table); + } + return tables; + } + + static List getColumns__(final Context context, final String catalog, final String schemaPattern, + final String tableNamePattern, final String columnNamePattern) + throws SQLException { + { + info(context); + } + final var columns = context.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); + assertThat(columns).doesNotHaveDuplicates(); + { + final var databaseProductNames = Set.of( + DatabaseProductNames.HSQL_DATABASE_ENGINE, + DatabaseProductNames.MARIA_DB + ); + if (!databaseProductNames.contains(databaseProductName)) { + assertThat(columns).satisfiesAnyOf( + l -> assertThat(l).isSortedAccordingTo(Column.CASE_INSENSITIVE_ORDER), + l -> assertThat(l).isSortedAccordingTo(Column.LEXICOGRAPHIC_ORDER) + ); + } + } + for (final var column : columns) { + common(column); + } + return columns; + } + private ContextTestUtils() { throw new AssertionError("instantiation is not allowed"); } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ContextTests.java b/src/test/java/com/github/jinahya/database/metadata/bind/ContextTests.java deleted file mode 100644 index d427d7cb..00000000 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ContextTests.java +++ /dev/null @@ -1,1397 +0,0 @@ -package com.github.jinahya.database.metadata.bind; - -/*- - * #%L - * database-metadata-bind - * %% - * Copyright (C) 2011 - 2019 Jinahya, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import com.github.jinahya.database.metadata.bind.VersionColumn.PseudoColumn; -import lombok.extern.slf4j.Slf4j; -import org.junit.platform.commons.util.ReflectionUtils; - -import java.sql.JDBCType; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.Types; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; - -/** - * An abstract test class for in-memory databases. - * - * @author Jin Kwon <onacit at gmail.com> - */ -@Slf4j -final class ContextTests { - - private static final boolean READ_TABLE_PRIVILEGES = false; - - private static final boolean READ_COLUMN_PRIVILEGES = false; - - static void info(final Context context) throws SQLException { - Objects.requireNonNull(context, "context is null"); - databaseProductName = context.databaseMetaData.getDatabaseProductName(); - log.info("databaseProductName: {}", databaseProductName); - log.info("databaseProductVersion: {}", context.databaseMetaData.getDatabaseProductVersion()); - log.info("databaseMajorVersion: {}", context.databaseMetaData.getDatabaseMajorVersion()); - log.info("databaseMinorVersion: {}", context.databaseMetaData.getDatabaseMinorVersion()); - log.info("driverName: {}", context.databaseMetaData.getDriverName()); - log.info("driverVersion: {}", context.databaseMetaData.getDriverVersion()); - log.info("driverMajorVersion: {}", context.databaseMetaData.getDriverMajorVersion()); - log.info("driverMinorVersion: {}", context.databaseMetaData.getDriverMinorVersion()); - log.info("catalogSeparator: {}", context.databaseMetaData.getCatalogSeparator()); - log.info("catalogTerm: {}", context.databaseMetaData.getCatalogTerm()); - log.info("schemaTerm: {}", context.databaseMetaData.getSchemaTerm()); - } - - private static T common(final T value) { - Objects.requireNonNull(value, "value is null"); - { - final var string = value.toString(); - } - { - final var hashCode = value.hashCode(); - } - if (value instanceof MetadataType) { - final var unmappedValues = ((MetadataType) value).getUnmappedValues(); - if (!unmappedValues.isEmpty()) { - log.warn("unmapped values of {}: {}", value.getClass().getSimpleName(), unmappedValues); - } - } - // .toBuilder().build() - ReflectionUtils.findMethod(value.getClass(), "toBuilder") - .map(m -> { - try { - return m.invoke(value); - } catch (final ReflectiveOperationException roe) { - throw new RuntimeException(roe); - } - }) - .flatMap(b -> ReflectionUtils.findMethod(b.getClass(), "build") - .map(m -> { - try { - return m.invoke(b); - } catch (final ReflectiveOperationException row) { - throw new RuntimeException(row); - } - }) - ); - return value; - } - - private static void thrown(final String message, final Throwable throwable) { - Objects.requireNonNull(message, "message is null"); - Objects.requireNonNull(throwable, "throwable is null"); - if (throwable instanceof SQLFeatureNotSupportedException) { - return; - } - log.error("{}", message, throwable); - } - - private static String databaseProductName; - - static void test(final Context context) throws SQLException { - Objects.requireNonNull(context, "context is null"); - { - databaseProductName = context.databaseMetaData.getDatabaseProductName(); - info(context); - } - { - final List catalogs; - try { - catalogs = context.getCatalogs(); - if (catalogs.isEmpty()) { - catalogs.add(Catalog.newVirtualInstance()); - } - catalogs(context, catalogs); - } catch (final SQLException sqle) { - thrown("failed; getCatalogs", sqle); - } - } - try { - final var clientInfoProperties = context.getClientInfoProperties(); - clientInfoProperties(context, clientInfoProperties); - } catch (final SQLException sqle) { - thrown("failed; getClientInfoProperties", sqle); - } - try { - final var functions = context.getFunctions(null, null, "%"); - functions(context, functions); - } catch (final SQLException sqle) { - thrown("failed; getFunctions", sqle); - } - try { - final var procedures = context.getProcedures(null, null, "%"); - procedures(context, procedures); - } catch (final SQLException sqle) { - thrown("failed; getProcedures", sqle); - } - try { - final var schemas = context.getSchemas(); - if (schemas.isEmpty()) { - schemas.add(Schema.newVirtualInstance()); - } - schemas(context, schemas); - } catch (final SQLException sqle) { - thrown("failed; getSchemas", sqle); - } - try { - final var schemas = context.getSchemas((String) null, null); - if (schemas.isEmpty()) { - schemas.add(Schema.newVirtualInstance()); - } - schemas(context, schemas); - } catch (final SQLException sqle) { - thrown("failed; getSchemas", sqle); - } - try { - final var tableTypes = context.getTableTypes(); - tableTypes(context, tableTypes); - } catch (final SQLException sqle) { - thrown("failed; getTableTypes", sqle); - } - try { - final var tables = context.getTables(null, null, "%", null); - tables(context, tables); - } catch (final SQLException sqle) { - thrown("failed; getTables", sqle); - } - try { - final var typeInfo = context.getTypeInfo(); - typeInfo(context, typeInfo); - } catch (final SQLException sqle) { - thrown("failed; getTypeInfo", sqle); - } - try { - final var udts = context.getUDTs(null, null, "%", null); - udts(context, udts); - } catch (final SQLException sqle) { - thrown("failed; getUDTs", sqle); - } - try { - final Set NumericFunctions = context.getNumericFunctions(); - log.debug("numeric functions: {}", NumericFunctions); - } catch (final SQLException sqle) { - thrown("failed; getNumericFunctions", sqle); - } - try { - final Set SQLKeywords = context.getSQLKeywords(); - log.debug("sql keywords: {}", SQLKeywords); - } catch (final SQLException sqle) { - thrown("failed; getSQLKeywords", sqle); - } - try { - final Set results = context.getStringFunctions(); - log.debug("string functions: {}", results); - } catch (final SQLException sqle) { - thrown("failed; getStringFunctions", sqle); - } - try { - final Set results = context.getSystemFunctions(); - log.debug("system functions: {}", results); - } catch (final SQLException sqle) { - thrown("failed; getSystemFunctions", sqle); - } - try { - final Set results = context.getTimeDateFunctions(); - log.debug("time date functions: {}", results); - } catch (final SQLException sqle) { - thrown("failed; getTimeDateFunctions", sqle); - } - } - - static void attributes(final Context context, final List attributes) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(attributes, "attributes is null"); - { - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(attributes) - .doesNotContainNull() - .satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Attribute.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Attribute.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var attribute : attributes) { - attribute(context, attribute); - } - } - - static void attribute(final Context context, final Attribute attribute) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(attribute, "attribute is null"); - { - assertThat(attribute.getTypeName()).isNotNull(); - assertThat(attribute.getAttrName()).isNotNull(); - final var dataType = attribute.getDataType(); - assertDoesNotThrow(() -> JDBCType.valueOf(dataType)); - assertThat(attribute.getAttrTypeName()).isNotNull(); - assertDoesNotThrow(() -> Attribute.Nullable.valueOfNullable(attribute.getNullable())); - assertThat(attribute.getIsNullable()).isNotNull(); - } - { - common(attribute); - } - } - - static void bestRowIdentifier(final Context context, final List bestRowIdentifier) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(bestRowIdentifier, "bestRowIdentifier is null"); - assertThat(bestRowIdentifier).isSortedAccordingTo(BestRowIdentifier.COMPARING_SCOPE); - assertThat(bestRowIdentifier).isSorted(); - for (final var bestRowIdentifier_ : bestRowIdentifier) { - bestRowIdentifier(context, bestRowIdentifier_); - } - } - - static void bestRowIdentifier(final Context context, final BestRowIdentifier bestRowIdentifier) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(bestRowIdentifier, "bestRowIdentifier is null"); - { - final var scope = bestRowIdentifier.getScope(); - assertDoesNotThrow(() -> BestRowIdentifier.Scope.valueOfScope(scope)); - assertThat(bestRowIdentifier.getColumnName()).isNotNull(); - assertDoesNotThrow(() -> JDBCType.valueOf(bestRowIdentifier.getDataType())); - assertThat(bestRowIdentifier.getTypeName()).isNotNull(); - final int pseudoColumn = bestRowIdentifier.getPseudoColumn(); - assertDoesNotThrow(() -> BestRowIdentifier.PseudoColumn.valueOfPseudoColumn(pseudoColumn)); - } - { - common(bestRowIdentifier); - } - } - - static void catalogs(final Context context, final List catalogs) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(catalogs, "catalogs is null"); - assertThat(catalogs).doesNotHaveDuplicates().satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Catalog.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Catalog.LEXICOGRAPHIC_ORDER) - ); - for (final var catalog : catalogs) { - catalog(context, catalog); - } - } - - static void catalog(final Context context, final Catalog catalog) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(catalog, "catalog is null"); - { - assertThat(catalog.getTableCat()).isNotNull(); - } - common(catalog); - try { - final var schemas = context.getSchemas(catalog, "%"); - { - final var databaseProductNames = Set.of( - // https://sourceforge.net/p/hsqldb/bugs/1671/ - DatabaseProductNames.HSQL_DATABASE_ENGINE - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(schemas).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Schema.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Schema.LEXICOGRAPHIC_ORDER) - ); - } - } - schemas(context, schemas); - } catch (final SQLException sqle) { - thrown("failed: getSchemas", sqle); - } - if (READ_TABLE_PRIVILEGES) { - try { - final var tablePrivileges = context.getTablePrivileges( - Optional.ofNullable(catalog.getTableCat()).orElse(Catalog.COLUMN_VALUE_TABLE_CAT_EMPTY), - "%", - "%" - ); - tablePrivileges(context, tablePrivileges); - } catch (final SQLException sqle) { - thrown("failed; getTablePrivileges", sqle); - } - } - } - - private static void clientInfoProperties(final Context context, - final List clientInfoProperties) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(clientInfoProperties, "clientInfoProperties is null"); - assertThat(clientInfoProperties) - .doesNotHaveDuplicates(); - for (final var clientInfoProperty : clientInfoProperties) { - clientInfoProperty(context, clientInfoProperty); - } - } - - private static void clientInfoProperty(final Context context, final ClientInfoProperty clientInfoProperty) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(clientInfoProperty, "clientInfoProperty is null"); - common(clientInfoProperty); - } - - static void columns(final Context context, final List columns) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(columns, "columns is null"); - assertThat(columns).doesNotHaveDuplicates(); - { - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(columns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Column.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Column.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var column : columns) { - column(context, column); - } - } - - static void column(final Context context, final Column column) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(column, "column is null"); - { - assertThat(column.getTableName()).isNotNull(); - assertThat(column.getColumnName()).isNotNull(); -// assertDoesNotThrow(() -> JDBCType.valueOf(column.getDataType())); - assertThat(column.getOrdinalPosition()).isPositive(); - assertThat(column.getIsNullable()).isNotNull(); - assertThat(column.getIsAutoincrement()).isNotNull(); - assertThat(column.getIsGeneratedcolumn()).isNotNull(); - } - { - final var value = Column.Nullable.valueOfNullable(column.getNullable()); - } - } - - static void columnPrivileges(final Context context, final List columnPrivileges) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(columnPrivileges, "columnPrivileges is null"); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.POSTGRE_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(columnPrivileges).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var columnPrivilege : columnPrivileges) { - columnPrivilege(context, columnPrivilege); - } - } - - static void columnPrivilege(final Context context, final ColumnPrivilege columnPrivilege) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(columnPrivilege, "columnPrivilege is null"); - common(columnPrivilege); - } - - static void crossReference(final Context context, List crossReference) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(crossReference, "crossReference is null"); - assertThat(crossReference).satisfiesAnyOf( - cr -> assertThat(cr).isSortedAccordingTo(CrossReference.CASE_INSENSITIVE_ORDER), - cr -> assertThat(cr).isSortedAccordingTo(CrossReference.LEXICOGRAPHIC_ORDER) - ); - for (final var crossReference_ : crossReference) { - crossReference(context, crossReference_); - } - } - - static void crossReference(final Context context, final CrossReference crossReference) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(crossReference, "crossReference is null"); - common(crossReference); - } - - static void exportedKeys(final Context context, final List exportedKeys) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(exportedKeys, "exportedKeys is null"); - { - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(exportedKeys).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ExportedKey.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ExportedKey.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var exportedKey : exportedKeys) { - exportedKey(context, exportedKey); - } - } - - private static void exportedKey(final Context context, final ExportedKey exportedKey) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(exportedKey, "exportedKey is null"); - common(exportedKey); - } - - private static void functions(final Context context, final List functions) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(functions, "functions is null"); - assertThat(functions).doesNotHaveDuplicates().satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Function.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Function.LEXICOGRAPHIC_ORDER) - ); - for (final var function : functions) { - function(context, function); - } - } - - private static void function(final Context context, final Function function) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(function, "function is null"); - common(function); - try { - final var functionColumns = context.getFunctionColumns(function, "%"); - functionColumns(context, function, functionColumns); - } catch (final SQLException sqle) { - thrown("failed; getFunctionColumns", sqle); - } - } - - private static void functionColumns(final Context context, final Function function, - final List functionColumns) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(function, "function is null"); - Objects.requireNonNull(functionColumns, "functionColumns is null"); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.POSTGRE_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(functionColumns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(FunctionColumn.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(FunctionColumn.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var functionColumn : functionColumns) { - functionColumn(context, function, functionColumn); - } - } - - private static void functionColumn(final Context context, final Function function, - final FunctionColumn functionColumn) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(function, "function is null"); - Objects.requireNonNull(functionColumn, "functionColumn is null"); - common(functionColumn); - final var columnType = FunctionColumn.ColumnType.valueOfColumnType(functionColumn.getColumnType()); - } - - static void importedKeys(final Context context, final List importedKeys) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(importedKeys, "importedKeys is null"); - { - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(importedKeys).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ImportedKey.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ImportedKey.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var importedKey : importedKeys) { - importedKey(context, importedKey); - } - } - - static void importedKey(final Context context, final ImportedKey importedKey) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(importedKey, "importedKey is null"); - common(importedKey); - } - - static void indexInfo(final Context context, final List indexInfo) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(indexInfo, "indexInfo is null"); - { - final var databaseProductNames = Set.of( - "" - // https://bugs.mysql.com/bug.php?id=109803 -// DatabaseProductNames.MY_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(indexInfo).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(IndexInfo.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(IndexInfo.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var indexInfo_ : indexInfo) { - indexInfo(context, indexInfo_); - } - } - - static void indexInfo(final Context context, final IndexInfo indexInfo) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(indexInfo, "indexInfo is null"); - common(indexInfo); - } - - private static void procedures(final Context context, final List procedures) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(procedures, "procedures is null"); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(procedures) - .satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Procedure.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Procedure.LEXICOGRAPHIC_ORDER) - ); - } - } - { - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE - ); - if (!databaseProductNames.contains(databaseProductName)) { -// assertThat(procedures) -// .extracting(Procedure::getProcedureId) -// .satisfiesAnyOf( -// l -> assertThat(l).isSortedAccordingTo(ProcedureId.CASE_INSENSITIVE_ORDER), -// l -> assertThat(l).isSortedAccordingTo(ProcedureId.LEXICOGRAPHIC_ORDER) -// ); - } - } - for (final var procedure : procedures) { - procedure(context, procedure); - } - } - - private static void procedure(final Context context, final Procedure procedure) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(procedure, "procedure is null"); - common(procedure); - try { - final var procedureColumns = context.getProcedureColumns(procedure, "%"); - assertThat(procedureColumns).doesNotHaveDuplicates(); - procedureColumns(context, procedureColumns); - } catch (final SQLException sqle) { - thrown("failed; getProcedureColumns", sqle); - } - } - - private static void procedureColumns(final Context context, final List procedureColumns) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(procedureColumns, "procedureColumns is null"); - assertThat(procedureColumns) - .isSortedAccordingTo(ProcedureColumn.CASE_INSENSITIVE_ORDER); - for (final var procedureColumn : procedureColumns) { - procedureColumn(context, procedureColumn); - } - } - - private static void procedureColumn(final Context context, final ProcedureColumn procedureColumn) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(procedureColumn, "procedureColumn is null"); - common(procedureColumn); - } - - static void schemas(final Context context, final List schemas) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(schemas, "schemas is null"); - for (final var schema : schemas) { - schema(context, schema); - } - } - - static void schema(final Context context, final Schema schema) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(schema, "schema is null"); - { - assertThat(schema.getTableSchem()).isNotNull(); - } - common(schema); - try { - final var superTables = context.getSuperTables(schema, "%"); - superTables(context, superTables); - } catch (final SQLException sqle) { - thrown("failed; getSuperTables", sqle); - } - try { - final var superTypes = context.getSuperTypes(schema, "%"); - superTypes(context, superTypes); - } catch (final SQLException sqle) { - thrown("failed: getSuperTypes", sqle); - } - if (READ_TABLE_PRIVILEGES) { - try { - final var tablePrivileges = context.getTablePrivileges(schema, "%"); - tablePrivileges(context, tablePrivileges); - } catch (final SQLException sqle) { - thrown("failed; getTablePrivileges", sqle); - } - } - } - - static void superTypes(final Context context, final List superTypes) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(superTypes, "superTypes is null"); - for (final var superType : superTypes) { - superType(context, superType); - } - } - - static void superType(final Context context, final SuperType superType) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(superType, "superType is null"); - { - assertThat(superType.getTypeName()).isNotNull(); - assertThat(superType.getSupertypeName()).isNotNull(); - } - { - common(superType); - } - } - - static void tables(final Context context, final List tables) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(tables, "tables is null"); - { - final var databaseProductNames = Set.of( - // https://sourceforge.net/p/hsqldb/bugs/1672/ - DatabaseProductNames.HSQL_DATABASE_ENGINE, - DatabaseProductNames.MARIA_DB, - DatabaseProductNames.POSTGRE_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(tables).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var table : tables) { - table(context, table); - } - for (int i = 0; i < 10 && i < tables.size(); i++) { // table 아 많으면 오래 걸린다. - final var parent = tables.get(i); - for (final var fktable : tables) { - final var crossReference = context.getCrossReference( - parent.getTableCat(), parent.getTableSchem(), parent.getTableName(), - fktable.getTableCat(), fktable.getTableSchem(), fktable.getTableName()); - crossReference(context, crossReference); - } - } - } - - static void table(final Context context, final Table table) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(table, "table is null"); - { - assertThat(table.getTableName()).isNotNull(); -// assertThat(table.getTableType()).isNotNull(); - } - common(table); - try { - for (final var scope : BestRowIdentifier.Scope.values()) { - for (final boolean nullable : new boolean[] {true, false}) { - final var bestRowIdentifier = - context.getBestRowIdentifier(table, scope.fieldValueAsInt(), nullable); - bestRowIdentifier(context, bestRowIdentifier); - } - } - } catch (final SQLException sqle) { - thrown("failed; getBestRowIdentifier", sqle); - } - try { - final var columns = context.getColumns(table, "%"); - columns(context, columns); - } catch (final SQLException sqle) { - thrown("failed; getColumns", sqle); - } - if (READ_COLUMN_PRIVILEGES) { - try { - final var columnPrivileges = context.getColumnPrivileges(table, "%"); - assertThat(columnPrivileges).doesNotHaveDuplicates(); - columnPrivileges(context, columnPrivileges); - } catch (final SQLException sqle) { - thrown("failed; getColumnPrivileges", sqle); - } - } - try { - final var exportedKeys = context.getExportedKeys(table); - assertThat(exportedKeys).doesNotHaveDuplicates(); - exportedKeys(context, exportedKeys); - } catch (final SQLException sqle) { - thrown("failed; getExportedKeys", sqle); - } - try { - final var importedKeys = context.getImportedKeys(table); - assertThat(importedKeys).doesNotHaveDuplicates(); - importedKeys(context, importedKeys); - } catch (final SQLException sqle) { - thrown("failed; getImportedKeys", sqle); - } - try { - for (final boolean unique : new boolean[] {true, false}) { - for (final boolean approximate : new boolean[] {true, false}) { - final var indexInfo = context.getIndexInfo(table, unique, approximate); - indexInfo(context, indexInfo); - } - } - } catch (final SQLException sqle) { - thrown("failed; getIndexInfo", sqle); - } - try { - final var primaryKeys = context.getPrimaryKeys(table); - assertThat(primaryKeys).doesNotHaveDuplicates(); - primaryKeys(context, primaryKeys); - } catch (final SQLException sqle) { - thrown("failed; getPrimaryKeys", sqle); - } - try { - final var pseudoColumns = context.getPseudoColumns(table, "%"); - assertThat(pseudoColumns).doesNotHaveDuplicates(); - pseudoColumns(context, pseudoColumns); - } catch (final SQLException sqle) { - thrown("failed; getPseudoColumns", sqle); - } - if (READ_TABLE_PRIVILEGES) { - try { - final var tablePrivileges = context.getTablePrivileges(table); - tablePrivileges(context, tablePrivileges); - } catch (final SQLException sqle) { - thrown("failed; getTablePrivileges", sqle); - } - } - try { - final var versionColumns = context.getVersionColumns(table); - assertThat(versionColumns).doesNotHaveDuplicates(); - versionColumns(context, versionColumns); - } catch (final SQLException sqle) { - thrown("failed; getVersionColumns", sqle); - } - } - - static void primaryKeys(final Context context, final List primaryKeys) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(primaryKeys, "primaryKeys is null"); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE // https://sourceforge.net/p/hsqldb/bugs/1673/ - , DatabaseProductNames.POSTGRE_SQL - , DatabaseProductNames.MY_SQL // https://bugs.mysql.com/bug.php?id=109808 - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(primaryKeys).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(PrimaryKey.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(PrimaryKey.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var primaryKey : primaryKeys) { - primaryKey(context, primaryKey); - } - } - - private static void primaryKey(final Context context, final PrimaryKey primaryKey) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(primaryKey, "primaryKey is null"); - common(primaryKey); - } - - static void pseudoColumns(final Context context, - final List pseudoColumns) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(pseudoColumns, "pseudoColumns is null"); - assertThat(pseudoColumns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo( - com.github.jinahya.database.metadata.bind.PseudoColumn.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo( - com.github.jinahya.database.metadata.bind.PseudoColumn.LEXICOGRAPHIC_ORDER) - ); - for (final var pseudoColumn : pseudoColumns) { - pseudoColumn(context, pseudoColumn); - } - } - - static void pseudoColumn(final Context context, - final com.github.jinahya.database.metadata.bind.PseudoColumn pseudoColumn) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(pseudoColumn, "pseudoColumn is null"); - common(pseudoColumn); - } - - static void superTables(final Context context, final List superTables) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(superTables, "superTables is null"); - for (final var superTable : superTables) { - superTable(context, superTable); - } - } - - static void superTable(final Context context, final SuperTable superTable) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(superTable, "superTable is null"); - } - - static void tablePrivileges(final Context context, final List tablePrivileges) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(tablePrivileges, "tablePrivileges is null"); - if (!tablePrivileges.isEmpty()) { -// log.debug("tablePrivileges: {}", tablePrivileges); - } - { - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(tablePrivileges).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(TablePrivilege.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(TablePrivilege.CASE_INSENSITIVE_ORDER) - ); - } - } - for (final var tablePrivilege : tablePrivileges) { - tablePrivilege(context, tablePrivilege); - } - } - - static void tablePrivilege(final Context context, final TablePrivilege tablePrivilege) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(tablePrivilege, "tablePrivilege is null"); - common(tablePrivilege); - } - - static void tableTypes(final Context context, final List tableTypes) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(tableTypes, "tableTypes is null"); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.MARIA_DB // https://jira.mariadb.org/browse/CONJ-1049 - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(tableTypes).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(TableType.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(TableType.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var tableType : tableTypes) { - tableType(context, tableType); - } - } - - static void tableType(final Context context, final TableType tableType) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(tableType, "tableType is null"); - { - assertThat(tableType.getTableType()).isNotNull(); - } - { - common(tableType); - } - } - - static void typeInfo(final Context context, final List typeInfo) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(typeInfo, "typeInfo is null"); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.MY_SQL // https://bugs.mysql.com/bug.php?id=109931 - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(typeInfo).isSortedAccordingTo(TypeInfo.COMPARING_DATA_TYPE); - } - } - for (final var typeInfo_ : typeInfo) { - typeInfo(context, typeInfo_); - } - } - - static void typeInfo(final Context context, final TypeInfo typeInfo) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(typeInfo, "typeInfo is null"); - { - assertThat(typeInfo.getTypeName()).isNotNull(); - assertDoesNotThrow(() -> JDBCType.valueOf(typeInfo.getDataType())); - assertDoesNotThrow(() -> TypeInfo.Nullable.valueOfNullable(typeInfo.getNullable())); - assertDoesNotThrow(() -> TypeInfo.Searchable.valueOfSearchable(typeInfo.getSearchable())); - } - { - common(typeInfo); - } - { - final var value = TypeInfo.Nullable.valueOfNullable(typeInfo.getNullable()); - } - { - final var value = TypeInfo.Searchable.valueOfSearchable(typeInfo.getSearchable()); - } - } - - static void udts(final Context context, final List udts) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(udts, "udts is null"); - { - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(udts).doesNotContainNull().satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(UDT.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(UDT.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var udt : udts) { - udt(context, udt); - } - } - - static void udt(final Context context, final UDT udt) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(udt, "udt is null"); - { - assertThat(udt.getTypeName()).isNotNull(); -// assertThat(udt.getClassName()).isNotNull(); - assertThat(udt.getDataType()).isIn(Types.JAVA_OBJECT, Types.STRUCT, Types.DISTINCT); - assertDoesNotThrow(() -> JDBCType.valueOf(udt.getDataType())); - } - try { - final var attributes = context.getAttributes(udt, "%"); - attributes(context, attributes); - } catch (final SQLException sqle) { - thrown("failed; getAttributes", sqle); - } - } - - static void versionColumns(final Context context, final List versionColumns) - throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(versionColumns, "versionColumns is null"); - for (final var versionColumn : versionColumns) { - versionColumn(context, versionColumn); - } - } - - static void versionColumn(final Context context, final VersionColumn versionColumn) throws SQLException { - Objects.requireNonNull(context, "context is null"); - Objects.requireNonNull(versionColumn, "versionColumn is null"); - { - assertDoesNotThrow(() -> JDBCType.valueOf(versionColumn.getDataType())); - assertThat(versionColumn.getTypeName()).isNotNull(); - assertDoesNotThrow(() -> PseudoColumn.valueOfPseudoColumn(versionColumn.getPseudoColumn())); - } - { - common(versionColumn); - } - } - - static void testOrdering(final Context context) throws SQLException { - { - databaseProductName = context.databaseMetaData.getDatabaseProductName(); - info(context); - } - try { - final var attributes = context.getAttributes(null, null, "%", "%"); - assertThat(attributes) - .satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Attribute.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Attribute.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed; getAttributes", sqle); - } - try { - for (final var scope : BestRowIdentifier.Scope.values()) { - for (final boolean nullable : new boolean[] {true, false}) { - final var bestRowIdentifier = - context.getBestRowIdentifier(null, null, "%", scope.fieldValueAsInt(), nullable); - assertThat(bestRowIdentifier).isSorted(); - assertThat(bestRowIdentifier) - .isSortedAccordingTo(BestRowIdentifier.COMPARING_SCOPE); - } - } - } catch (final SQLException sqle) { - thrown("failed; getBestRowIdentifier", sqle); - } - try { - final var catalogs = context.getCatalogs(); - assertThat(catalogs).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Catalog.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Catalog.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed; getCatalogs", sqle); - } - try { - final var clientInfoProperties = context.getClientInfoProperties(); - final var databaseProductNames = Set.of( - DatabaseProductNames.MARIA_DB - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(clientInfoProperties).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ClientInfoProperty.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ClientInfoProperty.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getCatalogs", sqle); - } - if (READ_COLUMN_PRIVILEGES) { - try { - final var columnPrivileges = context.getColumnPrivileges(null, null, "%", "%"); - assertThat(columnPrivileges).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed; getColumnPrivileges", sqle); - } - } - try { - final var columns = context.getColumns(null, null, "%", "%"); - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE, - DatabaseProductNames.MARIA_DB - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(columns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Column.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Column.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getColumns", sqle); - } - try { - final var functionColumns = context.getFunctionColumns(null, null, "%", "%"); - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(functionColumns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(FunctionColumn.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(FunctionColumn.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getFunctionColumns", sqle); - } - try { - final var functions = context.getFunctions(null, null, "%"); - assertThat(functions).doesNotHaveDuplicates(); - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(functions).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Function.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Function.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getFunctionColumns", sqle); - } - try { - final var procedureColumns = context.getProcedureColumns(null, null, "%", "%"); - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(procedureColumns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ProcedureColumn.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ProcedureColumn.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getProcedureColumns", sqle); - } - try { - final var procedures = context.getProcedures(null, null, "%"); - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(procedures).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Procedure.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Procedure.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getProcedureColumns", sqle); - } - try { - final var schemas = context.getSchemas((String) null, "%"); - final var databaseProductNames = Set.of( - "" - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(schemas).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Schema.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Schema.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getSchemas", sqle); - } - try { - final var superTables = context.getSuperTables(null, "%", "%"); - assertThat(superTables).doesNotHaveDuplicates(); - } catch (final SQLException sqle) { - thrown("failed; getSuperTables", sqle); - } - try { - final var superTypes = context.getSuperTypes(null, "%", "%"); - assertThat(superTypes).doesNotHaveDuplicates(); - } catch (final SQLException sqle) { - thrown("failed; getSuperTypes", sqle); - } - if (READ_TABLE_PRIVILEGES) { - try { - final var tablePrivileges = context.getTablePrivileges(null, null, "%"); - assertThat(tablePrivileges).doesNotHaveDuplicates(); - assertThat(tablePrivileges).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(TablePrivilege.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(TablePrivilege.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed; getTablePrivileges", sqle); - } - } - try { - final var tables = context.getTables(null, null, "%", null); - assertThat(tables).doesNotHaveDuplicates(); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE - , DatabaseProductNames.MARIA_DB - , DatabaseProductNames.POSTGRE_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(tables).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var table : tables) { - try { - for (final var scope : BestRowIdentifier.Scope.values()) { - for (final boolean nullable : new boolean[] {true, false}) { - final var bestRowIdentifier = - context.getBestRowIdentifier(table, scope.fieldValueAsInt(), nullable); - assertThat(bestRowIdentifier).isSortedAccordingTo(BestRowIdentifier.COMPARING_SCOPE); - if (false && !bestRowIdentifier.isEmpty()) { // 'actual...' - assertThat(bestRowIdentifier) - .extracting(BestRowIdentifier::getScope) - .containsOnly(scope.fieldValueAsInt()); - } - } - } - } catch (final SQLException sqle) { - thrown("failed: getBestRowIdentifier", sqle); - } - if (READ_COLUMN_PRIVILEGES) { - try { - final var columnPrivileges = context.getColumnPrivileges(table, "%"); - assertThat(columnPrivileges).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ColumnPrivilege.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed: getColumnPrivileges", sqle); - } - } - try { - final var exportedKeys = context.getExportedKeys(table); - assertThat(exportedKeys).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ExportedKey.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ExportedKey.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed: getExportedKeys", sqle); - } - try { - final var importedKeys = context.getImportedKeys(table); - assertThat(importedKeys).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(ImportedKey.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(ImportedKey.LEXICOGRAPHIC_ORDER) - ); - } catch (final SQLException sqle) { - thrown("failed: getImportedKeys", sqle); - } - try { - for (final boolean unique : new boolean[] {false, true}) { - for (final boolean approximate : new boolean[] {false, true}) { - final var indexInfo = context.getIndexInfo(table, unique, approximate); - assertThat(indexInfo).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(IndexInfo.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(IndexInfo.LEXICOGRAPHIC_ORDER) - ); - } - } - } catch (final SQLException sqle) { - thrown("failed: getIndexInfo", sqle); - } - try { - final var primaryKeys = context.getPrimaryKeys(table); - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE - , DatabaseProductNames.MY_SQL - , DatabaseProductNames.POSTGRE_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(primaryKeys).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(PrimaryKey.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(PrimaryKey.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed: getPrimaryKeys", sqle); - } - try { - final var versionColumns = context.getVersionColumns(table); // unordered - } catch (final SQLException sqle) { - thrown("failed: getVersionColumns", sqle); - } - } - } catch (final SQLException sqle) { - thrown("failed; getTables", sqle); - } - try { - final var typeInfo = context.getTypeInfo(); - assertThat(typeInfo).doesNotHaveDuplicates(); - final var databaseProductNames = Set.of( - DatabaseProductNames.H2 - , DatabaseProductNames.HSQL_DATABASE_ENGINE - , DatabaseProductNames.MY_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(typeInfo).isSortedAccordingTo(TypeInfo.COMPARING_DATA_TYPE); - } - } catch (final SQLException sqle) { - thrown("failed; getTypeInfo", sqle); - } - try { - final var udts = context.getUDTs(null, null, "%", null); - assertThat(udts).doesNotHaveDuplicates(); - final var databaseProductNames = Set.of( -// DatabaseProductNames.H2, -// DatabaseProductNames.HSQL_DATABASE_ENGINE - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(udts).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(UDT.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(UDT.LEXICOGRAPHIC_ORDER) - ); - } - } catch (final SQLException sqle) { - thrown("failed; getTypeInfo", sqle); - } - } - - static List
getTables__(final Context context, final String catalog, final String schemaPattern, - final String tableNamePattern, final String[] types) - throws SQLException { - { - info(context); - } - final var tables = context.getTables(catalog, schemaPattern, tableNamePattern, types); - assertThat(tables).doesNotHaveDuplicates(); - { - final var databaseProductNames = Set.of( - // https://sourceforge.net/p/hsqldb/bugs/1672/ - DatabaseProductNames.HSQL_DATABASE_ENGINE - , DatabaseProductNames.MARIA_DB - , DatabaseProductNames.POSTGRE_SQL - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(tables).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Table.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Table.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var table : tables) { - common(table); - } - return tables; - } - - static List getColumns__(final Context context, final String catalog, final String schemaPattern, - final String tableNamePattern, final String columnNamePattern) - throws SQLException { - { - info(context); - } - final var columns = context.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); - assertThat(columns).doesNotHaveDuplicates(); - { - final var databaseProductNames = Set.of( - DatabaseProductNames.HSQL_DATABASE_ENGINE, - DatabaseProductNames.MARIA_DB - ); - if (!databaseProductNames.contains(databaseProductName)) { - assertThat(columns).satisfiesAnyOf( - l -> assertThat(l).isSortedAccordingTo(Column.CASE_INSENSITIVE_ORDER), - l -> assertThat(l).isSortedAccordingTo(Column.LEXICOGRAPHIC_ORDER) - ); - } - } - for (final var column : columns) { - common(column); - } - return columns; - } - - private ContextTests() { - throw new AssertionError("instantiation is not allowed"); - } -} diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ExternalIT.java b/src/test/java/com/github/jinahya/database/metadata/bind/ExternalIT.java index 09483cc0..6acc2684 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ExternalIT.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ExternalIT.java @@ -54,7 +54,7 @@ void test() throws Exception { try (var connection = DriverManager.getConnection(url, user, password)) { log.info("connected: {}", connection); final var context = Context.newInstance(connection); - ContextTests.test(context); + ContextTestUtils.test(context); } } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/FunctionColumnTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/FunctionColumnTest.java index 6d64c657..c63b6484 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/FunctionColumnTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/FunctionColumnTest.java @@ -51,7 +51,7 @@ class ColumnTypeEnumAsEnumTest { @Test void getColumnTypeAsEnum__() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); final var columnTypeAsEnum = spy.getColumnTypeAsEnum(); assertThat(columnTypeAsEnum).isNull(); verify(spy, times(1)).getColumnType(); @@ -59,7 +59,7 @@ void getColumnTypeAsEnum__() { @Test void setColumnTypeAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setColumnTypeAsEnum(null); verify(spy, times(1)).setColumnType(null); } @@ -67,15 +67,15 @@ void setColumnTypeAsEnum_Null_Null() { @EnumSource(FunctionColumn.ColumnType.class) @ParameterizedTest void setColumnTypeAsEnum__(final FunctionColumn.ColumnType columnTypeAsEnum) { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setColumnTypeAsEnum(columnTypeAsEnum); verify(spy, times(1)).setColumnType(columnTypeAsEnum.fieldValueAsInt()); } } @Override - FunctionColumn typeInstance() { - final FunctionColumn instance = super.typeInstance(); + FunctionColumn newTypeInstance() { + final FunctionColumn instance = super.newTypeInstance(); instance.setFunctionName(""); instance.setColumnName(""); instance.setSpecificName(""); diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/FunctionTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/FunctionTest.java index edd037e6..648e51ce 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/FunctionTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/FunctionTest.java @@ -27,8 +27,8 @@ class FunctionTest extends AbstractMetadataTypeTest { } @Override - Function typeInstance() { - final Function instance = super.typeInstance(); + Function newTypeInstance() { + final Function instance = super.newTypeInstance(); instance.setFunctionName(""); instance.setSpecificName(""); return instance; diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/IndexInfoTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/IndexInfoTest.java index 6ff1d0ce..6dfd9d45 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/IndexInfoTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/IndexInfoTest.java @@ -48,7 +48,7 @@ class TypeAsEnumTest { @Test void getTypeAsEnum__() { // GIVEN - final var instance = typeSpy(); + final var instance = newTypeSpy(); // WHEN final var typeAsEnum = instance.getTypeAsEnum(); // THEN @@ -58,7 +58,7 @@ void getTypeAsEnum__() { @Test void setTypeAsEnum__Null() { // GIVEN - final var instance = typeSpy(); + final var instance = newTypeSpy(); // WHEN instance.setTypeAsEnum(null); // THEN @@ -69,7 +69,7 @@ void setTypeAsEnum__Null() { @ParameterizedTest void setTypeAsEnum__Nonnull(final IndexInfo.Type typeAsEnum) { // GIVEN - final var instance = typeSpy(); + final var instance = newTypeSpy(); // WHEN instance.setTypeAsEnum(typeAsEnum); // THEN diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/Memory_$_Test.java b/src/test/java/com/github/jinahya/database/metadata/bind/Memory_$_Test.java index 74b62148..fc95b4c7 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/Memory_$_Test.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/Memory_$_Test.java @@ -85,7 +85,7 @@ R applyContextChecked(final CheckedFunction1 f void test() throws SQLException { applyContext(c -> { try { - ContextTests.test(c); + ContextTestUtils.test(c); return null; } catch (final SQLException sqle) { throw new RuntimeException(sqle); @@ -97,7 +97,7 @@ void test() throws SQLException { void testOrdering() throws SQLException { applyContext(c -> { try { - ContextTests.testOrdering(c); + ContextTestUtils.testOrdering(c); return null; } catch (final SQLException sqle) { throw new RuntimeException(sqle); @@ -108,7 +108,7 @@ void testOrdering() throws SQLException { @Test void getColumns__() { applyContextChecked(c -> { - ContextTests.getColumns__(c, null, null, "%", "%"); + ContextTestUtils.getColumns__(c, null, null, "%", "%"); return null; }); } @@ -116,7 +116,7 @@ void getColumns__() { @Test void getTables__() { applyContextChecked(c -> { - ContextTests.getTables__(c, null, null, "%", null); + ContextTestUtils.getTables__(c, null, null, "%", null); return null; }); } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/Memory_Sqlite_Test.java b/src/test/java/com/github/jinahya/database/metadata/bind/Memory_Sqlite_Test.java index 5b0a3cfd..77c16993 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/Memory_Sqlite_Test.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/Memory_Sqlite_Test.java @@ -21,19 +21,10 @@ */ import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; import java.sql.Connection; -import java.sql.DatabaseMetaData; import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; import java.sql.SQLException; -import java.sql.Types; -import java.util.HashSet; - -import static org.assertj.core.api.Assertions.assertThat; /** * Tests for SQLite. @@ -49,68 +40,4 @@ class Memory_Sqlite_Test extends Memory_$_Test { protected Connection connect() throws SQLException { return DriverManager.getConnection(CONNECTION_URL); } - - @Disabled("https://github.com/xerial/sqlite-jdbc/issues/837 which has been fixed") - @Test - void getColumns_CATLOG_CATALOG() throws SQLException { - try (var connection = DriverManager.getConnection("jdbc:sqlite::memory:")) { - final var meta = connection.getMetaData(); - log.debug("driverName: {}", meta.getDriverName()); - log.debug("driverVersion: {}", meta.getDriverVersion()); - log.debug("driverMajorVersion: {}", meta.getDriverMajorVersion()); - log.debug("driverMinorVersion: {}", meta.getDriverMinorVersion()); - log.debug("databaseProductName: {}", meta.getDatabaseProductName()); - log.debug("databaseProductVersion: {}", meta.getDatabaseProductVersion()); - log.debug("databaseMajorVersion: {}", meta.getDatabaseMajorVersion()); - log.debug("databaseMinorVersion: {}", meta.getDatabaseMinorVersion()); - try (ResultSet results = meta.getColumns("", "", "%", "%")) { - final var labels = new HashSet<>(); - final var rsmd = results.getMetaData(); - for (int i = 1; i <= rsmd.getColumnCount(); i++) { - labels.add(rsmd.getColumnLabel(i)); - } - labels.forEach(l -> { - log.debug("label: {}", l); - }); - } - } - } - - @Disabled // https://github.com/xerial/sqlite-jdbc/issues/859 - @Test - void getColumns__INTEGER_DATA_TYPE() throws SQLException { - try (var connection = connect()) { - final var md = connection.getMetaData(); - try (var results = md.getColumns(null, null, "%", "%")) { - final var rsmd = results.getMetaData(); - for (int i = 1; i <= rsmd.getColumnCount(); i++) { - final var label = rsmd.getColumnLabel(i); - if (!"DATA_TYPE".equals(label)) { - continue; - } - final var type = rsmd.getColumnType(i); - assertThat(type).isEqualTo(Types.INTEGER); - assertThat(results.getObject(i)).isInstanceOf(Integer.class); - } - } - } - } - - public static void main(final String[] args) throws SQLException { - try (Connection connection = DriverManager.getConnection("jdbc:sqlite::memory:")) { - final DatabaseMetaData dmd = connection.getMetaData(); - try (ResultSet results = dmd.getColumns(null, null, "%", "%")) { - final ResultSetMetaData rsmd = results.getMetaData(); - for (int i = 1; i <= rsmd.getColumnCount(); i++) { - final String label = rsmd.getColumnLabel(i); - if (!"DATA_TYPE".equals(label)) { - continue; - } - final int type = rsmd.getColumnType(i); - assert type == Types.INTEGER; - assert results.getObject(i) instanceof Integer; - } - } - } - } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTest.java index f11fb7c2..a0158c55 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTest.java @@ -20,115 +20,172 @@ * #L% */ +import jakarta.annotation.Nullable; +import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; +import nl.jqno.equalsverifier.EqualsVerifier; +import nl.jqno.equalsverifier.Warning; import org.apache.commons.text.CaseUtils; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import java.beans.IntrospectionException; import java.beans.Introspector; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; +import java.util.Objects; +import java.util.stream.Stream; import static java.util.Arrays.stream; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.fail; +import static org.assertj.core.api.Assertions.assertThatCode; @Slf4j -abstract class MetadataTypeTest - extends _MetadataTypeTest { - - private static final Map> CLASSES_AND_SERIAL_VERSION_UIDS = new ConcurrentHashMap<>(); +abstract class MetadataTypeTest { MetadataTypeTest(final Class typeClass) { - super(typeClass); + super(); + this.typeClass = Objects.requireNonNull(typeClass, "typeClass is null"); } - @DisplayName("each serialVersionUID should be unique") + @DisplayName("toString()!blank") @Test - void serialVersionUID_Unique_() throws ReflectiveOperationException { - for (Class c = typeClass; MetadataType.class.isAssignableFrom(c); c = c.getSuperclass()) { - if (CLASSES_AND_SERIAL_VERSION_UIDS.containsValue(c)) { - continue; - } - final var field = c.getDeclaredField("serialVersionUID"); - if (field.getDeclaringClass() != c) { - log.error("{} is not declaring serialVersionUID", c); - fail(); - return; - } - if (!field.canAccess(null)) { - field.setAccessible(true); - } - final var serialVersionUID = field.getLong(null); - final var previous = CLASSES_AND_SERIAL_VERSION_UIDS.put(serialVersionUID, c); - if (previous != null) { - log.debug("{}#serialVersionUID({}) conflicts with {}", c, serialVersionUID, previous); - fail(); - return; - } - } + void toString_NotBlank_() { + // ------------------------------------------------------------------------------------------------------- given + final var instance = newTypeInstance(); + // -------------------------------------------------------------------------------------------------------- when + final var string = instance.toString(); + // -------------------------------------------------------------------------------------------------------- then + assertThat(string).isNotBlank(); } @Test - void toString_NonBlank_() { - assertThat(typeInstance().toString()).isNotBlank(); - } - - @Test - void equals_Equal_Self() throws ReflectiveOperationException { - final var method = typeClass.getMethod("equals", Object.class); - if (method.getDeclaringClass() == Object.class) { - return; - } - final T obj1 = typeInstance(); - final T obj2 = typeInstance(); - assertThat(obj1).isEqualTo(obj2); - assertThat(obj2).isEqualTo(obj1); + void equals__() { + EqualsVerifier + .simple() + .forClass(typeClass) + .suppress(Warning.ALL_FIELDS_SHOULD_BE_USED) + .verify(); } + @DisplayName("hashCode()I") @Test void hashCode__() { - assertDoesNotThrow(() -> typeInstance().hashCode()); + // ------------------------------------------------------------------------------------------------------- given + final var instance = newTypeInstance(); + // --------------------------------------------------------------------------------------------------- when/then + assertThatCode(() -> { + final var hashCode = instance.hashCode(); + }).doesNotThrowAnyException(); } - @DisplayName("@ColumnLabel -> has accessors") - @Test - void field_HasAccessors_AnnotatedWithColumnLabel() throws IntrospectionException { - for (final var field : getFieldsWithColumnLabel().keySet()) { - final var declaringClass = field.getDeclaringClass(); - final var info = Introspector.getBeanInfo(declaringClass); - final var descriptor = - stream(info.getPropertyDescriptors()) - .filter(d -> d.getName().equals(field.getName())) - .findAny(); - assertThat(descriptor).isNotEmpty().hasValueSatisfying(d -> { - final var reader = d.getReadMethod(); - assertThat(reader).isNotNull(); - try { - reader.invoke(typeInstance()); - } catch (final ReflectiveOperationException roe) { - throw new RuntimeException(roe); - } - final var writer = d.getWriteMethod(); - assertThat(writer) - .as("write method of %1$s", descriptor) - .isNotNull(); - if (!field.getType().isPrimitive()) { + @Nested + class FieldTest { + + @DisplayName("@ColumnLabel -> has accessors") + @Test + void _ShouldHaveAccessors_AnnotatedWithColumnLabel() throws IntrospectionException { + for (final var field : fieldsAnnotatedWithColumnLabel()) { + final var declaringClass = field.getDeclaringClass(); + final var info = Introspector.getBeanInfo(declaringClass); + final var descriptor = + stream(info.getPropertyDescriptors()) + .filter(d -> d.getName().equals(field.getName())) + .findAny(); + assertThat(descriptor).isNotEmpty().hasValueSatisfying(d -> { + final var reader = d.getReadMethod(); + assertThat(reader).isNotNull(); try { - writer.invoke(typeInstance(), new Object[] {null}); + reader.invoke(newTypeInstance()); } catch (final ReflectiveOperationException roe) { throw new RuntimeException(roe); } + final var writer = d.getWriteMethod(); + assertThat(writer) + .as("write method of %1$s", descriptor) + .isNotNull(); + if (!field.getType().isPrimitive()) { + try { + writer.invoke(newTypeInstance(), new Object[] {null}); + } catch (final ReflectiveOperationException roe) { + throw new RuntimeException(roe); + } + } + }); + } + } + + @DisplayName("@_ColumnLabel") + @Test + void _TypeIsNotPrimitive_AnnotatedWithColumnLabel() { + for (final var field : fieldsAnnotatedWithColumnLabel()) { + assertThat(field.getType()) + .as("type of %s.%s", typeClass.getSimpleName(), field.getName()) + .isNotPrimitive(); + } + } + + @DisplayName("@javax.validation.NotNull") + @Test + void __NotNull() { + for (final var field : fieldsAnnotatedWithColumnLabel()) { + if (!field.isAnnotationPresent(_NonNullBySpecification.class)) { + continue; + } + if (field.isAnnotationPresent(_NullableByVendor.class)) { + continue; + } + assertThat(field.isAnnotationPresent(NotNull.class)) + .as("%s.%s expected to be annotated with %s", typeClass.getSimpleName(), field.getName(), + NotNull.class) + .isTrue(); + } + } + + @DisplayName("@_NullableBySpecification -> @jakarta.annotation.Nullable") + @Test + void _ShouldBeAnnotatedWithNullable_AnnotatedWithNullableBySpecification() { + for (final var field : fieldsAnnotatedWithColumnLabel()) { + if (!field.isAnnotationPresent(_NullableBySpecification.class)) { + continue; } - }); + assertThat(field.getAnnotation(Nullable.class)) + .as("@%1$s on %2$s.%3$s", Nullable.class, typeClass.getSimpleName(), field.getName()) + .isNotNull(); + } + } + + @DisplayName("@_NullableByVendor -> !@jakarta.annotation.Nullable") + @Test + void _ShouldBeNotAnnotatedWithNullable_AnnotatedWithNullableByVendor() { + for (final var field : fieldsAnnotatedWithColumnLabel()) { + if (!field.isAnnotationPresent(_NullableByVendor.class)) { + continue; + } + assertThat(field.getAnnotation(Nullable.class)) + .as("@%1$s on %2$s.%3$s", Nullable.class, typeClass.getSimpleName(), field) + .isNull(); + } + } + + @DisplayName("fieldName = toCamelCase(@ColumnLabel#value)") + @Test + void _CamelCasedColumnLabel_() { + for (final var field : fieldsAnnotatedWithColumnLabel()) { + final var columnLabel = field.getAnnotation(_ColumnLabel.class); + assertThat(field.getName()) + .isEqualTo(CaseUtils.toCamelCase(columnLabel.value(), false, '_')); + } } } + @DisplayName("setXxx(getXxx())") @Test void accessors() throws Exception { - final var instance = typeInstance(); + final var instance = newTypeInstance(); final var beanInfo = Introspector.getBeanInfo(typeClass); for (final var descriptor : beanInfo.getPropertyDescriptors()) { final var reader = descriptor.getReadMethod(); @@ -145,45 +202,34 @@ void accessors() throws Exception { } } - @DisplayName("@Unused -> !primitive") - @Test - void field_NotPrimitive_Unused() { - for (final var field : fieldsWithUnusedBySpecification().keySet()) { - assert field.isAnnotationPresent(_NotUsedBySpecification.class); - assertThat(field.getType().isPrimitive()) - .as("@NotUsedBySpecification on primitive field: %s", field) - .isFalse(); - } - } + // ------------------------------------------------------------------------------------------------------- typeClass - @DisplayName("@NullableBySpecification -> !primitive") - @Test - void field_NotPrimitive_NullableBySpecification() { - for (final var field : getFieldsWithNullableBySpecification().keySet()) { - assert field.isAnnotationPresent(_NullableBySpecification.class); - assertThat(field.getType().isPrimitive()) - .as("@NullableBySpecification on primitive field: %s", field) - .isFalse(); + T newTypeInstance() { + try { + final var constructor = typeClass.getConstructor(); + return constructor.newInstance(); + } catch (final ReflectiveOperationException roe) { + throw new RuntimeException("failed to instantiate " + typeClass, roe); } } - @DisplayName("@MayBeNullByVendor -> !primitive") - @Test - void field_NotPrimitive_NullableByVendor() { - for (final var field : getFieldsWithMayBeNullByVendor().keySet()) { - assertThat(field.getAnnotation(_NullableByVendor.class)).isNotNull(); - assertThat(field.getType().isPrimitive()).isFalse(); - } + T newTypeSpy() { + return Mockito.spy(newTypeInstance()); } - @DisplayName("fieldName = toCamelCase(@ColumnLabel#value)") - @Test - void field_Expected_CamelCasedColumnLabel() { - getFieldsWithColumnLabel().forEach((f, l) -> { - final var expected = CaseUtils.toCamelCase(l.value(), false, '_'); - assertThat(f.getName()) - .as("expected name of %1$s", f) - .isEqualTo(expected); - }); + List fieldsAnnotatedWithColumnLabel() { + return Stream.of(typeClass.getDeclaredFields()).filter(f -> { + final var modifier = f.getModifiers(); + if (Modifier.isStatic(modifier)) { + return false; + } + if (!f.isAnnotationPresent(_ColumnLabel.class)) { + return false; + } + return true; + }).toList(); } + + // ----------------------------------------------------------------------------------------------------------------- + final Class typeClass; } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTestUtils.java b/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTestUtils.java new file mode 100644 index 00000000..d140bf10 --- /dev/null +++ b/src/test/java/com/github/jinahya/database/metadata/bind/MetadataTypeTestUtils.java @@ -0,0 +1,90 @@ +package com.github.jinahya.database.metadata.bind; + +/*- + * #%L + * database-metadata-bind + * %% + * Copyright (C) 2011 - 2024 Jinahya, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import lombok.extern.slf4j.Slf4j; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.util.Objects; + +@Slf4j +final class MetadataTypeTestUtils { + + static void verifyAccessors(final Class cls, final MetadataType obj) { + Objects.requireNonNull(cls, "cls is null"); + Objects.requireNonNull(obj, "obj is null"); + final BeanInfo info; + try { + info = Introspector.getBeanInfo(cls); + } catch (final IntrospectionException ie) { + throw new RuntimeException("failed to get beanInfo from " + cls, ie); + } + for (final var descriptor : info.getPropertyDescriptors()) { + final var reader = descriptor.getReadMethod(); + if (reader == null || !MetadataType.class.isAssignableFrom(reader.getDeclaringClass())) { + continue; + } + if (!reader.canAccess(obj)) { + reader.setAccessible(true); + } + final Object value; + try { + value = reader.invoke(obj); + } catch (final ReflectiveOperationException roe) { + log.error("failed to invoke {}, on {}", reader, obj, roe); + continue; + } + final var writer = descriptor.getWriteMethod(); + if (writer == null || !MetadataType.class.isAssignableFrom(reader.getDeclaringClass())) { + continue; + } + if (!writer.canAccess(obj)) { + writer.setAccessible(true); + } + try { + writer.invoke(obj, value); + } catch (final ReflectiveOperationException roe) { + log.error("failed to invoke {} with {}, on {}", writer, value, obj); + } + } + } + + private static void verifyAccessorsHelper(final Class cls, final Object obj) { + Objects.requireNonNull(cls, "cls is null"); + verifyAccessors(cls, cls.cast(obj)); + } + + static void verifyAccessors(final MetadataType obj) { + Objects.requireNonNull(obj, "obj is null"); + verifyAccessorsHelper(obj.getClass(), obj); + } + + static void verify(final MetadataType obj) { + verifyAccessors(obj); + ValidationTestUtils.requireValid(obj); + } + + private MetadataTypeTestUtils() { + throw new AssertionError("instantiation is not allowed"); + } +} diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/PrimaryKeyTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/PrimaryKeyTest.java index a1b37a83..12678f41 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/PrimaryKeyTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/PrimaryKeyTest.java @@ -27,8 +27,8 @@ class PrimaryKeyTest extends AbstractMetadataTypeTest { } @Override - PrimaryKey typeInstance() { - final var instance = super.typeInstance(); + PrimaryKey newTypeInstance() { + final var instance = super.newTypeInstance(); instance.setTableName(""); instance.setColumnName(""); return instance; diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureColumnTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureColumnTest.java index 57b96f7e..6674e3fe 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureColumnTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureColumnTest.java @@ -27,8 +27,8 @@ class ProcedureColumnTest extends AbstractMetadataTypeTest { } @Override - ProcedureColumn typeInstance() { - final ProcedureColumn instance = super.typeInstance(); + ProcedureColumn newTypeInstance() { + final ProcedureColumn instance = super.newTypeInstance(); instance.setProcedureName(""); instance.setColumnName(""); instance.setSpecificName(""); diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureTest.java index 5e81e7e7..84541382 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ProcedureTest.java @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.Mockito; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -35,8 +36,8 @@ class ProcedureTest extends AbstractMetadataTypeTest { } @Override - Procedure typeInstance() { - final Procedure instance = super.typeInstance(); + Procedure newTypeInstance() { + final Procedure instance = super.newTypeInstance(); instance.setProcedureName(""); instance.setSpecificName(""); return instance; @@ -48,7 +49,7 @@ class ProcedureTypeAsEnumTest { @Test void getProcedureTypeAsEnum__() { // GIVEN - final var spy = typeSpy(); + final var spy = Mockito.spy(newTypeInstance()); // WHEN final var procedureTypeAsEnum = spy.getProcedureTypeAsEnum(); // THEN @@ -59,7 +60,7 @@ void getProcedureTypeAsEnum__() { @ParameterizedTest void setProcedureTypeAsEnum__(final Procedure.ProcedureType procedureTypeAsEnum) { // GIVEN - final var spy = typeSpy(); + final var spy = Mockito.spy(newTypeInstance()); // WHEN spy.setProcedureTypeAsEnum(procedureTypeAsEnum); // THEN diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/SchemaTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/SchemaTest.java index 21211655..328876d4 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/SchemaTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/SchemaTest.java @@ -27,8 +27,8 @@ class SchemaTest extends AbstractMetadataTypeTest { } @Override - Schema typeInstance() { - final Schema instance = super.typeInstance(); + Schema newTypeInstance() { + final Schema instance = super.newTypeInstance(); instance.setTableSchem(Schema.COLUMN_VALUE_TABLE_SCHEM_EMPTY); return instance; } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrabilityTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrabilityTest.java index 065210b4..83b42983 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrabilityTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeferrabilityTest.java @@ -1,22 +1,42 @@ package com.github.jinahya.database.metadata.bind; +/*- + * #%L + * database-metadata-bind + * %% + * Copyright (C) 2011 - 2024 Jinahya, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; -import static com.github.jinahya.database.metadata.bind.TableKeyDeferrability.valueOfDeferrability; +import static com.github.jinahya.database.metadata.bind.TableKey.TableKeyDeferrability.valueOfDeferrability; import static org.assertj.core.api.Assertions.assertThat; -class TableKeyDeferrabilityTest extends _IntFieldEnumTest { +class TableKeyDeferrabilityTest extends _IntFieldEnumTest { TableKeyDeferrabilityTest() { - super(TableKeyDeferrability.class); + super(TableKey.TableKeyDeferrability.class); } @DisplayName("valueOfDeferrability(deferrability)") - @EnumSource(TableKeyDeferrability.class) + @EnumSource(TableKey.TableKeyDeferrability.class) @ParameterizedTest - void valueOfDeferrability__(final TableKeyDeferrability deferrability) { + void valueOfDeferrability__(final TableKey.TableKeyDeferrability deferrability) { assertThat(valueOfDeferrability(deferrability.fieldValueAsInt())) .isSameAs(deferrability); } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRuleTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRuleTest.java index d578be54..9a80dc6b 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRuleTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyDeleteRuleTest.java @@ -1,22 +1,42 @@ package com.github.jinahya.database.metadata.bind; +/*- + * #%L + * database-metadata-bind + * %% + * Copyright (C) 2011 - 2024 Jinahya, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import static org.assertj.core.api.Assertions.assertThat; -class TableKeyDeleteRuleTest extends _IntFieldEnumTest { +class TableKeyDeleteRuleTest extends _IntFieldEnumTest { TableKeyDeleteRuleTest() { - super(TableKeyDeleteRule.class); + super(TableKey.TableKeyDeleteRule.class); } @DisplayName("valueOfDeleteRule") - @EnumSource(TableKeyDeleteRule.class) + @EnumSource(TableKey.TableKeyDeleteRule.class) @ParameterizedTest - void valueOfDeleteRule__(final TableKeyDeleteRule deleteRule) { - assertThat(TableKeyDeleteRule.valueOfDeleteRule(deleteRule.fieldValueAsInt())) + void valueOfDeleteRule__(final TableKey.TableKeyDeleteRule deleteRule) { + assertThat(TableKey.TableKeyDeleteRule.valueOfDeleteRule(deleteRule.fieldValueAsInt())) .isSameAs(deleteRule); } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyTest.java index 7556bea0..6817dd49 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyTest.java @@ -24,6 +24,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.Mockito; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.times; @@ -36,8 +37,8 @@ abstract class TableKeyTest> extends AbstractMetadataTypeT } @Override - T typeInstance() { - final T instance = super.typeInstance(); + T newTypeInstance() { + final T instance = super.newTypeInstance(); instance.setPktableName(""); instance.setPkcolumnName(""); instance.setFktableName(""); @@ -50,22 +51,22 @@ class UpdateRuleAsEnumTest { @Test void getUpdateRuleAsEnum__() { - final var spy = typeSpy(); + final var spy = Mockito.spy(newTypeInstance()); assertThat(spy.getUpdateRuleAsEnum()).isNull(); verify(spy, times(1)).getUpdateRule(); } @Test void setUpdateRuleAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = Mockito.spy(newTypeInstance()); spy.setUpdateRuleAsEnum(null); verify(spy, times(1)).setUpdateRule(null); } - @EnumSource(TableKeyUpdateRule.class) + @EnumSource(TableKey.TableKeyUpdateRule.class) @ParameterizedTest - void setUpdateRuleAsEnum__(final TableKeyUpdateRule updateRuleAsEnum) { - final var spy = typeSpy(); + void setUpdateRuleAsEnum__(final TableKey.TableKeyUpdateRule updateRuleAsEnum) { + final var spy = Mockito.spy(newTypeInstance()); spy.setUpdateRuleAsEnum(updateRuleAsEnum); verify(spy, times(1)).setUpdateRule(updateRuleAsEnum.fieldValueAsInt()); } @@ -76,22 +77,22 @@ class DeleteRuleAsEnumTest { @Test void getDeleteRuleAsEnum__() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); assertThat(spy.getDeleteRuleAsEnum()).isNull(); verify(spy, times(1)).getDeleteRule(); } @Test void setDeleteRuleAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setDeleteRuleAsEnum(null); verify(spy, times(1)).setDeleteRule(null); } - @EnumSource(TableKeyDeleteRule.class) + @EnumSource(TableKey.TableKeyDeleteRule.class) @ParameterizedTest - void setDeleteRuleAsEnum__(final TableKeyDeleteRule deleteRuleAsEnum) { - final var spy = typeSpy(); + void setDeleteRuleAsEnum__(final TableKey.TableKeyDeleteRule deleteRuleAsEnum) { + final var spy = newTypeSpy(); spy.setDeleteRuleAsEnum(deleteRuleAsEnum); verify(spy, times(1)).setDeleteRule(deleteRuleAsEnum.fieldValueAsInt()); } @@ -102,22 +103,22 @@ class DeferrabilityAsEnumTest { @Test void getDeferrabilityAsEnum__() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); assertThat(spy.getDeferrabilityAsEnum()).isNull(); verify(spy, times(1)).getDeferrability(); } @Test void setDeferrabilityAsEnum_Null_Null() { - final var spy = typeSpy(); + final var spy = newTypeSpy(); spy.setDeferrabilityAsEnum(null); verify(spy, times(1)).setDeferrability(null); } - @EnumSource(TableKeyDeferrability.class) + @EnumSource(TableKey.TableKeyDeferrability.class) @ParameterizedTest - void setDeferrabilityAsEnum__(final TableKeyDeferrability deferrabilityAsEnum) { - final var spy = typeSpy(); + void setDeferrabilityAsEnum__(final TableKey.TableKeyDeferrability deferrabilityAsEnum) { + final var spy = newTypeSpy(); spy.setDeferrabilityAsEnum(deferrabilityAsEnum); verify(spy, times(1)).setDeferrability(deferrabilityAsEnum.fieldValueAsInt()); } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRuleTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRuleTest.java index b6a15b17..1bf4dc31 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRuleTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/TableKeyUpdateRuleTest.java @@ -1,22 +1,42 @@ package com.github.jinahya.database.metadata.bind; +/*- + * #%L + * database-metadata-bind + * %% + * Copyright (C) 2011 - 2024 Jinahya, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import static org.assertj.core.api.Assertions.assertThat; -class TableKeyUpdateRuleTest extends _IntFieldEnumTest { +class TableKeyUpdateRuleTest extends _IntFieldEnumTest { TableKeyUpdateRuleTest() { - super(TableKeyUpdateRule.class); + super(TableKey.TableKeyUpdateRule.class); } @DisplayName("valueOfUpdateRule") - @EnumSource(TableKeyUpdateRule.class) + @EnumSource(TableKey.TableKeyUpdateRule.class) @ParameterizedTest - void valueOfUpdateRule__(final TableKeyUpdateRule updateRule) { - assertThat(TableKeyUpdateRule.valueOfUpdateRule(updateRule.fieldValueAsInt())) + void valueOfUpdateRule__(final TableKey.TableKeyUpdateRule updateRule) { + assertThat(TableKey.TableKeyUpdateRule.valueOfUpdateRule(updateRule.fieldValueAsInt())) .isSameAs(updateRule); } } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/TableTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/TableTest.java index 5dafc80d..40413443 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/TableTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/TableTest.java @@ -27,8 +27,8 @@ class TableTest extends AbstractMetadataTypeTest
{ } @Override - Table typeInstance() { - final Table instance = super.typeInstance(); + Table newTypeInstance() { + final Table instance = super.newTypeInstance(); instance.setTableName(""); return instance; } diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/ValidationTestUtils.java b/src/test/java/com/github/jinahya/database/metadata/bind/ValidationTestUtils.java new file mode 100644 index 00000000..e707e90f --- /dev/null +++ b/src/test/java/com/github/jinahya/database/metadata/bind/ValidationTestUtils.java @@ -0,0 +1,44 @@ +package com.github.jinahya.database.metadata.bind; + +/*- + * #%L + * database-metadata-bind + * %% + * Copyright (C) 2011 - 2024 Jinahya, Inc. + * %% + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * #L% + */ + +import jakarta.validation.Validation; + +import java.util.Objects; + +import static org.assertj.core.api.Assertions.assertThat; + +final class ValidationTestUtils { + + static void requireValid(final Object obj) { + Objects.requireNonNull(obj, "obj is null"); + try (final var factory = Validation.buildDefaultValidatorFactory()) { + final var violations = factory.getValidator().validate(obj); + assertThat(violations) + .as("violations of %s: %s", obj, violations) + .isEmpty(); + } + } + + private ValidationTestUtils() { + throw new AssertionError("instantiation is not allowed"); + } +} diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/VersionColumnTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/VersionColumnTest.java index 7a3a3b43..a2a72319 100644 --- a/src/test/java/com/github/jinahya/database/metadata/bind/VersionColumnTest.java +++ b/src/test/java/com/github/jinahya/database/metadata/bind/VersionColumnTest.java @@ -57,7 +57,7 @@ class PseudoColumnAsEnumTest { @Test void getPseudoColumnAsEnum__() { - final var instance = typeSpy(); + final var instance = newTypeSpy(); // WHEN final var pseudoColumnAsEnum = instance.getPseudoColumnAsEnum(); // THEN @@ -66,7 +66,7 @@ void getPseudoColumnAsEnum__() { @Test void setPseudoColumnAsEnum__Null() { - final var instance = typeSpy(); + final var instance = newTypeSpy(); // WHEN instance.setPseudoColumnAsEnum(null); // THEN @@ -76,7 +76,7 @@ void setPseudoColumnAsEnum__Null() { @EnumSource(VersionColumn.PseudoColumn.class) @ParameterizedTest void setPseudoColumnAsEnum__(final VersionColumn.PseudoColumn pseudoColumn) { - final var instance = typeSpy(); + final var instance = newTypeSpy(); // WHEN instance.setPseudoColumnAsEnum(pseudoColumn); // THEN diff --git a/src/test/java/com/github/jinahya/database/metadata/bind/_MetadataTypeTest.java b/src/test/java/com/github/jinahya/database/metadata/bind/_MetadataTypeTest.java deleted file mode 100644 index f56320f6..00000000 --- a/src/test/java/com/github/jinahya/database/metadata/bind/_MetadataTypeTest.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.github.jinahya.database.metadata.bind; - -/*- - * #%L - * database-metadata-bind - * %% - * Copyright (C) 2011 - 2021 Jinahya, Inc. - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * #L% - */ - -import lombok.extern.slf4j.Slf4j; - -import java.lang.reflect.Field; -import java.util.Map; -import java.util.stream.Collectors; - -import static java.util.Collections.unmodifiableMap; -import static java.util.Objects.requireNonNull; -import static org.mockito.Mockito.spy; - -@Slf4j -abstract class _MetadataTypeTest { - - _MetadataTypeTest(final Class typeClass) { - this.typeClass = requireNonNull(typeClass, "typeClass is null"); - } - - T typeInstance() { -// try { // just for the coverage -// final var builder = typeClass.getMethod("builder").invoke(null); -// final var built = builder.getClass().getMethod("build").invoke(builder); -// } catch (final ReflectiveOperationException roe) { -// throw new RuntimeException(roe); -// } - try { - final var constructor = typeClass.getDeclaredConstructor(); - if (!constructor.canAccess(null)) { - constructor.setAccessible(true); - } - return constructor.newInstance(); - } catch (final ReflectiveOperationException roe) { - throw new RuntimeException("failed to find/invoke default constructor", roe); - } - } - - T typeSpy() { - return spy(typeInstance()); - } - - Map getFieldsWithMayBeNullByVendor() { - return getFieldsWithColumnLabel().entrySet().stream() - .filter(e -> e.getKey().getAnnotation(_NullableByVendor.class) != null) - .collect(Collectors.toMap(Map.Entry::getKey, e -> e.getKey().getAnnotation(_NullableByVendor.class))); - } - - Map getFieldsWithNullableBySpecification() { - return getFieldsWithColumnLabel().entrySet().stream() - .filter(e -> e.getKey().getAnnotation(_NullableBySpecification.class) != null).collect( - Collectors.toMap(Map.Entry::getKey, - e -> e.getKey().getAnnotation(_NullableBySpecification.class))); - } - - Map fieldsWithUnusedBySpecification() { - return getFieldsWithColumnLabel().entrySet().stream() - .filter(e -> e.getKey().getAnnotation(_NotUsedBySpecification.class) != null).collect( - Collectors.toMap(Map.Entry::getKey, - e -> e.getKey().getAnnotation(_NotUsedBySpecification.class))); - } - - Map getFieldsWithColumnLabel() { - if (fieldsWithLabel == null) { - fieldsWithLabel = unmodifiableMap(Utils.getFieldsAnnotatedWith(typeClass, _ColumnLabel.class)); - } - return fieldsWithLabel; - } - - final Class typeClass; - - private Map fieldsWithLabel; -} diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 0a43b831..3c3d37f6 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -33,6 +33,7 @@ +