This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 0d44b82483f2213a30dd5c3156f7fed51f574eaa Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Aug 14 12:40:07 2024 +0200 Replace the boolean in `Dialect` by flags, because we are getting more and more of them and a long list of boolean values is difficult to read. --- .../apache/sis/metadata/sql/MetadataWriter.java | 10 +-- .../org/apache/sis/metadata/sql/privy/Dialect.java | 78 +++++++++++++++------- .../sis/metadata/sql/privy/ScriptRunner.java | 4 +- .../apache/sis/metadata/sql/privy/Supports.java | 74 ++++++++++++++++++++ .../apache/sis/storage/sql/feature/Database.java | 2 +- .../sis/storage/sql/feature/FeatureStream.java | 2 +- .../sql/feature/TemporalValueGetterTest.java | 2 +- 7 files changed, 138 insertions(+), 34 deletions(-) diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java index 7e8f29807e..0ab6bc5ab5 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/MetadataWriter.java @@ -302,7 +302,7 @@ public class MetadataWriter extends MetadataSource { * (if such parent exists). In most case, the answer is "no" and `addTo` is equal to `table`. */ String addTo = table; - if (helper.dialect.supportsTableInheritance) { + if (helper.dialect.supportsTableInheritance()) { @SuppressWarnings("null") // `colTables` is initialized in same time as `colTypes`. final Class<?> declaring = colTables.get(column); if (!interfaceType.isAssignableFrom(declaring)) { @@ -417,7 +417,7 @@ public class MetadataWriter extends MetadataSource { if (dependency == null) { dependency = add(stmt, value, done, identifier); assert done.get(value) == dependency; // Really identity comparison. - if (!helper.dialect.supportsIndexInheritance) { + if (!helper.dialect.supportsIndexInheritance()) { /* * In a classical object-oriented model, the foreigner key constraints declared in the * parent table would take in account the records in the child table and we would have @@ -503,7 +503,7 @@ public class MetadataWriter extends MetadataSource { * However, this is not yet supported as of PostgreSQL 9.6. If inheritance is not supported, * then we have to repeat the constraint creation in child tables. */ - if (!helper.dialect.supportsIndexInheritance && !table.equals(fkey.tableName)) { + if (!helper.dialect.supportsIndexInheritance() && !table.equals(fkey.tableName)) { stmt.executeUpdate(helper.createForeignKey(schema(), table, column, target, primaryKey, !isCodeList)); } } @@ -593,12 +593,12 @@ public class MetadataWriter extends MetadataSource { if (standard.isMetadata(candidate)) { isChildTable = Boolean.TRUE; final SQLBuilder helper = helper(); - if (helper.dialect.supportsTableInheritance) { + if (helper.dialect.supportsTableInheritance()) { final String parent = getTableName(candidate); createTable(stmt, candidate, parent, getExistingColumns(parent)); if (inherits == null) { helper.clear().append("CREATE TABLE ").appendIdentifier(schema(), table); - if (!helper.dialect.supportsIndexInheritance) { + if (!helper.dialect.supportsIndexInheritance()) { /* * In a classical object-oriented model, the new child table would inherit the index from * its parent table. However, this is not yet the case as of PostgreSQL 9.6. If the index is diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Dialect.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Dialect.java index 8c09d25b8e..a942ada0df 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Dialect.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Dialect.java @@ -34,7 +34,10 @@ public enum Dialect { * * @see DatabaseMetaData#supportsANSI92EntryLevelSQL() */ - ANSI(null, false, true, true, true), + ANSI(null, Supports.ALTER_TABLE_WITH_ADD_CONSTRAINT + | Supports.JAVA_TIME + | Supports.READ_ONLY_UPDATE + | Supports.CONCURRENCY), /** * The database uses Derby syntax. This is ANSI, with some constraints that PostgreSQL does not have @@ -43,31 +46,43 @@ public enum Dialect { * * <a href="https://issues.apache.org/jira/browse/DERBY-6445">DERBY-6445</a> */ - DERBY("derby", false, true, false, true), + DERBY("derby", Supports.ALTER_TABLE_WITH_ADD_CONSTRAINT + | Supports.READ_ONLY_UPDATE + | Supports.CONCURRENCY), /** * The database uses HSQL syntax. This is ANSI, but does not allow {@code INSERT} statements inserting many lines. * It also have a {@code SHUTDOWN} command which is specific to HSQLDB. */ - HSQL("hsqldb", false, true, true, true), + HSQL("hsqldb", Supports.ALTER_TABLE_WITH_ADD_CONSTRAINT + | Supports.JAVA_TIME + | Supports.READ_ONLY_UPDATE + | Supports.CONCURRENCY), /** * The database uses PostgreSQL syntax. This is ANSI, but provided an a separated * enumeration value because it allows a few additional commands like {@code VACUUM}. */ - POSTGRESQL("postgresql", true, true, true, true), + POSTGRESQL("postgresql", Supports.TABLE_INHERITANCE + | Supports.ALTER_TABLE_WITH_ADD_CONSTRAINT + | Supports.JAVA_TIME + | Supports.READ_ONLY_UPDATE + | Supports.CONCURRENCY), /** * The database uses Oracle syntax. This is ANSI, but without {@code "AS"} keyword. */ - ORACLE("oracle", false, true, true, true), + ORACLE("oracle", Supports.ALTER_TABLE_WITH_ADD_CONSTRAINT + | Supports.JAVA_TIME + | Supports.READ_ONLY_UPDATE + | Supports.CONCURRENCY), /** * The database uses SQLite syntax. This is ANSI, but with several limitations. * * @see <a href="https://www.sqlite.org/omitted.html">SQL Features That SQLite Does Not Implement</a> */ - SQLITE("sqlite", false, false, false, false); + SQLITE("sqlite", 0); /** * The protocol in JDBC URL, or {@code null} if unknown. @@ -75,10 +90,25 @@ public enum Dialect { */ private final String protocol; + /** + * Bit mask of supported features. + */ + private final int flags; + + /** + * Creates a new enumeration value for a SQL dialect for the given protocol. + */ + private Dialect(final String protocol, final int flags) { + this.protocol = protocol; + this.flags = flags; + } + /** * Whether this dialect support table inheritance. */ - public final boolean supportsTableInheritance; + public final boolean supportsTableInheritance() { + return (flags & Supports.TABLE_INHERITANCE) != 0; + } /** * {@code true} if child tables inherit the index of their parent tables. @@ -86,7 +116,9 @@ public enum Dialect { * * @see <a href="https://issues.apache.org/jira/browse/SIS-358">SIS-358</a> */ - public final boolean supportsIndexInheritance = false; + public final boolean supportsIndexInheritance() { + return (flags & Supports.INDEX_INHERITANCE) != 0; + } /** * Whether this dialect support adding table constraints after creation. @@ -94,7 +126,9 @@ public enum Dialect { * * @see DatabaseMetaData#supportsAlterTableWithAddColumn() */ - public final boolean supportsAlterTableWithAddConstraint; + public final boolean supportsAlterTableWithAddConstraint() { + return (flags & Supports.ALTER_TABLE_WITH_ADD_CONSTRAINT) != 0; + } /** * Whether the JDBC driver supports conversions from objects to {@code java.time} API. @@ -104,28 +138,24 @@ public enum Dialect { * * @see <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr221/JDBC4.2MR-January2014.pdf">JDBC Maintenance Release 4.2</a> */ - public final boolean supportsJavaTime; + public final boolean supportsJavaTime() { + return (flags & Supports.JAVA_TIME) != 0; + } /** - * Whether the JDBC driver supports configuring readOnly mode on connection instances. + * Whether the JDBC driver supports configuring read-only mode on connection instances. * This feature is not supported in SQLite. */ - public final boolean supportsReadOnlyUpdate; + public final boolean supportsReadOnlyUpdate() { + return (flags & Supports.READ_ONLY_UPDATE) != 0; + } /** - * Creates a new enumeration value for a SQL dialect for the given protocol. + * Whether the JDBC driver supports concurrent transactions. + * This feature is not well supported in SQLite. */ - private Dialect(final String protocol, - final boolean supportsTableInheritance, - final boolean supportsAlterTableWithAddConstraint, - final boolean supportsJavaTime, - final boolean supportsReadOnlyUpdate) - { - this.protocol = protocol; - this.supportsTableInheritance = supportsTableInheritance; - this.supportsAlterTableWithAddConstraint = supportsAlterTableWithAddConstraint; - this.supportsJavaTime = supportsJavaTime; - this.supportsReadOnlyUpdate = supportsReadOnlyUpdate; + public final boolean supportsConcurrency() { + return (flags & Supports.CONCURRENCY) != 0; } /** diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/ScriptRunner.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/ScriptRunner.java index 486268f6d6..b8785b9cce 100644 --- a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/ScriptRunner.java +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/ScriptRunner.java @@ -342,7 +342,7 @@ public class ScriptRunner implements AutoCloseable { if (!isCommentSupported) { addStatementToSkip("COMMENT\\s+ON\\s+.*"); } - if (!dialect.supportsAlterTableWithAddConstraint) { + if (!dialect.supportsAlterTableWithAddConstraint()) { addStatementToSkip("ALTER\\s+TABLE\\s+\\w+\\s+ADD\\s+CONSTRAINT\\s+.*"); } } @@ -730,7 +730,7 @@ parseLine: while (pos < length) { return 0; } String subSQL = currentSQL = CharSequences.trimWhitespaces(sql).toString(); - if (!dialect.supportsTableInheritance && subSQL.startsWith("CREATE TABLE")) { + if (!dialect.supportsTableInheritance() && subSQL.startsWith("CREATE TABLE")) { final int s = sql.lastIndexOf("INHERITS"); if (s >= 0 && isOutsideQuotes(sql, s+8, sql.length())) { // 8 is the length of "INHERITS". sql.setLength(CharSequences.skipTrailingWhitespaces(sql, 0, s)); diff --git a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Supports.java b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Supports.java new file mode 100644 index 0000000000..b2556112e8 --- /dev/null +++ b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/sql/privy/Supports.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ +package org.apache.sis.metadata.sql.privy; + + +/** + * Enumeration of features that may be supported by a database. + * This is used as a complement of database metadata. + * + * @author Martin Desruisseaux (Geomatys) + */ +final class Supports { + /** + * Whether this dialect support table inheritance. + */ + static final int TABLE_INHERITANCE = 1; + + /** + * Whether child tables inherit the index of their parent tables. + * This feature is not yet supported in PostgreSQL. + * + * @see <a href="https://issues.apache.org/jira/browse/SIS-358">SIS-358</a> + */ + static final int INDEX_INHERITANCE = 2; + + /** + * Whether this dialect support adding table constraints after creation. + * This feature is not yet supported in SQLite. + * + * @see DatabaseMetaData#supportsAlterTableWithAddColumn() + */ + static final int ALTER_TABLE_WITH_ADD_CONSTRAINT = 4; + + /** + * Whether the JDBC driver supports conversions from objects to {@code java.time} API. + * The JDBC 4.2 specification provides a mapping from {@link java.sql.Types} to temporal objects. + * The specification suggests that {@link java.sql.ResultSet#getObject(int, Class)} should accept + * those temporal types in the {@link Class} argument, but not all drivers support that. + * + * @see <a href="https://jcp.org/aboutJava/communityprocess/maintenance/jsr221/JDBC4.2MR-January2014.pdf">JDBC Maintenance Release 4.2</a> + */ + static final int JAVA_TIME = 8; + + /** + * Whether the JDBC driver supports configuring readOnly mode on connection instances. + * This feature is not supported in SQLite. + */ + static final int READ_ONLY_UPDATE = 16; + + /** + * Whether the JDBC driver supports concurrent transactions. + */ + static final int CONCURRENCY = 32; + + /** + * Do not allow instantiation of this class. + */ + private Supports() { + } +} diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java index a16a41d2ef..ed49071ea5 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/Database.java @@ -278,7 +278,7 @@ public class Database<G> extends Syntax { this.tablesByNames = new FeatureNaming<>(); supportsCatalogs = metadata.supportsCatalogsInDataManipulation(); supportsSchemas = metadata.supportsSchemasInDataManipulation(); - supportsJavaTime = dialect.supportsJavaTime; + supportsJavaTime = dialect.supportsJavaTime(); crsEncodings = EnumSet.noneOf(CRSEncoding.class); } diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java index 2189b94447..196c9887cd 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/FeatureStream.java @@ -366,7 +366,7 @@ final class FeatureStream extends DeferredStream<Feature> { * @param connection the connection to configure. */ private void makeReadOnly(final Connection connection) throws SQLException { - if (table.database.dialect.supportsReadOnlyUpdate) { + if (table.database.dialect.supportsReadOnlyUpdate()) { connection.setReadOnly(true); } /* diff --git a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/TemporalValueGetterTest.java b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/TemporalValueGetterTest.java index ea268fc614..5301e495d5 100644 --- a/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/TemporalValueGetterTest.java +++ b/endorsed/src/org.apache.sis.storage.sql/test/org/apache/sis/storage/sql/feature/TemporalValueGetterTest.java @@ -66,7 +66,7 @@ public final class TemporalValueGetterTest extends TestOnAllDatabases { */ @Override protected void test(final TestDatabase database, final boolean noschema) throws Exception { - supportsJavaTime = database.dialect.supportsJavaTime; + supportsJavaTime = database.dialect.supportsJavaTime(); try (Connection connection = database.source.getConnection()) { if (!noschema) { connection.setSchema(SCHEMA);