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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new 7c2e16ac90 Make the information about database version accessible through public API. 7c2e16ac90 is described below commit 7c2e16ac904881d0ab3dfa2010eb527a1439bc20 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Mar 13 20:26:19 2025 +0100 Make the information about database version accessible through public API. --- .../main/org/apache/sis/storage/sql/SQLStore.java | 18 ++++++- .../apache/sis/storage/sql/feature/Database.java | 62 +++++++++++++++------- .../apache/sis/storage/sql/postgis/Postgres.java | 33 ++---------- 3 files changed, 66 insertions(+), 47 deletions(-) diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java index 6e2f0361b9..8b7c08cc6f 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/SQLStore.java @@ -16,6 +16,7 @@ */ package org.apache.sis.storage.sql; +import java.util.Map; import java.util.Locale; import java.util.Optional; import java.util.Collection; @@ -55,6 +56,7 @@ import org.apache.sis.util.iso.Names; import org.apache.sis.util.privy.Strings; import org.apache.sis.setup.GeometryLibrary; import org.apache.sis.setup.OptionKey; +import org.apache.sis.util.Version; /** @@ -415,12 +417,26 @@ public abstract class SQLStore extends DataStore implements Aggregate { return current; } + /** + * Returns the version of the database software, together with versions of extensions if any. + * For example, in the case of a database on PostgreSQL, this map may contain two entries: + * the first one with the "PostgreSQL" key, optionally followed by an entry with the "PostGIS" key. + * + * @return version of the database software as the first entry, followed by versions of extensions if any. + * @throws DataStoreException if an error occurred while fetching the metadata. + * + * @since 1.5 + */ + public Map<String, Version> getDatabaseSoftwareVersions() throws DataStoreException { + return model().getDatabaseSoftwareVersions(); + } + /** * Returns information about the dataset as a whole. The returned metadata object can contain information * such as the list of feature types. * * @return information about the dataset. - * @throws DataStoreException if an error occurred while reading the data. + * @throws DataStoreException if an error occurred while fetching the metadata. */ @Override public synchronized Metadata getMetadata() throws DataStoreException { 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 983db64e53..e61f12d6ba 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 @@ -21,6 +21,7 @@ import java.util.List; import java.util.EnumSet; import java.util.HashMap; import java.util.WeakHashMap; +import java.util.LinkedHashMap; import java.util.Locale; import java.util.Optional; import java.util.logging.LogRecord; @@ -32,6 +33,7 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.sql.Types; +import java.util.Collections; import javax.sql.DataSource; import org.opengis.util.GenericName; import org.opengis.geometry.Envelope; @@ -54,8 +56,10 @@ import org.apache.sis.storage.sql.SQLStore; import org.apache.sis.storage.sql.ResourceDefinition; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.util.Debug; +import org.apache.sis.util.Version; import org.apache.sis.util.collection.TreeTable; import org.apache.sis.util.collection.Cache; +import org.apache.sis.util.privy.Strings; import org.apache.sis.util.privy.UnmodifiableArrayList; import org.apache.sis.util.resources.Vocabulary; import org.opengis.metadata.citation.PresentationForm; @@ -109,6 +113,16 @@ public class Database<G> extends Syntax { */ protected final DataSource source; + /** + * Version of the database software, together with versions of extensions if any. + * For example, in the case of a PostGIS database, this map should contain two entries: + * one with the "PostgreSQL" key and one with the "PostGIS" key, preferably in that order. + * This map is for information purpose only and should be completed by subclass constructors. + * + * @see #getDatabaseSoftwareVersions() + */ + protected final Map<String, Version> softwareVersions; + /** * The factory to use for creating geometric objects. * For example, the geometry implementations may be ESRI, JTS or Java2D objects. @@ -294,6 +308,23 @@ public class Database<G> extends Syntax { supportsJavaTime = dialect.supportsJavaTime(); crsEncodings = EnumSet.noneOf(CRSEncoding.class); transactionLocks = dialect.supportsConcurrency() ? null : locks; + softwareVersions = new LinkedHashMap<>(4); + final String product = Strings.trimOrNull(metadata.getDatabaseProductName()); + final String version = Strings.trimOrNull(metadata.getDatabaseProductVersion()); + if (product != null || version != null) { + softwareVersions.put(product, version != null ? new Version(version) : null); + } + } + + /** + * Returns the version of the database software, together with versions of extensions if any. + * For example, in the case of a database on PostgreSQL, this map may contain two entries: + * the first one with the "PostgreSQL" key, optionally followed by an entry with the "PostGIS" key. + * + * @return version of the database software as the first entry, followed by versions of extensions if any. + */ + public final Map<String, Version> getDatabaseSoftwareVersions() { + return Collections.unmodifiableMap(softwareVersions); } /** @@ -479,30 +510,25 @@ public class Database<G> extends Syntax { builder.addFeatureType(table.featureType, table.countRows(metadata, false, false)); } builder.addFormatName((spatialSchema != null) ? spatialSchema.name : "SQL database"); - String server = metadata.getDatabaseProductName(); - if (server != null && !server.isBlank()) { - CharSequence description = server; - final String version = metadata.getDatabaseProductVersion(); + CharSequence description = null; + for (Map.Entry<String, Version> entry : softwareVersions.entrySet()) { + CharSequence software = entry.getKey(); + if (software == null) software = "?"; + Version version = entry.getValue(); if (version != null) { - description = Vocabulary.formatInternational(Vocabulary.Keys.Version_2, server, version); + software = Vocabulary.formatInternational(Vocabulary.Keys.Version_2, software, version); + } + if (description == null) { + description = software; + } else { + description = Vocabulary.formatInternational(Vocabulary.Keys.With_2, description, software); + // Above assumes that there is no more than two entries. } - builder.addFormatCitationDetails(completeDatabaseVersion(description)); } + builder.addFormatCitationDetails(description); builder.addFormatReaderSIS("SQL"); // Value of SQLStoreProvider.NAME. } - /** - * Completes the given database version with information such as the version of the geospatial extension. - * For example, in the case of the PostgreSL database, this will add the PostGIS version. - * The default implementation returns the given text unchanged. - * - * @param version name and version of the database. - * @return given text, optionally completed with additional information. - */ - protected CharSequence completeDatabaseVersion(CharSequence version) { - return version; - } - /** * Returns all tables in declaration order. * The list contains only the tables explicitly requested at construction time. diff --git a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java index b5a6ab50ea..7507ebf31d 100644 --- a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java +++ b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/postgis/Postgres.java @@ -42,7 +42,6 @@ import org.apache.sis.storage.sql.feature.SpatialSchema; import org.apache.sis.metadata.sql.privy.Dialect; import org.apache.sis.storage.event.StoreListeners; import org.apache.sis.util.Version; -import org.apache.sis.util.resources.Vocabulary; /** @@ -56,15 +55,6 @@ import org.apache.sis.util.resources.Vocabulary; * @author Martin Desruisseaux (Geomatys) */ public final class Postgres<G> extends Database<G> { - /** - * Version of PostGIS extension, or {@code null} if PostGIS has not been found. - * Not to be confused with the version of PostgreSQL server, which is given by - * another class provided in the PostgreSQL JDBC driver. - * - * @see org.postgresql.core.ServerVersion - */ - private final Version postgisVersion; - /** * Creates a new session for a PostGIS database. * @@ -83,19 +73,20 @@ public final class Postgres<G> extends Database<G> { throws SQLException { super(source, metadata, dialect, geomLibrary, contentLocale, listeners, locks); - Version version = null; try (Statement st = metadata.getConnection().createStatement(); ResultSet result = st.executeQuery("SELECT public.PostGIS_version();")) { while (result.next()) { - version = parseVersion(result.getString(1)); - if (version != null) break; + final Version version = parseVersion(result.getString(1)); + if (version != null) { + softwareVersions.put("PostGIS", version); + break; + } } } catch (SQLException e) { log(Resources.forLocale(null).getLogRecord(Level.CONFIG, Resources.Keys.SpatialExtensionNotFound_1, "PostGIS")); } - postgisVersion = version; } /** @@ -121,20 +112,6 @@ public final class Postgres<G> extends Database<G> { return null; } - /** - * Completes the given database version with information about PostGIS version. - * - * @param version name and version of the database. - * @return given text, completed with PostGIS information if present. - */ - @Override - protected CharSequence completeDatabaseVersion(CharSequence version) { - if (version != null) { - return Vocabulary.formatInternational(Vocabulary.Keys.With_2, version, "PostGIS " + postgisVersion); - } - return version; - } - /** * Returns a function for getting values from a column having the given definition. * The given definition should include data SQL type and type name.