sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] branch geoapi-4.0 updated: Provides an estimation of the number of features, when available.
Date Thu, 12 Jul 2018 20:00:38 GMT
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 836f5f7  Provides an estimation of the number of features, when available.
836f5f7 is described below

commit 836f5f704ba96b9f149d1b499bba74d9f36f9c83
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Jul 12 20:43:10 2018 +0200

    Provides an estimation of the number of features, when available.
---
 .../sis/internal/metadata/sql/Reflection.java      | 14 +++++++++++
 .../apache/sis/internal/sql/feature/Database.java  | 21 ++++++++++++----
 .../org/apache/sis/internal/sql/feature/Table.java | 28 ++++++++++++++++++++++
 .../sis/internal/sql/feature/TableReference.java   | 14 ++++++++++-
 .../java/org/apache/sis/storage/sql/SQLStore.java  | 28 +++++++++++++++-------
 5 files changed, 91 insertions(+), 14 deletions(-)

diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Reflection.java
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Reflection.java
index ffdee2e..962a2eb 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Reflection.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Reflection.java
@@ -195,6 +195,20 @@ public final class Reflection {
     public static final String INDEX_NAME = "INDEX_NAME";
 
     /**
+     * Index type: statistics, clustered, hashed or other.
+     *
+     * <p>Values in this column are short integers ({@code short}) rather than {@code
String}.</p>
+     */
+    public static final String TYPE = "TYPE";
+
+    /**
+     * Number of rows in the table, or number of unique values in the index.
+     *
+     * <p>Values in this column are long integers ({@code long}) rather than {@code
String}.</p>
+     */
+    public static final String CARDINALITY = "CARDINALITY";
+
+    /**
      * Do not allow instantiation of this class.
      */
     private Reflection() {
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
index 59b0047..9faadbd 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Database.java
@@ -24,10 +24,9 @@ import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
-import org.opengis.util.LocalName;
 import org.opengis.util.GenericName;
-import org.apache.sis.util.ArraysExt;
 import org.apache.sis.internal.metadata.sql.Reflection;
+import org.apache.sis.internal.storage.MetadataBuilder;
 import org.apache.sis.internal.util.UnmodifiableArrayList;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.sql.SQLStore;
@@ -111,9 +110,7 @@ public final class Database {
         final Analyzer analyzer = new Analyzer(connection.getMetaData(), listeners, store.getLocale());
         final String[] tableTypes = getTableTypes(analyzer.metadata);
         for (final GenericName tableName : tableNames) {
-            String[] names = tableName.getParsedNames().stream().map(LocalName::toString).toArray(String[]::new);
-            ArraysExt.reverse(names);               // Reorganize in (catalog, schemaPattern,
tablePattern) order.
-            names = ArraysExt.resize(names, 3);     // Pad with null values if necessary.
+            final String[] names = TableReference.splitName(tableName);
             try (ResultSet reflect = analyzer.metadata.getTables(names[2], names[1], names[0],
tableTypes)) {
                 while (reflect.next()) {
                     final String table = reflect.getString(Reflection.TABLE_NAME);
@@ -163,6 +160,20 @@ public final class Database {
     }
 
     /**
+     * Lists the tables in the given metadata.
+     *
+     * @param  metadata  information about the database.
+     * @param  builder   where to add information about the tables.
+     * @throws SQLException if an error occurred while fetching table information.
+     */
+    public final void listTables(final DatabaseMetaData metadata, final MetadataBuilder builder)
throws SQLException {
+        for (final Table table : tables) {
+            final long n = table.countRows(metadata, false);
+            builder.addFeatureType(table.getType(), (n > 0 && n <= Integer.MAX_VALUE)
? (int) n : null);
+        }
+    }
+
+    /**
      * Returns all tables in declaration order.
      * The list contains only the tables explicitly requested at construction time.
      *
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Table.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Table.java
index 877b931..7e4332c 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Table.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/Table.java
@@ -23,6 +23,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.stream.Stream;
@@ -293,6 +294,33 @@ final class Table extends AbstractFeatureSet {
     }
 
     /**
+     * Returns the number of rows, or -1 if unknown. Note that some database drivers returns
0,
+     * so it is better to consider 0 as "unknown" too.
+     *
+     * @param  metadata     information about the database.
+     * @param  approximate  whether approximative or outdated values are acceptable.
+     * @return number of rows (may be approximative), or -1 if unknown.
+     */
+    final long countRows(final DatabaseMetaData metadata, final boolean approximate) throws
SQLException {
+        long count = -1;
+        final String[] names = TableReference.splitName(featureType.getName());
+        try (ResultSet reflect = metadata.getIndexInfo(names[2], names[1], names[0], false,
approximate)) {
+            while (reflect.next()) {
+                final long n = reflect.getLong(Reflection.CARDINALITY);
+                if (!reflect.wasNull()) {
+                    if (reflect.getShort(Reflection.TYPE) == DatabaseMetaData.tableIndexStatistic)
{
+                        return n;       // "Index statistic" type provides the number of
rows in the table.
+                    }
+                    if (n > count) {    // Other index types may be inaccurate.
+                        count = n;
+                    }
+                }
+            }
+        }
+        return count;
+    }
+
+    /**
      * Returns a stream of all features contained in this dataset.
      *
      * @param  parallel  {@code true} for a parallel stream (if supported), or {@code false}
for a sequential stream.
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/TableReference.java
b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/TableReference.java
index aa9d9ac..97dcac7 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/TableReference.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/internal/sql/feature/TableReference.java
@@ -21,10 +21,12 @@ import java.util.HashMap;
 import java.util.Objects;
 import java.util.function.Consumer;
 import org.opengis.util.LocalName;
+import org.opengis.util.GenericName;
 import org.apache.sis.storage.sql.SQLStoreProvider;
 import org.apache.sis.util.collection.DefaultTreeTable;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.collection.TreeTable;
+import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.Debug;
 
 
@@ -71,9 +73,19 @@ public class TableReference {
     }
 
     /**
+     * Splits the given name in (catalog, schema, table) tuple.
+     * Those components are returned in an array of length 3, in reverse order.
+     */
+    static String[] splitName(final GenericName name) {
+        String[] parts = name.getParsedNames().stream().map(LocalName::toString).toArray(String[]::new);
+        ArraysExt.reverse(parts);               // Reorganize in (catalog, schemaPattern,
tablePattern) order.
+        return ArraysExt.resize(parts, 3);      // Pad with null values if necessary.
+    }
+
+    /**
      * Creates a name for the feature type backed by this table.
      */
-    final LocalName getName(final Analyzer analyzer) {
+    final GenericName getName(final Analyzer analyzer) {
         return analyzer.nameFactory.createLocalName(analyzer.namespace(catalog, schema),
table);
     }
 
diff --git a/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java b/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java
index b93fcd9..129edf3 100644
--- a/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java
+++ b/storage/sis-sqlstore/src/main/java/org/apache/sis/storage/sql/SQLStore.java
@@ -24,7 +24,6 @@ import org.opengis.util.GenericName;
 import org.opengis.metadata.Metadata;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.metadata.spatial.SpatialRepresentationType;
-import org.apache.sis.storage.FeatureSet;
 import org.apache.sis.storage.Resource;
 import org.apache.sis.storage.Aggregate;
 import org.apache.sis.storage.DataStore;
@@ -147,6 +146,19 @@ public class SQLStore extends DataStore implements Aggregate {
     }
 
     /**
+     * Returns the database model, analyzing the database schema when first needed.
+     * This method performs the same work than {@link #model()}, but using an existing connection.
+     *
+     * @param c  connection to the database.
+     */
+    private synchronized Database model(final Connection c) throws DataStoreException, SQLException
{
+        if (model == null) {
+            model = new Database(this, c, tableNames, listeners);
+        }
+        return model;
+    }
+
+    /**
      * Returns information about the dataset as a whole. The returned metadata object can
contain information
      * such as the list of feature types.
      *
@@ -156,16 +168,16 @@ public class SQLStore extends DataStore implements Aggregate {
     @Override
     public synchronized Metadata getMetadata() throws DataStoreException {
         if (metadata == null) {
-            final Database model = model();
             final MetadataBuilder builder = new MetadataBuilder();
             builder.addSpatialRepresentation(SpatialRepresentationType.TEXT_TABLE);
-            if (model.hasGeometry) {
-                builder.addSpatialRepresentation(SpatialRepresentationType.VECTOR);
-            }
-            for (final Resource r : model.tables()) {
-                if (r instanceof FeatureSet) {
-                    builder.addFeatureType(((FeatureSet) r).getType(), null);
+            try (Connection c = source.getConnection()) {
+                final Database model = model(c);
+                if (model.hasGeometry) {
+                    builder.addSpatialRepresentation(SpatialRepresentationType.VECTOR);
                 }
+                model.listTables(c.getMetaData(), builder);
+            } catch (SQLException e) {
+                throw new DataStoreException(Exceptions.unwrap(e));
             }
             metadata = builder.build(true);
         }


Mime
View raw message