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.

Reply via email to