You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2018/07/04 16:08:13 UTC

[sis] branch geoapi-4.0 updated (22e0930 -> 8b9558f)

This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a change to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git.


    from 22e0930  Copy Smaniotto Enzo's work from https://issues.apache.org/jira/browse/SIS-417. This work will need major review and cleanup for exception handlings, factorization, etc. This cleanup is deferred to a later time.
     new 188ba7c  Regroup the SQL classes in "org.apache.sis.internal.sql.feature" package.
     new e8631df  Begins a review of storage/sis-sql module. The constants by database reflection API moved to sis-metadata internal package, for sharing by other classes doing similar operations.
     new 8b9558f  Leverage Reflection constants in other modules.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../sis/internal/metadata/sql/Reflection.java      | 190 +++++
 .../sis/internal/metadata/sql/SQLBuilder.java      |  16 +-
 .../apache/sis/metadata/sql/MetadataSource.java    |   3 +-
 .../apache/sis/metadata/sql/MetadataWriter.java    |  11 +-
 .../sis/referencing/factory/sql/SQLTranslator.java |   9 +-
 .../referencing/factory/sql/EPSGInstallerTest.java |   3 +-
 .../internal/sql/SingleAttributeTypeBuilder.java   | 260 -------
 .../sql/{reverse => feature}/CachedResultSet.java  |   2 +-
 .../sql/{reverse => feature}/ColumnMetaModel.java  |  17 +-
 .../sis/internal/sql/feature/DataBaseModel.java    | 717 +++++++++++++++++++
 .../sis/internal/sql/{ => feature}/Dialect.java    |  35 +-
 .../sql/{reverse => feature}/InsertRelation.java   |   2 +-
 .../sql/{reverse => feature}/MetaModel.java        |   2 +-
 .../sql/{reverse => feature}/PrimaryKey.java       |   3 +-
 .../sql/{reverse => feature}/QueryFeatureSet.java  |   2 +-
 .../{reverse => feature}/RelationMetaModel.java    |   2 +-
 .../sql/{reverse => feature}/SchemaMetaModel.java  |   2 +-
 .../sql/{reverse => feature}/TableMetaModel.java   |   2 +-
 .../internal/sql/{ => feature}/package-info.java   |   2 +-
 .../sis/internal/sql/postgres/PostgresDialect.java |  27 +-
 .../sis/internal/sql/postgres/PostgresStore.java   |   4 +-
 .../sis/internal/sql/reverse/DataBaseModel.java    | 769 ---------------------
 .../internal/sql/reverse/MetaDataConstants.java    | 515 --------------
 .../sis/internal/sql/reverse/package-info.java     |  32 -
 .../java/org/apache/sis/storage/sql/SQLStore.java  |   2 +-
 .../org/apache/sis/storage/sql/package-info.java   |   2 +-
 26 files changed, 962 insertions(+), 1669 deletions(-)
 create mode 100644 core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Reflection.java
 delete mode 100644 storage/sis-sql/src/main/java/org/apache/sis/internal/sql/SingleAttributeTypeBuilder.java
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/CachedResultSet.java (98%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/ColumnMetaModel.java (93%)
 create mode 100644 storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{ => feature}/Dialect.java (81%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/InsertRelation.java (96%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/MetaModel.java (98%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/PrimaryKey.java (97%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/QueryFeatureSet.java (98%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/RelationMetaModel.java (98%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/SchemaMetaModel.java (97%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{reverse => feature}/TableMetaModel.java (98%)
 rename storage/sis-sql/src/main/java/org/apache/sis/internal/sql/{ => feature}/package-info.java (96%)
 delete mode 100644 storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/DataBaseModel.java
 delete mode 100644 storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaDataConstants.java
 delete mode 100644 storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/package-info.java


[sis] 01/03: Regroup the SQL classes in "org.apache.sis.internal.sql.feature" package.

Posted by de...@apache.org.
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 188ba7ca1d572801146ff9c1420e010f91d94212
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Tue Jul 3 17:21:25 2018 +0200

    Regroup the SQL classes in "org.apache.sis.internal.sql.feature" package.
---
 .../sql/{reverse => feature}/CachedResultSet.java  |  2 +-
 .../sql/{reverse => feature}/ColumnMetaModel.java  |  3 +-
 .../sql/{reverse => feature}/DataBaseModel.java    |  6 ++--
 .../sis/internal/sql/{ => feature}/Dialect.java    |  3 +-
 .../sql/{reverse => feature}/InsertRelation.java   |  2 +-
 .../{reverse => feature}/MetaDataConstants.java    |  2 +-
 .../sql/{reverse => feature}/MetaModel.java        |  2 +-
 .../sql/{reverse => feature}/PrimaryKey.java       |  3 +-
 .../sql/{reverse => feature}/QueryFeatureSet.java  |  2 +-
 .../{reverse => feature}/RelationMetaModel.java    |  2 +-
 .../sql/{reverse => feature}/SchemaMetaModel.java  |  2 +-
 .../{ => feature}/SingleAttributeTypeBuilder.java  |  4 +--
 .../sql/{reverse => feature}/TableMetaModel.java   |  2 +-
 .../internal/sql/{ => feature}/package-info.java   |  2 +-
 .../sis/internal/sql/postgres/PostgresDialect.java |  6 ++--
 .../sis/internal/sql/postgres/PostgresStore.java   |  4 +--
 .../sis/internal/sql/reverse/package-info.java     | 32 ----------------------
 .../java/org/apache/sis/storage/sql/SQLStore.java  |  2 +-
 .../org/apache/sis/storage/sql/package-info.java   |  2 +-
 19 files changed, 23 insertions(+), 60 deletions(-)

diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/CachedResultSet.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/CachedResultSet.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/CachedResultSet.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/CachedResultSet.java
index 13c653a..4aba4fc 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/CachedResultSet.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/CachedResultSet.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/ColumnMetaModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/ColumnMetaModel.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java
index 5970f9e..6ff5453 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/ColumnMetaModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java
@@ -14,9 +14,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
-import org.apache.sis.internal.sql.Dialect;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/DataBaseModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
similarity index 99%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/DataBaseModel.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
index 0823140..5f73ec4 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/DataBaseModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
@@ -45,9 +45,7 @@ import org.apache.sis.feature.builder.AttributeTypeBuilder;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
 import org.apache.sis.internal.feature.Geometries;
-import org.apache.sis.internal.sql.Dialect;
-import org.apache.sis.internal.sql.SingleAttributeTypeBuilder;
-import org.apache.sis.internal.sql.reverse.MetaDataConstants.*;
+import org.apache.sis.internal.sql.feature.MetaDataConstants.*;
 import org.apache.sis.storage.sql.SQLStore;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/Dialect.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/Dialect.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java
index fcc6cb9..17f9547 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/Dialect.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java
@@ -14,14 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql;
+package org.apache.sis.internal.sql.feature;
 
 import java.util.Map;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.internal.sql.reverse.ColumnMetaModel;
 import org.apache.sis.storage.DataStoreException;
 
 
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/InsertRelation.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/InsertRelation.java
similarity index 96%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/InsertRelation.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/InsertRelation.java
index 47becf9..2d494d0 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/InsertRelation.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/InsertRelation.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import org.opengis.feature.Feature;
 
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaDataConstants.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaDataConstants.java
similarity index 99%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaDataConstants.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaDataConstants.java
index d8eccef..393785b 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaDataConstants.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaDataConstants.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 
 /**
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaModel.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaModel.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaModel.java
index 94aa43f..880437e 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/MetaModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.util.Iterator;
 import org.apache.sis.util.CharSequences;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/PrimaryKey.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/PrimaryKey.java
similarity index 97%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/PrimaryKey.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/PrimaryKey.java
index 543082b..ff2667a 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/PrimaryKey.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/PrimaryKey.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
@@ -22,7 +22,6 @@ import java.sql.SQLException;
 import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
-import org.apache.sis.internal.sql.Dialect;
 import org.apache.sis.storage.DataStoreException;
 
 
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/QueryFeatureSet.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/QueryFeatureSet.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
index d40fe67..d2ce7d0 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/QueryFeatureSet.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/QueryFeatureSet.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/RelationMetaModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/RelationMetaModel.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/RelationMetaModel.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/RelationMetaModel.java
index ed64d6c..ab09cf3 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/RelationMetaModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/RelationMetaModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import org.apache.sis.util.ArgumentChecks;
 
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/SchemaMetaModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SchemaMetaModel.java
similarity index 97%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/SchemaMetaModel.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SchemaMetaModel.java
index f53866a..21b4a60 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/SchemaMetaModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SchemaMetaModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.util.Collection;
 import java.util.HashMap;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/SingleAttributeTypeBuilder.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SingleAttributeTypeBuilder.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/SingleAttributeTypeBuilder.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SingleAttributeTypeBuilder.java
index 9179971..ad22d65 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/SingleAttributeTypeBuilder.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SingleAttributeTypeBuilder.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql;
+package org.apache.sis.internal.sql.feature;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -44,7 +44,7 @@ import static org.apache.sis.feature.AbstractIdentifiedType.*;
  *
  * @todo Is this class really needed?
  */
-public class SingleAttributeTypeBuilder {
+public final class SingleAttributeTypeBuilder {
     /**
      * Properties (name, description, …) to give to the attribute type constructor.
      */
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/TableMetaModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/TableMetaModel.java
similarity index 98%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/TableMetaModel.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/TableMetaModel.java
index e80bf45..efb4239 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/TableMetaModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/TableMetaModel.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.internal.sql.reverse;
+package org.apache.sis.internal.sql.feature;
 
 import java.util.ArrayList;
 import java.util.Collection;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/package-info.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/package-info.java
similarity index 96%
rename from storage/sis-sql/src/main/java/org/apache/sis/internal/sql/package-info.java
rename to storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/package-info.java
index 6c3aa9c..4b8369b 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/package-info.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/package-info.java
@@ -29,4 +29,4 @@
  * @since   1.0
  * @module
  */
-package org.apache.sis.internal.sql;
+package org.apache.sis.internal.sql.feature;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java
index 6eb207d..6bd82cd 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java
@@ -23,10 +23,10 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.internal.sql.SingleAttributeTypeBuilder;
-import org.apache.sis.internal.sql.reverse.ColumnMetaModel;
+import org.apache.sis.internal.sql.feature.SingleAttributeTypeBuilder;
+import org.apache.sis.internal.sql.feature.ColumnMetaModel;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.internal.sql.Dialect;
+import org.apache.sis.internal.sql.feature.Dialect;
 
 
 /**
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresStore.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresStore.java
index be3b7e0..5174621 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresStore.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresStore.java
@@ -23,8 +23,8 @@ import org.apache.sis.storage.sql.SQLQuery;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.event.ChangeEvent;
 import org.apache.sis.storage.event.ChangeListener;
-import org.apache.sis.internal.sql.reverse.DataBaseModel;
-import org.apache.sis.internal.sql.reverse.QueryFeatureSet;
+import org.apache.sis.internal.sql.feature.DataBaseModel;
+import org.apache.sis.internal.sql.feature.QueryFeatureSet;
 import org.apache.sis.storage.FeatureSet;
 import org.apache.sis.storage.StorageConnector;
 
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/package-info.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/package-info.java
deleted file mode 100644
index 46773e7..0000000
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/reverse/package-info.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-
-/**
- * Inspect a database schema.
- *
- * <STRONG>Do not use!</STRONG>
- *
- * This package is for internal use by SIS only. Classes in this package
- * may change in incompatible ways in any future version without notice.
- *
- * @author  Johann Sorel (Geomatys)
- * @version 1.0
- * @since   1.0
- * @module
- */
-package org.apache.sis.internal.sql.reverse;
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/SQLStore.java b/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/SQLStore.java
index 37369d7..991c4b1 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/SQLStore.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/SQLStore.java
@@ -24,7 +24,7 @@ import org.apache.sis.storage.StorageConnector;
 
 
 /**
- * Parent store class for {@code DataStore} implementations using JDBC backend.
+ * A data store capable to read and create features from a database.
  *
  * <div class="warning">This is an experimental class,
  * not yet target for any Apache SIS release at this time.</div>
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/package-info.java b/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/package-info.java
index e749a39..4c3499b 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/package-info.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/storage/sql/package-info.java
@@ -17,7 +17,7 @@
 
 
 /**
- * Data stores that create features from a JDBC connection to a database.
+ * Data store capable to read and create features from a JDBC connection to a database.
  *
  * <div class="warning">This is an experimental package,
  * not yet target for any Apache SIS release at this time.</div>


[sis] 02/03: Begins a review of storage/sis-sql module. The constants by database reflection API moved to sis-metadata internal package, for sharing by other classes doing similar operations.

Posted by de...@apache.org.
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 e8631df70bae6656aaa89c5b7e5ff832dfd6cde7
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Jul 4 16:53:40 2018 +0200

    Begins a review of storage/sis-sql module. The constants by database reflection API moved to sis-metadata internal package, for sharing by other classes doing similar operations.
---
 .../sis/internal/metadata/sql/Reflection.java      | 185 ++++++
 .../sis/internal/metadata/sql/SQLBuilder.java      |  16 +-
 .../sis/internal/sql/feature/ColumnMetaModel.java  |  14 +-
 .../sis/internal/sql/feature/DataBaseModel.java    | 620 ++++++++++-----------
 .../apache/sis/internal/sql/feature/Dialect.java   |  32 +-
 .../internal/sql/feature/MetaDataConstants.java    | 515 -----------------
 .../sql/feature/SingleAttributeTypeBuilder.java    | 260 ---------
 .../sis/internal/sql/postgres/PostgresDialect.java |  25 +-
 8 files changed, 494 insertions(+), 1173 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
new file mode 100644
index 0000000..45f21b2
--- /dev/null
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/Reflection.java
@@ -0,0 +1,185 @@
+/*
+ * 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.internal.metadata.sql;
+
+import java.sql.DatabaseMetaData;
+
+
+/**
+ * Column names used in database reflection API. Reflection provides information about schemas, tables, columns,
+ * constraints, <i>etc.</i> in the form of database tables. The main JDBC methods for those reflections are:
+ *
+ * <ul>
+ *   <li>{@link DatabaseMetaData#getSchemas()}</li>
+ *   <li>{@link DatabaseMetaData#getTables(String, String, String, String[])}</li>
+ *   <li>{@link DatabaseMetaData#getColumns(String, String, String, String)}</li>
+ * </ul>
+ *
+ * This class enumerates all the constants used by Apache SIS, and only those constants (this give a way to have
+ * an overview of which database metadata are needed by SIS). Unless specified otherwise, the columns with those
+ * names contain only {@code String} values. The main exceptions are {@link #DATA_TYPE}, {@link #COLUMN_SIZE} and
+ * {@link #DELETE_RULE}, which contain integers.
+ *
+ * @author  Johann Sorel (Geomatys)
+ * @version 1.0
+ * @since   1.0
+ * @module
+ */
+public final class Reflection {
+    /**
+     * The {@value} key for getting a schema name. This column appears in all reflection
+     * operations (listing schemas, tables, columns, constraints, <i>etc.</i>) used by SIS.
+     * The value in that column may be null.
+     */
+    public static final String TABLE_SCHEM = "TABLE_SCHEM";
+
+    /**
+     * The {@value} key for getting a table name. This column appears in most reflection
+     * operations (listing tables, columns, constraints, <i>etc.</i>) used by SIS.
+     */
+    public static final String TABLE_NAME = "TABLE_NAME";
+
+    /**
+     * The {@value} key for getting a table type. The values that may appear in this column
+     * are listed by {@link DatabaseMetaData#getTableTypes()}. Typical values are "TABLE",
+     * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
+     */
+    public static final String TABLE_TYPE = "TABLE_TYPE";
+
+    /**
+     * The {@value} key for getting a column name.
+     */
+    public static final String COLUMN_NAME = "COLUMN_NAME";
+
+    /**
+     * The {@value} key for getting the data type as one of {@link java.sql.Types} constants.
+     *
+     * <p>Values in this column are integers ({@code int}) rather than {@code String}.</p>
+     */
+    public static final String DATA_TYPE = "DATA_TYPE";
+
+    /**
+     * Data source dependent type name. For a UDT the type name is fully qualified.
+     */
+    public static final String TYPE_NAME = "TYPE_NAME";
+
+    /**
+     * The {@value} key for the size for of a column. For numeric data, this is the maximum precision.
+     * For character data, this is the length in characters.
+     *
+     * <p>Values in this column are integers ({@code int}) rather than {@code String}.</p>
+     */
+    public static final String COLUMN_SIZE = "COLUMN_SIZE";
+
+    /**
+     * The {@value} key for the number of fractional digits.
+     * Null is returned for data types where {@code DECIMAL_DIGITS} is not applicable.
+     *
+     * <p>Values in this column are integers ({@code int}) rather than {@code String}.</p>
+     */
+    public static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";
+
+    /**
+     * The {@value} key for the nullability of a column. Possible values are {@code "YES"} if
+     * the parameter can include NULLs, {@code "NO"} if the parameter cannot include NULLs,
+     * and empty string if the nullability for the parameter is unknown.
+     */
+    public static final String IS_NULLABLE = "IS_NULLABLE";
+
+    /**
+     * The {@value} key for indicating whether this column is auto incremented. Possible values
+     * are {@code "YES"} if the column is auto incremented, {@code "NO"} if the column is not
+     * auto incremented, or empty string if whether the column is auto incremented is unknown.
+     */
+    public static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
+
+    /**
+     * The {@value} key for comment describing columns.
+     * Values in this column may be null.
+     */
+    public static final String REMARKS = "REMARKS";
+
+    /**
+     * The {@value} key for primary key name.
+     * Values in this column may be null.
+     */
+    public static final String PK_NAME = "PK_NAME";
+
+    /**
+     * The {@value} key for the primary key table schema being imported.
+     * Values in this column may be null.
+     */
+    public static final String PKTABLE_SCHEM = "PKTABLE_SCHEM";
+
+    /**
+     * The {@value} key for the primary key table name being imported.
+     */
+    public static final String PKTABLE_NAME = "PKTABLE_NAME";
+
+    /**
+     * The {@value} key for the primary key column name being imported.
+     */
+    public static final String PKCOLUMN_NAME = "PKCOLUMN_NAME";
+
+    /**
+     * The {@value} key for foreign key name.
+     * Values in this column may be null.
+     */
+    public static final String FK_NAME = "FK_NAME";
+
+    /**
+     * The {@value} key for the foreign key table schema.
+     * Values in this column may be null.
+     */
+    public static final String FKTABLE_SCHEM = "FKTABLE_SCHEM";
+
+    /**
+     * The {@value} key for the foreign key table name.
+     */
+    public static final String FKTABLE_NAME = "FKTABLE_NAME";
+
+    /**
+     * The {@value} key for the foreign key column name.
+     */
+    public static final String FKCOLUMN_NAME = "FKCOLUMN_NAME";
+
+    /**
+     * The {@value} key for what happens to the foreign key when primary is deleted.
+     * Possible values are:
+     * <ul>
+     *   <li>{@code importedKeyNoAction}   — do not allow delete of primary key if it has been imported.</li>
+     *   <li>{@code importedKeyCascade}    — delete rows that import a deleted key.</li>
+     *   <li>{@code importedKeySetNull}    — change imported key to NULL if its primary key has been deleted.</li>
+     *   <li>{@code importedKeySetDefault} — change imported key to default if its primary key has been deleted.</li>
+     * </ul>
+     *
+     * <p>Values in this column are short integers ({@code short}) rather than {@code String}.</p>
+     */
+    public static final String DELETE_RULE = "DELETE_RULE";
+
+    /**
+     * The {@value} key for the name of the index.
+     * Values in this column may be null.
+     */
+    public static final String INDEX_NAME = "INDEX_NAME";
+
+    /**
+     * Do not allow instantiation of this class.
+     */
+    private Reflection() {
+    }
+}
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java
index 56661c5..adc0352 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/SQLBuilder.java
@@ -46,6 +46,14 @@ public class SQLBuilder {
     private final String quote;
 
     /**
+     * Whether the schema name should be written between quotes. If {@code false},
+     * we will let the database engine uses its default lower case / upper case policy.
+     *
+     * @see #appendIdentifier(String, String)
+     */
+    private final boolean quoteSchema;
+
+    /**
      * The string that can be used to escape wildcard characters.
      * This is the value returned by {@link DatabaseMetaData#getSearchStringEscape()}.
      */
@@ -57,14 +65,6 @@ public class SQLBuilder {
     private final StringBuilder buffer = new StringBuilder();
 
     /**
-     * Whether the schema name should be written between quotes. If {@code false},
-     * we will let the database engine uses its default lower case / upper case policy.
-     *
-     * @see #appendIdentifier(String, String)
-     */
-    private final boolean quoteSchema;
-
-    /**
      * Creates a new {@code SQLBuilder} initialized from the given database metadata.
      *
      * @param  metadata     the database metadata.
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java
index 6ff5453..9b86ac3 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/ColumnMetaModel.java
@@ -25,6 +25,7 @@ import java.util.UUID;
 import org.opengis.feature.AttributeType;
 import org.apache.sis.feature.DefaultAttributeType;
 import org.apache.sis.storage.DataStoreException;
+import org.apache.sis.internal.metadata.sql.SQLBuilder;
 
 
 /**
@@ -161,13 +162,14 @@ public final class ColumnMetaModel {
             // Generate value if possible.
             if (Number.class.isAssignableFrom(clazz)) {
                 // Get the maximum value in the database and increment it
-                final StringBuilder sql = new StringBuilder();
-                sql.append("SELECT 1 + MAX(");
-                dialect.encodeColumnName(sql, name);
-                sql.append(") FROM ");
-                dialect.encodeSchemaAndTableName(sql, schema, table);
+                final String sql = new SQLBuilder(cx.getMetaData(), true)
+                        .append("SELECT 1 + MAX(")
+                        .appendIdentifier(name)
+                        .append(") FROM ")
+                        .appendIdentifier(schema, table)
+                        .toString();
                 try (Statement st = cx.createStatement();
-                    ResultSet rs = st.executeQuery(sql.toString())) {
+                    ResultSet rs = st.executeQuery(sql)) {
                     rs.next();
                     next = rs.getObject(1);
                 }
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
index 5f73ec4..4e3d86d 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/DataBaseModel.java
@@ -44,8 +44,8 @@ import org.apache.sis.feature.builder.AttributeRole;
 import org.apache.sis.feature.builder.AttributeTypeBuilder;
 import org.apache.sis.feature.builder.FeatureTypeBuilder;
 import org.apache.sis.feature.builder.PropertyTypeBuilder;
+import org.apache.sis.internal.metadata.sql.Reflection;
 import org.apache.sis.internal.feature.Geometries;
-import org.apache.sis.internal.sql.feature.MetaDataConstants.*;
 import org.apache.sis.storage.sql.SQLStore;
 import org.apache.sis.storage.DataStore;
 import org.apache.sis.storage.DataStoreException;
@@ -63,17 +63,11 @@ import org.apache.sis.util.logging.WarningListeners;
  * @module
  */
 public final class DataBaseModel {
-    /**
-     * @todo Does not seem to be used yet.
-     */
-    private static final String ASSOCIATION_SEPARATOR = "→";
 
-    /**
-     * The native SRID associated to a certain descriptor
-     *
-     * @todo Does not seem to be used yet.
-     */
-    private static final String JDBC_NATIVE_SRID = "nativeSRID";
+    private static final String TYPE_TABLE = "TABLE";
+    private static final String TYPE_VIEW  = "VIEW";
+    private static final String VALUE_YES = "YES";
+    private static final String VALUE_NO = "NO";
 
     /**
      * Feature type used to mark types which are sub-types of others.
@@ -99,7 +93,6 @@ public final class DataBaseModel {
 
     //various cache while analyzing model
     private DatabaseMetaData metadata;
-    private CachedResultSet cacheSchemas;
     private CachedResultSet cacheTables;
     private CachedResultSet cacheColumns;
     private CachedResultSet cachePrimaryKeys;
@@ -135,8 +128,7 @@ public final class DataBaseModel {
     }
 
     /**
-     * Clear the model cache. A new database analyze will be made the next time
-     * it is needed.
+     * Clear the model cache. A new database analyze will be made the next time it is needed.
      */
     private synchronized void clearCache() {
         pkIndex   = new FeatureNaming<>();
@@ -191,87 +183,59 @@ public final class DataBaseModel {
         requieredSchemas = new HashSet<>();
 
         try (Connection cx = store.getDataSource().getConnection()) {
-
             metadata = cx.getMetaData();
-
-            // Cache all metadata informations, we will loop on them plenty of times ////////
-            cacheSchemas = new CachedResultSet(metadata.getSchemas(),
-                    Schema.TABLE_SCHEM);
+            /*
+             * Schema names available in the database:
+             * 1. TABLE_SCHEM   : String  =>  schema name
+             * 2. TABLE_CATALOG : String  =>  catalog name (may be null)
+             */
+            final CachedResultSet cacheSchemas = new CachedResultSet(metadata.getSchemas(),
+                    Reflection.TABLE_SCHEM);
+            /*
+             * Description of the tables available:
+             * 1. TABLE_SCHEM : String  =>  table schema (may be null)
+             * 2. TABLE_NAME  : String  =>  table name
+             * 3. TABLE_TYPE  : String  =>  table type (typically "TABLE" or "VIEW").
+             */
             cacheTables = new CachedResultSet(
-                    metadata.getTables(null,null,null,new String[]{Table.VALUE_TYPE_TABLE, Table.VALUE_TYPE_VIEW}),
-                    Table.TABLE_SCHEM,
-                    Table.TABLE_NAME,
-                    Table.TABLE_TYPE);
-            cacheColumns = new CachedResultSet(metadata.getColumns(null, null, null, "%"),
-                    Column.TABLE_SCHEM,
-                    Column.TABLE_NAME,
-                    Column.COLUMN_NAME,
-                    Column.COLUMN_SIZE,
-                    Column.DATA_TYPE,
-                    Column.TYPE_NAME,
-                    Column.IS_NULLABLE,
-                    Column.IS_AUTOINCREMENT,
-                    Column.REMARKS);
-            if (dialect.supportGlobalMetadata()) {
-                cachePrimaryKeys = new CachedResultSet(metadata.getPrimaryKeys(null, null, null),
-                        Column.TABLE_SCHEM,
-                        Column.TABLE_NAME,
-                        Column.COLUMN_NAME);
-                cacheImportedKeys = new CachedResultSet(metadata.getImportedKeys(null, null, null),
-                        ImportedKey.PK_NAME,
-                        ImportedKey.FK_NAME,
-                        ImportedKey.FKTABLE_SCHEM,
-                        ImportedKey.FKTABLE_NAME,
-                        ImportedKey.FKCOLUMN_NAME,
-                        ImportedKey.PKTABLE_SCHEM,
-                        ImportedKey.PKTABLE_NAME,
-                        ImportedKey.PKCOLUMN_NAME,
-                        ImportedKey.DELETE_RULE);
-                cacheExportedKeys = new CachedResultSet(metadata.getExportedKeys(null, null, null),
-                        ExportedKey.PK_NAME,
-                        ExportedKey.FK_NAME,
-                        ExportedKey.PKTABLE_SCHEM,
-                        ExportedKey.PKTABLE_NAME,
-                        ExportedKey.PKCOLUMN_NAME,
-                        ExportedKey.FKTABLE_SCHEM,
-                        ExportedKey.FKTABLE_NAME,
-                        ExportedKey.FKCOLUMN_NAME,
-                        ExportedKey.DELETE_RULE);
-            } else {
-                //we have to loop ourself on all schema and tables to collect informations
-                cachePrimaryKeys = new CachedResultSet();
-                cacheImportedKeys = new CachedResultSet();
-                cacheExportedKeys = new CachedResultSet();
-
-                final Iterator<Map<String,Object>> ite = cacheSchemas.records.iterator();
-                while (ite.hasNext()) {
-                    final String schemaName = (String) ite.next().get(Schema.TABLE_SCHEM);
-                    for (Map<String,Object> info : cacheTables.records) {
-                        if (!Objects.equals(info.get(Table.TABLE_SCHEM),schemaName)) continue;
-                        cachePrimaryKeys.append(metadata.getPrimaryKeys(null, schemaName, (String) info.get(Table.TABLE_NAME)),
-                            Column.TABLE_SCHEM,
-                            Column.TABLE_NAME,
-                            Column.COLUMN_NAME);
-                        cacheImportedKeys.append(metadata.getImportedKeys(null, schemaName, (String) info.get(Table.TABLE_NAME)),
-                            ImportedKey.FKTABLE_SCHEM,
-                            ImportedKey.FKTABLE_NAME,
-                            ImportedKey.FKCOLUMN_NAME,
-                            ImportedKey.PKTABLE_SCHEM,
-                            ImportedKey.PKTABLE_NAME,
-                            ImportedKey.PKCOLUMN_NAME,
-                            ImportedKey.DELETE_RULE);
-                        cacheExportedKeys.append(metadata.getExportedKeys(null, schemaName, (String) info.get(Table.TABLE_NAME)),
-                            ImportedKey.PKTABLE_SCHEM,
-                            ImportedKey.PKTABLE_NAME,
-                            ExportedKey.PKCOLUMN_NAME,
-                            ExportedKey.FKTABLE_SCHEM,
-                            ExportedKey.FKTABLE_NAME,
-                            ExportedKey.FKCOLUMN_NAME,
-                            ImportedKey.DELETE_RULE);
-                    }
-                }
-            }
-
+                    metadata.getTables(null, null, null, new String[] {TYPE_TABLE, TYPE_VIEW}),   // TODO: use metadata.getTableTypes()
+                    Reflection.TABLE_SCHEM,
+                    Reflection.TABLE_NAME,
+                    Reflection.TABLE_TYPE);
+            cacheColumns = new CachedResultSet(metadata.getColumns(null, null, null, null),
+                    Reflection.TABLE_SCHEM,
+                    Reflection.TABLE_NAME,
+                    Reflection.COLUMN_NAME,
+                    Reflection.COLUMN_SIZE,
+                    Reflection.DATA_TYPE,
+                    Reflection.TYPE_NAME,
+                    Reflection.IS_NULLABLE,
+                    Reflection.IS_AUTOINCREMENT,
+                    Reflection.REMARKS);
+            cachePrimaryKeys = new CachedResultSet(metadata.getPrimaryKeys(null, null, null),
+                    Reflection.TABLE_SCHEM,
+                    Reflection.TABLE_NAME,
+                    Reflection.COLUMN_NAME);
+            cacheImportedKeys = new CachedResultSet(metadata.getImportedKeys(null, null, null),
+                    Reflection.PK_NAME,
+                    Reflection.FK_NAME,
+                    Reflection.FKTABLE_SCHEM,
+                    Reflection.FKTABLE_NAME,
+                    Reflection.FKCOLUMN_NAME,
+                    Reflection.PKTABLE_SCHEM,
+                    Reflection.PKTABLE_NAME,
+                    Reflection.PKCOLUMN_NAME,
+                    Reflection.DELETE_RULE);
+            cacheExportedKeys = new CachedResultSet(metadata.getExportedKeys(null, null, null),
+                    Reflection.PK_NAME,
+                    Reflection.FK_NAME,
+                    Reflection.PKTABLE_SCHEM,
+                    Reflection.PKTABLE_NAME,
+                    Reflection.PKCOLUMN_NAME,
+                    Reflection.FKTABLE_SCHEM,
+                    Reflection.FKTABLE_NAME,
+                    Reflection.FKCOLUMN_NAME,
+                    Reflection.DELETE_RULE);
 
             ////////////////////////////////////////////////////////////////////////////////
 
@@ -280,7 +244,7 @@ public final class DataBaseModel {
             } else {
                 final Iterator<Map<String,Object>> ite = cacheSchemas.records.iterator();
                 while (ite.hasNext()) {
-                    requieredSchemas.add((String) ite.next().get(Schema.TABLE_SCHEM));
+                    requieredSchemas.add((String) ite.next().get(Reflection.TABLE_SCHEM));
                 }
             }
 
@@ -298,7 +262,6 @@ public final class DataBaseModel {
         } catch (SQLException e) {
             throw new DataStoreException("Error occurred analyzing database model.\n" + e.getMessage(), e);
         } finally {
-            cacheSchemas = null;
             cacheTables = null;
             cacheColumns = null;
             cachePrimaryKeys = null;
@@ -343,279 +306,267 @@ public final class DataBaseModel {
 
     }
 
-    private SchemaMetaModel analyzeSchema(final String schemaName, final Connection cx) throws DataStoreException {
+    private SchemaMetaModel analyzeSchema(final String schemaName, final Connection cx) throws SQLException {
         final SchemaMetaModel schema = new SchemaMetaModel(schemaName);
-        try {
-            for (Map<String,Object> info : cacheTables.records) {
-                if (!Objects.equals(info.get(Table.TABLE_SCHEM), schemaName)) continue;
-                if (databaseTable != null && !databaseTable.isEmpty() && !Objects.equals(info.get(Table.TABLE_NAME),databaseTable)) continue;
-                final TableMetaModel table = analyzeTable(info,cx);
-                schema.tables.put(table.name, table);
-            }
-        } catch (SQLException e) {
-            throw new DataStoreException("Error occurred analyzing database model.", e);
+        for (Map<String,Object> info : cacheTables.records) {
+            if (!Objects.equals(info.get(Reflection.TABLE_SCHEM), schemaName)) continue;
+            if (databaseTable != null && !databaseTable.isEmpty() && !Objects.equals(info.get(Reflection.TABLE_NAME), databaseTable)) continue;
+            final TableMetaModel table = analyzeTable(info, cx);
+            schema.tables.put(table.name, table);
         }
         return schema;
     }
 
-    private TableMetaModel analyzeTable(final Map tableSet, final Connection cx) throws DataStoreException, SQLException {
-        final String schemaName = (String) tableSet.get(Table.TABLE_SCHEM);
-        final String tableName  = (String) tableSet.get(Table.TABLE_NAME);
-        final String tableType  = (String) tableSet.get(Table.TABLE_TYPE);
-
+    private TableMetaModel analyzeTable(final Map<String,Object> tableSet, final Connection cx) throws SQLException {
+        final String schemaName = (String) tableSet.get(Reflection.TABLE_SCHEM);
+        final String tableName  = (String) tableSet.get(Reflection.TABLE_NAME);
+        final String tableType  = (String) tableSet.get(Reflection.TABLE_TYPE);
         final TableMetaModel table = new TableMetaModel(tableName,tableType);
-
         final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
-        try {
+        // Explore all columns ----------------------------------------------
+        final Predicate<Map<String,Object>> tableFilter = (Map<String,Object> info) -> {
+            return Objects.equals(info.get(Reflection.TABLE_SCHEM), schemaName)
+                && Objects.equals(info.get(Reflection.TABLE_NAME), tableName);
+        };
+
+        final Iterator<Map<String,Object>> ite1 = cacheColumns.records.stream().filter(tableFilter).iterator();
+        while (ite1.hasNext()) {
+            analyzeColumn(ite1.next(), cx, ftb.addAttribute(Object.class));
+        }
+
+        // Find primary key -------------------------------------------------
+        final List<ColumnMetaModel> cols = new ArrayList<>();
+        final Iterator<Map<String,Object>> pkIte = cachePrimaryKeys.records.stream().filter(tableFilter).iterator();
+        while (pkIte.hasNext()) {
+            final Map<String,Object> result = pkIte.next();
+            final String columnName = (String) result.get(Reflection.COLUMN_NAME);
 
-            // Explore all columns ----------------------------------------------
-            final Predicate<Map<String,Object>> tableFilter = (Map<String,Object> info) -> {
-                return Objects.equals(info.get(Table.TABLE_SCHEM), schemaName)
-                    && Objects.equals(info.get(Table.TABLE_NAME), tableName);
+            final Predicate<Map<String,Object>> colFilter = (Map<String,Object> info) -> {
+                return Objects.equals(info.get(Reflection.COLUMN_NAME), columnName);
             };
+            final Iterator<Map<String,Object>> cite = cacheColumns.records.stream().filter(tableFilter.and(colFilter)).iterator();
+            final Map<String,Object> column = cite.next();
 
-            final Iterator<Map<String,Object>> ite1 = cacheColumns.records.stream().filter(tableFilter).iterator();
-            while (ite1.hasNext()) {
-                ftb.addAttribute(analyzeColumn(ite1.next(),cx));
-            }
+            final int sqlType = ((Number) column.get(Reflection.DATA_TYPE)).intValue();
+            final String sqlTypeName = (String) column.get(Reflection.TYPE_NAME);
+            Class<?> columnType = dialect.getJavaType(sqlType, sqlTypeName);
 
-            // Find primary key -------------------------------------------------
-            final List<ColumnMetaModel> cols = new ArrayList<>();
-            final Iterator<Map<String,Object>> pkIte = cachePrimaryKeys.records.stream().filter(tableFilter).iterator();
-            while (pkIte.hasNext()) {
-                final Map<String,Object> result = pkIte.next();
-                final String columnName = (String) result.get(Column.COLUMN_NAME);
-
-                final Predicate<Map<String,Object>> colFilter = (Map<String,Object> info) -> {
-                    return Objects.equals(info.get(Column.COLUMN_NAME), columnName);
-                };
-                final Iterator<Map<String,Object>> cite = cacheColumns.records.stream().filter(tableFilter.and(colFilter)).iterator();
-                final Map<String,Object> column = cite.next();
-
-                final int sqlType = ((Number) column.get(Column.DATA_TYPE)).intValue();
-                final String sqlTypeName = (String) column.get(Column.TYPE_NAME);
-                Class<?> columnType = dialect.getJavaType(sqlType, sqlTypeName);
-
-                if (columnType == null) {
-                    listeners.warning("No class for SQL type " + sqlType, null);
-                    columnType = Object.class;
-                }
+            if (columnType == null) {
+                listeners.warning("No class for SQL type " + sqlType, null);
+                columnType = Object.class;
+            }
 
-                ColumnMetaModel col = null;
+            ColumnMetaModel col = null;
 
-                final String str = (String) column.get(Column.IS_AUTOINCREMENT);
-                if (Column.VALUE_YES.equalsIgnoreCase(str)) {
-                    col = new ColumnMetaModel(schemaName, tableName, columnName, sqlType, sqlTypeName, columnType, ColumnMetaModel.Type.AUTO, null);
+            final String str = (String) column.get(Reflection.IS_AUTOINCREMENT);
+            if (VALUE_YES.equalsIgnoreCase(str)) {
+                col = new ColumnMetaModel(schemaName, tableName, columnName, sqlType, sqlTypeName, columnType, ColumnMetaModel.Type.AUTO, null);
+            } else {
+                // TODO: need to distinguish "NO" and empty string.
+                final String sequenceName = dialect.getColumnSequence(cx,schemaName, tableName, columnName);
+                if (sequenceName != null) {
+                    col = new ColumnMetaModel(schemaName, tableName, columnName, sqlType,
+                            sqlTypeName, columnType, ColumnMetaModel.Type.SEQUENCED,sequenceName);
                 } else {
-                    final String sequenceName = dialect.getColumnSequence(cx,schemaName, tableName, columnName);
-                    if (sequenceName != null) {
-                        col = new ColumnMetaModel(schemaName, tableName, columnName, sqlType,
-                                sqlTypeName, columnType, ColumnMetaModel.Type.SEQUENCED,sequenceName);
-                    } else {
-                        col = new ColumnMetaModel(schemaName, tableName, columnName, sqlType,
-                                sqlTypeName, columnType, ColumnMetaModel.Type.PROVIDED, null);
-                    }
+                    col = new ColumnMetaModel(schemaName, tableName, columnName, sqlType,
+                            sqlTypeName, columnType, ColumnMetaModel.Type.PROVIDED, null);
                 }
-                cols.add(col);
             }
-            /*
-             * Search indexes, they provide informations such as:
-             * - Unique indexes may indicate 1:1 relations in complexe features
-             * - Unique indexes can be used as primary key if no primary key are defined
-             */
-            final boolean pkEmpty = cols.isEmpty();
-            final List<String> names = new ArrayList<>();
-            final Map<String,List<String>> uniqueIndexes = new HashMap<>();
-            String indexname = null;
-            // We can't cache this one, seems to be a bug in the driver, it won't find anything for table name like '%'
-            cacheIndexInfos = new CachedResultSet(metadata.getIndexInfo(null, schemaName, tableName, true, false),
-                    Index.TABLE_SCHEM,
-                    Index.TABLE_NAME,
-                    Index.COLUMN_NAME,
-                    Index.INDEX_NAME);
-            final Iterator<Map<String,Object>> indexIte = cacheIndexInfos.records.stream().filter(tableFilter).iterator();
-            while (indexIte.hasNext()) {
-                final Map<String,Object> result = indexIte.next();
-                final String columnName = (String) result.get(Index.COLUMN_NAME);
-                final String idxName = (String) result.get(Index.INDEX_NAME);
-
-                List<String> lst = uniqueIndexes.get(idxName);
-                if (lst == null) {
-                    lst = new ArrayList<>();
-                    uniqueIndexes.put(idxName, lst);
-                }
-                lst.add(columnName);
-
-                if (pkEmpty) {
-                    // We use a single index columns set as primary key
-                    // We must not mix with other potential indexes.
-                    if (indexname == null) {
-                        indexname = idxName;
-                    } else if (!indexname.equals(idxName)) {
-                        continue;
-                    }
-                    names.add(columnName);
-                }
+            cols.add(col);
+        }
+        /*
+         * Search indexes, they provide informations such as:
+         * - Unique indexes may indicate 1:1 relations in complexe features
+         * - Unique indexes can be used as primary key if no primary key are defined
+         */
+        final boolean pkEmpty = cols.isEmpty();
+        final List<String> names = new ArrayList<>();
+        final Map<String,List<String>> uniqueIndexes = new HashMap<>();
+        String indexname = null;
+        // We can't cache this one, seems to be a bug in the driver, it won't find anything for table name like '%'
+        cacheIndexInfos = new CachedResultSet(metadata.getIndexInfo(null, schemaName, tableName, true, false),
+                Reflection.TABLE_SCHEM,
+                Reflection.TABLE_NAME,
+                Reflection.COLUMN_NAME,
+                Reflection.INDEX_NAME);
+        final Iterator<Map<String,Object>> indexIte = cacheIndexInfos.records.stream().filter(tableFilter).iterator();
+        while (indexIte.hasNext()) {
+            final Map<String,Object> result = indexIte.next();
+            final String columnName = (String) result.get(Reflection.COLUMN_NAME);
+            final String idxName = (String) result.get(Reflection.INDEX_NAME);
+
+            List<String> lst = uniqueIndexes.get(idxName);
+            if (lst == null) {
+                lst = new ArrayList<>();
+                uniqueIndexes.put(idxName, lst);
             }
-
-            // For each unique index composed of one column add a flag on the property descriptor
-            for (Entry<String,List<String>> entry : uniqueIndexes.entrySet()) {
-                final List<String> columns = entry.getValue();
-                if (columns.size() == 1) {
-                    String columnName = columns.get(0);
-                    for (PropertyTypeBuilder desc : ftb.properties()) {
-                        if (desc.getName().tip().toString().equals(columnName)) {
-                            final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
-                            atb.addCharacteristic(ColumnMetaModel.JDBC_PROPERTY_UNIQUE).setDefaultValue(Boolean.TRUE);
-                        }
-                    }
+            lst.add(columnName);
+
+            if (pkEmpty) {
+                // We use a single index columns set as primary key
+                // We must not mix with other potential indexes.
+                if (indexname == null) {
+                    indexname = idxName;
+                } else if (!indexname.equals(idxName)) {
+                    continue;
                 }
+                names.add(columnName);
             }
+        }
 
-            if (pkEmpty && !names.isEmpty()) {
-                // Build a primary key from unique index
-                final Iterator<Map<String,Object>> ite = cacheColumns.records.stream().filter(tableFilter).iterator();
-                while (ite.hasNext()) {
-                    final Map<String,Object> result = ite.next();
-                    final String columnName = (String) result.get(Column.COLUMN_NAME);
-                    if (!names.contains(columnName)) {
-                        continue;
-                    }
-
-                    final int sqlType = ((Number) result.get(Column.DATA_TYPE)).intValue();
-                    final String sqlTypeName = (String) result.get(Column.TYPE_NAME);
-                    final Class<?> columnType = dialect.getJavaType(sqlType, sqlTypeName);
-                    final ColumnMetaModel col = new ColumnMetaModel(schemaName, tableName, columnName,
-                            sqlType, sqlTypeName, columnType, ColumnMetaModel.Type.PROVIDED, null);
-                    cols.add(col);
-
-                    // Set as identifier
-                    for (PropertyTypeBuilder desc : ftb.properties()) {
-                        if (desc.getName().tip().toString().equals(columnName)) {
-                            final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
-                            atb.addRole(AttributeRole.IDENTIFIER_COMPONENT);
-                            break;
-                        }
+        // For each unique index composed of one column add a flag on the property descriptor
+        for (Entry<String,List<String>> entry : uniqueIndexes.entrySet()) {
+            final List<String> columns = entry.getValue();
+            if (columns.size() == 1) {
+                String columnName = columns.get(0);
+                for (PropertyTypeBuilder desc : ftb.properties()) {
+                    if (desc.getName().tip().toString().equals(columnName)) {
+                        final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
+                        atb.addCharacteristic(ColumnMetaModel.JDBC_PROPERTY_UNIQUE).setDefaultValue(Boolean.TRUE);
                     }
                 }
             }
+        }
 
-
-            if (cols.isEmpty()) {
-                if (Table.VALUE_TYPE_TABLE.equals(tableType)) {
-                    listeners.warning("No primary key found for " + tableName, null);
+        if (pkEmpty && !names.isEmpty()) {
+            // Build a primary key from unique index
+            final Iterator<Map<String,Object>> ite = cacheColumns.records.stream().filter(tableFilter).iterator();
+            while (ite.hasNext()) {
+                final Map<String,Object> result = ite.next();
+                final String columnName = (String) result.get(Reflection.COLUMN_NAME);
+                if (!names.contains(columnName)) {
+                    continue;
                 }
-            }
-            table.key = new PrimaryKey(tableName, cols);
 
-            // Mark primary key columns
-            for (PropertyTypeBuilder desc : ftb.properties()) {
-                for (ColumnMetaModel col : cols) {
-                    if (desc.getName().tip().toString().equals(col.name)) {
+                final int sqlType = ((Number) result.get(Reflection.DATA_TYPE)).intValue();
+                final String sqlTypeName = (String) result.get(Reflection.TYPE_NAME);
+                final Class<?> columnType = dialect.getJavaType(sqlType, sqlTypeName);
+                final ColumnMetaModel col = new ColumnMetaModel(schemaName, tableName, columnName,
+                        sqlType, sqlTypeName, columnType, ColumnMetaModel.Type.PROVIDED, null);
+                cols.add(col);
+
+                // Set as identifier
+                for (PropertyTypeBuilder desc : ftb.properties()) {
+                    if (desc.getName().tip().toString().equals(columnName)) {
                         final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
                         atb.addRole(AttributeRole.IDENTIFIER_COMPONENT);
                         break;
                     }
                 }
             }
+        }
 
 
-            // Find imported keys -----------------------------------------------
-            final Predicate<Map<String,Object>> fkFilter = (Map<String,Object> info) -> {
-                return Objects.equals(info.get(ImportedKey.FKTABLE_SCHEM), schemaName)
-                    && Objects.equals(info.get(ImportedKey.FKTABLE_NAME), tableName);
-            };
-            Iterator<Map<String,Object>> ite = cacheImportedKeys.records.stream().filter(fkFilter).iterator();
-            while (ite.hasNext()) {
-                final Map<String,Object> result = ite.next();
-                String relationName = (String) result.get(ImportedKey.PK_NAME);
-                if (relationName == null) relationName = (String) result.get(ImportedKey.FK_NAME);
-                final String localColumn = (String) result.get(ImportedKey.FKCOLUMN_NAME);
-                final String refSchemaName = (String) result.get(ImportedKey.PKTABLE_SCHEM);
-                final String refTableName = (String) result.get(ImportedKey.PKTABLE_NAME);
-                final String refColumnName = (String) result.get(ImportedKey.PKCOLUMN_NAME);
-                final int deleteRule = ((Number) result.get(ImportedKey.DELETE_RULE)).intValue();
-                final boolean deleteCascade = DatabaseMetaData.importedKeyCascade == deleteRule;
-                final RelationMetaModel relation = new RelationMetaModel(relationName,localColumn,
-                        refSchemaName, refTableName, refColumnName, true, deleteCascade);
-                table.importedKeys.add(relation);
-
-                if (refSchemaName!=null && !visitedSchemas.contains(refSchemaName)) requieredSchemas.add(refSchemaName);
-
-                // Set the information
-                for (PropertyTypeBuilder desc : ftb.properties()) {
-                    if (desc.getName().tip().toString().equals(localColumn)) {
-                        final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
-                        atb.addCharacteristic(ColumnMetaModel.JDBC_PROPERTY_RELATION).setDefaultValue(relation);
-                        break;
-                    }
+        if (cols.isEmpty()) {
+            if (TYPE_TABLE.equals(tableType)) {
+                listeners.warning("No primary key found for " + tableName, null);
+            }
+        }
+        table.key = new PrimaryKey(tableName, cols);
+
+        // Mark primary key columns
+        for (PropertyTypeBuilder desc : ftb.properties()) {
+            for (ColumnMetaModel col : cols) {
+                if (desc.getName().tip().toString().equals(col.name)) {
+                    final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
+                    atb.addRole(AttributeRole.IDENTIFIER_COMPONENT);
+                    break;
                 }
             }
+        }
 
-            // Find exported keys -----------------------------------------------
-            final Predicate<Map<String,Object>> ekFilter = (Map<String,Object> info) -> {
-                return Objects.equals(info.get(ImportedKey.PKTABLE_SCHEM), schemaName)
-                    && Objects.equals(info.get(ImportedKey.PKTABLE_NAME), tableName);
-            };
-            ite = cacheExportedKeys.records.stream().filter(ekFilter).iterator();
-            while (ite.hasNext()) {
-                final Map<String,Object> result = ite.next();
-                String relationName = (String) result.get(ExportedKey.FKCOLUMN_NAME);
-                if (relationName == null) relationName = (String) result.get(ExportedKey.FK_NAME);
-                final String localColumn = (String) result.get(ExportedKey.PKCOLUMN_NAME);
-                final String refSchemaName = (String) result.get(ExportedKey.FKTABLE_SCHEM);
-                final String refTableName = (String) result.get(ExportedKey.FKTABLE_NAME);
-                final String refColumnName = (String) result.get(ExportedKey.FKCOLUMN_NAME);
-                final int deleteRule = ((Number) result.get(ImportedKey.DELETE_RULE)).intValue();
-                final boolean deleteCascade = DatabaseMetaData.importedKeyCascade == deleteRule;
-                table.exportedKeys.add(new RelationMetaModel(relationName, localColumn,
-                        refSchemaName, refTableName, refColumnName, false, deleteCascade));
-
-                if (refSchemaName != null && !visitedSchemas.contains(refSchemaName)) requieredSchemas.add(refSchemaName);
+
+        // Find imported keys -----------------------------------------------
+        final Predicate<Map<String,Object>> fkFilter = (Map<String,Object> info) -> {
+            return Objects.equals(info.get(Reflection.FKTABLE_SCHEM), schemaName)
+                && Objects.equals(info.get(Reflection.FKTABLE_NAME), tableName);
+        };
+        Iterator<Map<String,Object>> ite = cacheImportedKeys.records.stream().filter(fkFilter).iterator();
+        while (ite.hasNext()) {
+            final Map<String,Object> result = ite.next();
+            String relationName = (String) result.get(Reflection.PK_NAME);
+            if (relationName == null) relationName = (String) result.get(Reflection.FK_NAME);
+            final String localColumn = (String) result.get(Reflection.FKCOLUMN_NAME);
+            final String refSchemaName = (String) result.get(Reflection.PKTABLE_SCHEM);
+            final String refTableName = (String) result.get(Reflection.PKTABLE_NAME);
+            final String refColumnName = (String) result.get(Reflection.PKCOLUMN_NAME);
+            final int deleteRule = ((Number) result.get(Reflection.DELETE_RULE)).intValue();
+            final boolean deleteCascade = DatabaseMetaData.importedKeyCascade == deleteRule;
+            final RelationMetaModel relation = new RelationMetaModel(relationName,localColumn,
+                    refSchemaName, refTableName, refColumnName, true, deleteCascade);
+            table.importedKeys.add(relation);
+
+            if (refSchemaName!=null && !visitedSchemas.contains(refSchemaName)) requieredSchemas.add(refSchemaName);
+
+            // Set the information
+            for (PropertyTypeBuilder desc : ftb.properties()) {
+                if (desc.getName().tip().toString().equals(localColumn)) {
+                    final AttributeTypeBuilder<?> atb = (AttributeTypeBuilder) desc;
+                    atb.addCharacteristic(ColumnMetaModel.JDBC_PROPERTY_RELATION).setDefaultValue(relation);
+                    break;
+                }
             }
+        }
 
-            // Find parent table if any -----------------------------------------
-//            if(handleSuperTableMetadata == null || handleSuperTableMetadata){
-//                try{
-//                    result = metadata.getSuperTables(null, schemaName, tableName);
-//                    while (result.next()) {
-//                        final String parentTable = result.getString(SuperTable.SUPERTABLE_NAME);
-//                        table.parents.add(parentTable);
-//                    }
-//                }catch(final SQLException ex){
-//                    //not implemented by database
-//                    handleSuperTableMetadata = Boolean.FALSE;
-//                    store.getLogger().log(Level.INFO, "Database does not handle getSuperTable, feature type hierarchy will be ignored.");
-//                }finally{
-//                    closeSafe(store.getLogger(),result);
+        // Find exported keys -----------------------------------------------
+        final Predicate<Map<String,Object>> ekFilter = (Map<String,Object> info) -> {
+            return Objects.equals(info.get(Reflection.PKTABLE_SCHEM), schemaName)
+                && Objects.equals(info.get(Reflection.PKTABLE_NAME), tableName);
+        };
+        ite = cacheExportedKeys.records.stream().filter(ekFilter).iterator();
+        while (ite.hasNext()) {
+            final Map<String,Object> result = ite.next();
+            String relationName = (String) result.get(Reflection.FKCOLUMN_NAME);
+            if (relationName == null) relationName = (String) result.get(Reflection.FK_NAME);
+            final String localColumn = (String) result.get(Reflection.PKCOLUMN_NAME);
+            final String refSchemaName = (String) result.get(Reflection.FKTABLE_SCHEM);
+            final String refTableName = (String) result.get(Reflection.FKTABLE_NAME);
+            final String refColumnName = (String) result.get(Reflection.FKCOLUMN_NAME);
+            final int deleteRule = ((Number) result.get(Reflection.DELETE_RULE)).intValue();
+            final boolean deleteCascade = DatabaseMetaData.importedKeyCascade == deleteRule;
+            table.exportedKeys.add(new RelationMetaModel(relationName, localColumn,
+                    refSchemaName, refTableName, refColumnName, false, deleteCascade));
+
+            if (refSchemaName != null && !visitedSchemas.contains(refSchemaName)) requieredSchemas.add(refSchemaName);
+        }
+
+        // Find parent table if any -----------------------------------------
+//        if (handleSuperTableMetadata == null || handleSuperTableMetadata) {
+//            try {
+//                result = metadata.getSuperTables(null, schemaName, tableName);
+//                while (result.next()) {
+//                    final String parentTable = result.getString(SuperTable.SUPERTABLE_NAME);
+//                    table.parents.add(parentTable);
 //                }
+//            } catch (SQLException ex) {
+//                //not implemented by database
+//                handleSuperTableMetadata = Boolean.FALSE;
+//                store.getLogger().log(Level.INFO, "Database does not handle getSuperTable, feature type hierarchy will be ignored.");
+//            } finally {
+//                closeSafe(store.getLogger(),result);
 //            }
+//        }
 
-        } catch (SQLException e) {
-            throw new DataStoreException("Error occurred analyzing table: " + tableName, e);
-        }
         ftb.setName(tableName);
         table.tableType = ftb;
         return table;
     }
 
-    private AttributeType<?> analyzeColumn(final Map<String,Object> columnSet, final Connection cx) throws SQLException, DataStoreException{
-        final String schemaName     = (String)  columnSet.get(Column.TABLE_SCHEM);
-        final String tableName      = (String)  columnSet.get(Column.TABLE_NAME);
-        final String columnName     = (String)  columnSet.get(Column.COLUMN_NAME);
-        final int columnSize        = ((Number) columnSet.get(Column.COLUMN_SIZE)).intValue();
-        final int columnDataType    = ((Number) columnSet.get(Column.DATA_TYPE)).intValue();
-        final String columnTypeName = (String)  columnSet.get(Column.TYPE_NAME);
-        final String columnNullable = (String)  columnSet.get(Column.IS_NULLABLE);
-        final SingleAttributeTypeBuilder atb = new SingleAttributeTypeBuilder();
+    private AttributeType<?> analyzeColumn(final Map<String,Object> columnSet, final Connection cx, final AttributeTypeBuilder<?> atb)
+            throws SQLException
+    {
+        final String schemaName     = (String)  columnSet.get(Reflection.TABLE_SCHEM);
+        final String tableName      = (String)  columnSet.get(Reflection.TABLE_NAME);
+        final String columnName     = (String)  columnSet.get(Reflection.COLUMN_NAME);
+        final int columnSize        = ((Number) columnSet.get(Reflection.COLUMN_SIZE)).intValue();
+        final int columnDataType    = ((Number) columnSet.get(Reflection.DATA_TYPE)).intValue();
+        final String columnTypeName = (String)  columnSet.get(Reflection.TYPE_NAME);
+        final String columnNullable = (String)  columnSet.get(Reflection.IS_NULLABLE);
         atb.setName(columnName);
-        atb.setLength(columnSize);
-        try {
-            dialect.decodeColumnType(atb, cx, columnTypeName, columnDataType, schemaName, tableName, columnName);
-        } catch (SQLException e) {
-            throw new DataStoreException("Error occurred analyzing column: " + columnName, e);
-        }
-        atb.setMinimumOccurs(Column.VALUE_NO.equalsIgnoreCase(columnNullable) ? 1 : 0);
+        atb.setMaximalLength(columnSize);
+        dialect.decodeColumnType(atb, cx, columnTypeName, columnDataType, schemaName, tableName, columnName);
+        // TODO: need to distinguish "YES" and empty string?
+        atb.setMinimumOccurs(VALUE_NO.equalsIgnoreCase(columnNullable) ? 1 : 0);
         atb.setMaximumOccurs(1);
         return atb.build();
     }
@@ -623,7 +574,7 @@ public final class DataBaseModel {
     /**
      * Analyze the metadata of the ResultSet to rebuild a feature type.
      */
-    public FeatureType analyzeResult(final ResultSet result, final String name) throws SQLException, DataStoreException{
+    final FeatureType analyzeResult(final ResultSet result, final String name) throws SQLException, DataStoreException {
         final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
         ftb.setName(name);
 
@@ -652,15 +603,16 @@ public final class DataBaseModel {
                     }
                 }
             }
-
-            if (desc == null) {
-                //could not find the original type
-                //this column must be calculated
-                final SingleAttributeTypeBuilder atb = new SingleAttributeTypeBuilder();
+            if (desc != null) {
+                ftb.addProperty(desc);
+            } else {
+                // could not find the original type
+                // this column must be calculated
+                final AttributeTypeBuilder<?> atb = ftb.addAttribute(Object.class);
 
                 final int nullable = metadata.isNullable(i);
                 atb.setName(columnLabel);
-                atb.setMinimumOccurs(nullable == metadata.columnNullable ? 0 : 1);
+                atb.setMinimumOccurs(nullable == ResultSetMetaData.columnNullable ? 0 : 1);
                 atb.setMaximumOccurs(1);
                 atb.setName(columnLabel);
 
@@ -676,9 +628,7 @@ public final class DataBaseModel {
                 } catch (SQLException e) {
                     throw new DataStoreException("Error occurred analyzing column : " + columnName, e);
                 }
-                desc = atb.build();
             }
-            ftb.addProperty(desc);
         }
         return ftb.build();
     }
@@ -709,9 +659,9 @@ public final class DataBaseModel {
                     if (Geometries.isKnownType(binding)) {
 
                         final Predicate<Map<?,?>> colFilter = (Map<?,?> info) -> {
-                            return Objects.equals(info.get(Table.TABLE_SCHEM), schema.name)
-                                && Objects.equals(info.get(Table.TABLE_NAME), tableName)
-                                && Objects.equals(info.get(Column.COLUMN_NAME), name);
+                            return Objects.equals(info.get(Reflection.TABLE_SCHEM), schema.name)
+                                && Objects.equals(info.get(Reflection.TABLE_NAME), tableName)
+                                && Objects.equals(info.get(Reflection.COLUMN_NAME), name);
                         };
                         final Map<String,Object> metas = cacheColumns.records.stream().filter(colFilter).findFirst().get();
 
@@ -730,9 +680,9 @@ public final class DataBaseModel {
                         }
                     } else if (Coverage.class.isAssignableFrom(binding)) {
                         final Predicate<Map<String,Object>> colFilter = (Map<String,Object> info) -> {
-                            return Objects.equals(info.get(Table.TABLE_SCHEM), schema.name)
-                                && Objects.equals(info.get(Table.TABLE_NAME), tableName)
-                                && Objects.equals(info.get(Column.COLUMN_NAME), name);
+                            return Objects.equals(info.get(Reflection.TABLE_SCHEM), schema.name)
+                                && Objects.equals(info.get(Reflection.TABLE_NAME), tableName)
+                                && Objects.equals(info.get(Reflection.COLUMN_NAME), name);
                         };
                         final Map<String,Object> metas = cacheColumns.records.stream().filter(colFilter).findFirst().get();
 
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java
index 17f9547..ad9930f 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/Dialect.java
@@ -21,6 +21,7 @@ import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.apache.sis.feature.builder.AttributeTypeBuilder;
 import org.apache.sis.storage.DataStoreException;
 
 
@@ -42,16 +43,6 @@ public abstract class Dialect {
     }
 
     /**
-     * Indicates if the JDBC driver support global metadata.
-     * Some drivers force specifying a schema or table to return results.
-     * This prevent us from loading all metadata in one request and
-     * makes us loop on all tables.
-     *
-     * @return whether global JDBC metadata are available.
-     */
-    public abstract boolean supportGlobalMetadata();
-
-    /**
      * Indicates whether a table will be used as a {@code FeatureType}.
      *
      * @param  name  database table name.
@@ -71,23 +62,6 @@ public abstract class Dialect {
     public abstract Class<?> getJavaType(int sqlType, String sqlTypeName);
 
     /**
-     * Encodes the column name part of a SQL query.
-     *
-     * @param sql   where to write the SQL statement.
-     * @param name  column name to write, not null.
-     */
-    public abstract void encodeColumnName(StringBuilder sql, String name);
-
-    /**
-     * Encodes the schema and table name parts of a SQL query.
-     *
-     * @param sql     where to write the SQL statement.
-     * @param schema  database schema to write, or null if none.
-     * @param table   database table to write, not null.
-     */
-    public abstract void encodeSchemaAndTableName(StringBuilder sql, String schema, String table);
-
-    /**
      * If a column is an auto-increment or has a sequence, tries to extract next value.
      *
      * @param  column  description of the database column for which to get the next value.
@@ -122,7 +96,7 @@ public abstract class Dialect {
      * @param  column    name of the database column.
      * @throws SQLException if a JDBC error occurred while executing a statement.
      */
-    public abstract void decodeColumnType(final SingleAttributeTypeBuilder atb, final Connection cx,
+    public abstract void decodeColumnType(final AttributeTypeBuilder<?> atb, final Connection cx,
             final String typeName, final int datatype, final String schema,
             final String table, final String column) throws SQLException;
 
@@ -136,7 +110,7 @@ public abstract class Dialect {
      * @param  customquery  {@code true} if the request is a custom query.
      * @throws SQLException if a JDBC error occurred while executing a statement.
      */
-    public abstract void decodeGeometryColumnType(final SingleAttributeTypeBuilder atb, final Connection cx,
+    public abstract void decodeGeometryColumnType(final AttributeTypeBuilder<?> atb, final Connection cx,
             final ResultSet rs, final int columnIndex, boolean customquery) throws SQLException;
 
     /**
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaDataConstants.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaDataConstants.java
deleted file mode 100644
index 393785b..0000000
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/MetaDataConstants.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * 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.internal.sql.feature;
-
-
-/**
- * Constants defined by JDBC to retrieve a database meta-model.
- *
- * @author  Johann Sorel (Geomatys)
- * @version 1.0
- * @since   1.0
- * @module
- */
-final class MetaDataConstants {
-
-    static final class Schema {
-        /** schema name. */
-        public static final String TABLE_SCHEM = "TABLE_SCHEM";
-
-        /** catalog name (values in this column may be null). */
-        public static final String TABLE_CATALOG = "TABLE_CATALOG";
-
-        private Schema() {
-        }
-    }
-
-    static final class Table {
-        /** Table catalog (values in this column may be null). */
-        public static final String TABLE_CAT = "TABLE_CAT";
-
-        /** Table schema (values in this column may be null). */
-
-        public static final String TABLE_SCHEM = "TABLE_SCHEM";
-
-        /** Table name. */
-        public static final String TABLE_NAME = "TABLE_NAME";
-
-        /**
-         * Table type. Typical types are:
-         * "TABLE", "VIEW", "SYSTEM TABLE",
-         * "GLOBAL TEMPORARY", "LOCAL TEMPORARY", "ALIAS", "SYNONYM".
-         */
-        public static final String TABLE_TYPE = "TABLE_TYPE";
-
-        /** Explanatory comment on the table. */
-        public static final String REMARKS = "REMARKS";
-
-        /** The types catalog (values in this column may be null). */
-        public static final String TYPE_CAT = "TYPE_CAT";
-
-        /** The types schema (values in this column may be null). */
-        public static final String TYPE_SCHEM = "TYPE_SCHEM";
-
-        /** Type name (values in this column may be null). */
-        public static final String TYPE_NAME = "TYPE_NAME";
-
-        /** Name of the designated "identifier" column of a typed table (values in this column may be null). */
-        public static final String SELF_REFERENCING_COL_NAME = "SELF_REFERENCING_COL_NAME";
-
-        /**
-         * Specifies how values in SELF_REFERENCING_COL_NAME are created.
-         * Values are "SYSTEM", "USER", "DERIVED". values in this column may be null.
-         */
-        public static final String REF_GENERATION =  "REF_GENERATION";
-
-        public static final String VALUE_TYPE_TABLE             = "TABLE";
-        public static final String VALUE_TYPE_VIEW              = "VIEW";
-        public static final String VALUE_TYPE_SYSTEMTABLE       = "SYSTEM TABLE";
-        public static final String VALUE_TYPE_GLOBALTEMPORARY   = "GLOBAL TEMPORARY";
-        public static final String VALUE_TYPE_LOCALTEMPORARY    = "LOCAL TEMPORARY";
-        public static final String VALUE_TYPE_ALIAS             = "ALIAS";
-        public static final String VALUE_TYPE_SYNONYM           = "SYNONYM";
-
-        public static final String VALUE_REFGEN_SYSTEM          = "SYSTEM";
-        public static final String VALUE_REFGEN_USER            = "USER";
-        public static final String VALUE_REFGEN_DERIVED         = "DERIVED";
-
-        private Table() {
-        }
-    }
-
-    public static final class SuperTable {
-        /** The type's catalog (values in this column may be null). */
-        public static final String TABLE_CAT = "TABLE_CAT";
-
-        /** Type's schema (values in this column may be null). */
-        public static final String TABLE_SCHEM = "TABLE_SCHEM";
-
-        /** Type name. */
-        public static final String TABLE_NAME = "TABLE_NAME";
-
-        /** The direct super type's name. */
-        public static final String SUPERTABLE_NAME =  "SUPERTABLE_NAME";
-
-        private SuperTable() {
-        }
-    }
-
-    public static final class Column {
-        /** Table catalog (values in this column may be null). */
-        public static final String TABLE_CAT = "TABLE_CAT";
-
-        /** Table schema (values in this column may be null). */
-        public static final String TABLE_SCHEM = "TABLE_SCHEM";
-
-        /** Table name. */
-        public static final String TABLE_NAME = "TABLE_NAME";
-
-        /** Column name. */
-        public static final String COLUMN_NAME = "COLUMN_NAME";
-
-        /** SQL type from {@link java.sql.Types}. */
-        public static final String DATA_TYPE = "DATA_TYPE";
-
-        /** Data source dependent type name, for a UDT the type name is fully qualified. */
-        public static final String TYPE_NAME = "TYPE_NAME";
-
-        /** Column size ({@code int} values). */
-        public static final String COLUMN_SIZE = "COLUMN_SIZE";
-
-        /** Not used. */
-        public static final String BUFFER_LENGTH = "BUFFER_LENGTH";
-
-        /**
-         * The number of fractional digits as {@code int} values.
-         * Null is returned for data types where DECIMAL_DIGITS is not applicable.
-         */
-        public static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";
-
-        /** Radix (typically either 10 or 2) as {@code int} values. */
-        public static final String NUM_PREC_RADIX = "NUM_PREC_RADIX";
-
-        /**
-         * Whether NULL allowed as a {@code int} code.
-         * <ul>
-         *   <li>{@code columnNoNulls} - might not allow NULL values</li>
-         *   <li>{@code columnNullable} - definitely allows NULL values</li>
-         *   <li>{@code columnNullableUnknown} - nullability unknown</li>
-         * </ul>
-         */
-        public static final String NULLABLE = "NULLABLE";
-
-        /** Comment describing column (values in this column may be null). */
-        public static final String REMARKS = "REMARKS";
-
-        /**
-         * Default value for the column, which should be interpreted as a
-         * string when the value is enclosed in single quotes (values in this column may be null)
-         */
-        public static final String COLUMN_DEF = "COLUMN_DEF";
-
-        /** Unused {@code int} values. */
-        public static final String SQL_DATA_TYPE = "SQL_DATA_TYPE";
-
-        /** Unused {@code int} values. */
-        public static final String SQL_DATETIME_SUB = "SQL_DATETIME_SUB";
-
-        /** Maximum number (as a {@code int}) of bytes in the column of type {@code char}. */
-        public static final String CHAR_OCTET_LENGTH = "CHAR_OCTET_LENGTH";
-
-        /** Index of column in table (starting at 1). */
-        public static final String ORDINAL_POSITION = "ORDINAL_POSITION";
-
-        /**
-         * ISO rules are used to determine the nullability for a column.
-         * YES if the parameter can include NULLs,
-         * NO if the parameter cannot include NULLs,
-         * empty string if the nullability for the parameter is unknown.
-         */
-        public static final String IS_NULLABLE = "IS_NULLABLE";
-
-        /**
-         * Catalog of table that is the scope of a reference attribute
-         * (null if DATA_TYPE isn't REF).
-         */
-        public static final String SCOPE_CATLOG = "SCOPE_CATLOG";
-
-        /**
-         * Schema of table that is the scope of a reference attribute
-         * (null if the DATA_TYPE isn't REF).
-         */
-        public static final String SCOPE_SCHEMA = "SCOPE_SCHEMA";
-
-        /**
-         * Table name that this the scope of a reference attribute
-         * (null if the DATA_TYPE isn't REF).
-         */
-        public static final String SCOPE_TABLE = "SCOPE_TABLE";
-
-        /**
-         * Source type of a distinct type or user-generated Ref type.
-         * This is a SQL type from {@link java.sql.Types}
-         * (null if DATA_TYPE isn't DISTINCT or user-generated REF).
-         */
-        public static final String SOURCE_DATA_TYPE = "SOURCE_DATA_TYPE";
-
-        /**
-         * Indicates whether this column is auto incremented.
-         * YES if the column is auto incremented,
-         * NO if the column is not auto incremented,
-         * empty string if whether the column is auto incremented is unknown.
-         */
-        public static final String IS_AUTOINCREMENT = "IS_AUTOINCREMENT";
-
-        public static final String VALUE_YES = "YES";
-        public static final String VALUE_NO = "NO";
-
-        private Column() {
-        }
-    }
-
-    public static final class PrimaryKey{
-        /** Table catalog (values in this column may be null). */
-        public static final String TABLE_CAT = "TABLE_CAT";
-
-        /** Table schema (values in this column may be null). */
-        public static final String TABLE_SCHEM = "TABLE_SCHEM";
-
-        /** Table name. */
-        public static final String TABLE_NAME = "TABLE_NAME";
-
-        /** Column name. */
-        public static final String COLUMN_NAME = "COLUMN_NAME";
-
-        /**
-         * Sequence number within primary key as a {@code short} code.
-         * A value of 1 represents the first column of the primary key;
-         * a value of 2 would represent the second column within the primary key.
-         */
-        public static final String KEY_SEQ = "KEY_SEQ";
-
-        /** Primary key name (values in this column may be null). */
-        public static final String PK_NAME = "PK_NAME";
-
-        private PrimaryKey() {
-        }
-    }
-
-    public static final class ImportedKey{
-        /** Primary key table catalog being imported (values in this column may be null). */
-        public static final String PKTABLE_CAT = "PKTABLE_CAT";
-
-        /** Primary key table schema being imported (values in this column may be null). */
-        public static final String PKTABLE_SCHEM = "PKTABLE_SCHEM";
-
-        /** Primary key table name being imported. */
-        public static final String PKTABLE_NAME = "PKTABLE_NAME";
-
-        /** Primary key column name being imported. */
-        public static final String PKCOLUMN_NAME = "PKCOLUMN_NAME";
-
-        /** Foreign key table catalog (may be null). */
-        public static final String FKTABLE_CAT = "FKTABLE_CAT";
-
-        /** Foreign key table schema (may be null). */
-        public static final String FKTABLE_SCHEM = "FKTABLE_SCHEM";
-
-        /** Foreign key table name. */
-        public static final String FKTABLE_NAME = "FKTABLE_NAME";
-
-        /** Foreign key column name. */
-        public static final String FKCOLUMN_NAME = "FKCOLUMN_NAME";
-
-        /**
-         * Sequence number within a foreign key as a {@code short} code.
-         * A value of 1 represents the first column of the foreign key;
-         * a value of 2 would represent the second column within the foreign key.
-         */
-        public static final String KEY_SEQ = "KEY_SEQ";
-
-        /**
-         * What happens to a foreign key when the primary key is updated, as a {@code short} code.
-         * <ul>
-         *   <li>{@code importedNoAction} - do not allow update of primary key if it has been imported</li>
-         *   <li>{@code importedKeyCascade} - change imported key to agree with primary key update</li>
-         *   <li>{@code importedKeySetNull} - change imported key to NULL if its primary key has been updated</li>
-         *   <li>{@code importedKeySetDefault} - change imported key to default values if its primary key has been updated</li>
-         *   <li>{@code importedKeyRestrict} - same as importedKeyNoAction (for ODBC 2.x compatibility).</li>
-         * </ul>
-         */
-        public static final String UPDATE_RULE = "UPDATE_RULE";
-
-        /**
-         * What happens to the foreign key when primary is deleted, as a {@code short} code.
-         * <ul>
-         *   <li>{@code importedKeyNoAction} - do not allow delete of primary key if it has been imported</li>
-         *   <li>{@code importedKeyCascade} - delete rows that import a deleted key</li>
-         *   <li>{@code importedKeySetNull} - change imported key to NULL if its primary key has been deleted</li>
-         *   <li>{@code importedKeyRestrict} - same as importedKeyNoAction (for ODBC 2.x compatibility)</li>
-         *   <li>{@code importedKeySetDefault} - change imported key to default if its primary key has been deleted.</li>
-         * </ul>
-         */
-        public static final String DELETE_RULE = "DELETE_RULE";
-
-        /** Foreign key name (values in this column may be null). */
-        public static final String FK_NAME = "FK_NAME";
-
-        /** Primary key name (values in this column may be null). */
-        public static final String PK_NAME = "PK_NAME";
-
-        /**
-         * Whether the evaluation of foreign key constraints can be deferred until commit (as a {@code short} code).
-         * <ul>
-         *   <li>{@code importedKeyInitiallyDeferred} - see SQL92 for definition</li>
-         *   <li>{@code importedKeyInitiallyImmediate} - see SQL92 for definition</li>
-         *   <li>{@code importedKeyNotDeferrable} - see SQL92 for definition</li>
-         * </ul>
-         */
-        public static final String DEFERRABILITY = "DEFERRABILITY";
-
-        private ImportedKey() {
-        }
-    }
-
-    public static final class ExportedKey{
-        /** Primary key table catalog (values in this column may be null). */
-        public static final String PKTABLE_CAT = "PKTABLE_CAT";
-
-        /** Primary key table schema (values in this column may be null). */
-        public static final String PKTABLE_SCHEM = "PKTABLE_SCHEM";
-
-        /** Primary key table name. */
-        public static final String PKTABLE_NAME = "PKTABLE_NAME";
-
-        /** Primary key column name. */
-        public static final String PKCOLUMN_NAME = "PKCOLUMN_NAME";
-
-        /** Foreign key table catalog (may be null) being exported (values in this column may be null). */
-        public static final String FKTABLE_CAT = "FKTABLE_CAT";
-
-        /** Foreign key table schema (may be null) being exported (values in this column may be null). */
-        public static final String FKTABLE_SCHEM = "FKTABLE_SCHEM";
-
-        /** Foreign key table name being exported. */
-        public static final String FKTABLE_NAME = "FKTABLE_NAME";
-
-        /** Foreign key column name being exported. */
-        public static final String FKCOLUMN_NAME = "FKCOLUMN_NAME";
-
-        /**
-         * Sequence number within foreign key as a {@code short} code.
-         * a value of 1 represents the first column of the foreign key;
-         * a value of 2 would represent the second column within the foreign key.
-         */
-        public static final String KEY_SEQ = "KEY_SEQ";
-
-        /**
-         * What happens to foreign key when primary is updated, as a {@code short} code.
-         * <ul>
-         *   <li>{@code importedNoAction} - do not allow update of primary key if it has been imported</li>
-         *   <li>{@code importedKeyCascade} - change imported key to agree with primary key update</li>
-         *   <li>{@code importedKeySetNull} - change imported key to NULL if its primary key has been updated</li>
-         *   <li>{@code importedKeySetDefault} - change imported key to default values if its primary key has been updated</li>
-         *   <li>{@code importedKeyRestrict} - same as importedKeyNoAction (for ODBC 2.x compatibility)</li>
-         * </ul>
-         */
-        public static final String UPDATE_RULE = "UPDATE_RULE";
-
-        /**
-         * What happens to the foreign key when primary is deleted, as a {@code short} code.
-         * <ul>
-         *   <li>{@code importedKeyNoAction} - do not allow delete of primary key if it has been imported</li>
-         *   <li>{@code importedKeyCascade} - delete rows that import a deleted key</li>
-         *   <li>{@code importedKeySetNull} - change imported key to NULL if its primary key has been deleted</li>
-         *   <li>{@code importedKeyRestrict} - same as importedKeyNoAction (for ODBC 2.x compatibility)</li>
-         *   <li>{@code importedKeySetDefault} - change imported key to default if its primary key has been deleted</li>
-         * </ul>
-         */
-        public static final String DELETE_RULE = "DELETE_RULE";
-
-        /** Foreign key name (values in this column may be null). */
-        public static final String FK_NAME = "FK_NAME";
-
-        /** Primary key name (values in this column may be null). */
-        public static final String PK_NAME = "PK_NAME";
-
-        /**
-         * Whether the evaluation of foreign key constraints can be deferred until commit, as a {@code short} code.
-         * <ul>
-         *   <li>{@code importedKeyInitiallyDeferred} - see SQL92 for definition</li>
-         *   <li>{@code importedKeyInitiallyImmediate} - see SQL92 for definition</li>
-         *   <li>{@code importedKeyNotDeferrable} - see SQL92 for definition</li>
-         * </ul>
-         */
-        public static final String DEFERRABILITY = "DEFERRABILITY";
-
-        private ExportedKey() {
-        }
-    }
-
-    public static final class BestRow{
-        /**
-         * Actual scope of result as a {@code short} code.
-         *  bestRowTemporary - very temporary, while using row
-         *  bestRowTransaction - valid for remainder of current transaction
-         *  bestRowSession - valid for remainder of current session.
-         */
-        public static final String SCOPE = "SCOPE";
-
-        /** Column name. */
-        public static final String COLUMN_NAME = "COLUMN_NAME";
-
-        /** SQL data type from {@link java.sql.Types}. */
-        public static final String DATA_TYPE = "DATA_TYPE";
-
-        /** Data source dependent type name. For a UDT the type name is fully qualified. */
-        public static final String TYPE_NAME = "TYPE_NAME";
-
-        /** Precision as an {@code int}. */
-        public static final String COLUMN_SIZE = "COLUMN_SIZE";
-
-        /** Not used. */
-        public static final String BUFFER_LENGTH = "BUFFER_LENGTH";
-
-        /** Scale - Null is returned for data types where DECIMAL_DIGITS is not applicable. */
-        public static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";
-
-        /**
-         * Whether this a pseudo column like an Oracle ROWID, as a {@code short} code.
-         * bestRowUnknown - may or may not be pseudo column
-         * bestRowNotPseudo - is NOT a pseudo column
-         * bestRowPseudo - is a pseudo column.
-         */
-        public static final String PSEUDO_COLUMN = "PSEUDO_COLUMN";
-
-        private BestRow() {
-        }
-    }
-
-    public static final class Index {
-        /** Table catalog (values in this column may be null). */
-        public static final String TABLE_CAT = "TABLE_CAT";
-
-        /** Table schema (values in this column may be null). */
-        public static final String TABLE_SCHEM = "TABLE_SCHEM";
-
-        /** Table name. */
-        public static final String TABLE_NAME = "TABLE_NAME";
-
-        /** Whether index values can be non-unique.
-         * false when TYPE is tableIndexStatistic  */
-        public static final String NON_UNIQUE = "NON_UNIQUE";
-
-        /**
-         * Index catalog (values in this column may be null).
-         * Values are null when TYPE is tableIndexStatistic.
-         */
-        public static final String INDEX_QUALIFIER = "INDEX_QUALIFIER";
-
-        /** Index name; null when TYPE is tableIndexStatistic. */
-        public static final String INDEX_NAME = "INDEX_NAME";
-
-        /**
-         * Index type as a {@code short} code.
-         *   tableIndexStatistic - this identifies table statistics that are
-         *       returned in conjuction with a table's index descriptions
-         *   tableIndexClustered - this is a clustered index
-         *   tableIndexHashed - this is a hashed index
-         *   tableIndexOther - this is some other style of index.
-         */
-        public static final String TYPE = "TYPE";
-
-        /**
-         * Column sequence number within index as a {@code short}.
-         * Zero when TYPE is tableIndexStatistic.
-         */
-        public static final String ORDINAL_POSITION = "ORDINAL_POSITION";
-
-        /** Column name. Values are null when TYPE is tableIndexStatistic. */
-        public static final String COLUMN_NAME = "COLUMN_NAME";
-
-        /**
-         * Column sort sequence.
-         * "A" for ascending,
-         * "D" for descending, may be null if sort sequence is not supported;
-         * null when TYPE is tableIndexStatistic.
-         */
-        public static final String ASC_OR_DESC = "ASC_OR_DESC";
-
-        /**
-         * When TYPE is tableIndexStatistic, then this is the number of rows in the table as an {@code int}.
-         * Otherwise, it is the number of unique values in the index.
-         */
-        public static final String CARDINALITY = "CARDINALITY";
-
-        /**
-         * When TYPE is tableIndexStatisic then this is the number of pages used for the table as an {@code int}.
-         * Otherwise it is the number of pages used for the current index.
-         */
-        public static final String PAGES = "PAGES";
-
-        /** Filter condition, if any. Values in this column may be null. */
-        public static final String FILTER_CONDITION = "FILTER_CONDITION";
-
-        private Index() {
-        }
-    }
-
-    private MetaDataConstants() {
-    }
-}
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SingleAttributeTypeBuilder.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SingleAttributeTypeBuilder.java
deleted file mode 100644
index ad22d65..0000000
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/feature/SingleAttributeTypeBuilder.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * 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.internal.sql.feature;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.apache.sis.feature.DefaultAttributeType;
-import org.opengis.feature.AttributeType;
-import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.opengis.util.GenericName;
-import org.apache.sis.internal.feature.AttributeConvention;
-import org.apache.sis.internal.system.DefaultFactories;
-import org.opengis.util.NameFactory;
-
-import static org.apache.sis.feature.AbstractIdentifiedType.*;
-
-
-/**
- * Builder for a single {@link AttributeType}.
- * This is an alternative to {@link org.apache.sis.feature.builder.PropertyTypeBuilder}.
- *
- * @author  Johann Sorel (Geomatys)
- * @version 1.0
- * @since   1.0
- * @module
- *
- * @todo Is this class really needed?
- */
-public final class SingleAttributeTypeBuilder {
-    /**
-     * Properties (name, description, …) to give to the attribute type constructor.
-     */
-    private final Map<String,Object> properties;
-
-    /**
-     * Optional characteristics of the attribute.
-     */
-    private final List<AttributeType<?>> characteristics;
-
-    /**
-     * The class of the attribute.
-     */
-    private Class<?> valueClass;
-
-    /**
-     * Minimum number of occurrences.
-     */
-    private int minimumOccurs;
-
-    /**
-     * Maximum number of occurrences.
-     */
-    private int maximumOccurs;
-
-    /**
-     * The default value, or {@code null} if none.
-     */
-    private Object defaultValue;
-
-    /**
-     * Creates a new attribute type builder.
-     */
-    public SingleAttributeTypeBuilder() {
-        properties      = new HashMap<>();
-        characteristics = new ArrayList<>();
-        minimumOccurs   = 1;
-        maximumOccurs   = 1;
-    }
-
-    /**
-     * Restores this builder to its initial state.
-     * This method can be invoked before to build another attribute.
-     *
-     * @return {@code this} for method call chaining.
-     */
-    public SingleAttributeTypeBuilder reset(){
-        properties.clear();
-        characteristics.clear();
-        valueClass    = null;
-        minimumOccurs = 1;
-        maximumOccurs = 1;
-        defaultValue  = null;
-        return this;
-    }
-
-    /**
-     * Sets this builder to the same properties then the given attribute type.
-     *
-     * @param  template  the attribute type to use as a template.
-     * @return {@code this} for method call chaining.
-     */
-    public SingleAttributeTypeBuilder copy(AttributeType<?> template) {
-        reset();
-        setName       (template.getName());
-        setDefinition (template.getDefinition());
-        setDescription(template.getDescription());
-        setDesignation(template.getDesignation());
-        characteristics.addAll(template.characteristics().values());
-        valueClass    = template.getValueClass();
-        minimumOccurs = template.getMinimumOccurs();
-        maximumOccurs = template.getMaximumOccurs();
-        defaultValue  = template.getDefaultValue();
-        return this;
-    }
-
-    public SingleAttributeTypeBuilder setName(String localPart) {
-        return setName(null, localPart);
-    }
-
-    public SingleAttributeTypeBuilder setName(String namespace, String localPart) {
-        final GenericName name;
-        if (namespace == null || namespace.isEmpty()) {
-            name = DefaultFactories.forBuildin(NameFactory.class).createGenericName(null, localPart);
-        } else {
-            name = DefaultFactories.forBuildin(NameFactory.class).createGenericName(null, namespace, localPart);
-        }
-        return setName(name);
-    }
-
-    public SingleAttributeTypeBuilder setName(GenericName name) {
-        properties.put(DefaultAttributeType.NAME_KEY, name);
-        return this;
-    }
-
-    public GenericName getName() {
-        return (GenericName) properties.get(DefaultAttributeType.NAME_KEY);
-    }
-
-    public SingleAttributeTypeBuilder setDescription(CharSequence description) {
-        properties.put(DESCRIPTION_KEY, description);
-        return this;
-    }
-
-    public CharSequence getDescription() {
-        return (CharSequence) properties.get(DESCRIPTION_KEY);
-    }
-
-    public SingleAttributeTypeBuilder setDesignation(CharSequence designation){
-        properties.put(DESIGNATION_KEY, designation);
-        return this;
-    }
-
-    public CharSequence getDesignation(){
-        return (CharSequence) properties.get(DESIGNATION_KEY);
-    }
-
-    public SingleAttributeTypeBuilder setDefinition(CharSequence definition){
-        properties.put(DEFINITION_KEY, definition);
-        return this;
-    }
-
-    public CharSequence getDefinition(){
-        return (CharSequence) properties.get(DEFINITION_KEY);
-    }
-
-    public SingleAttributeTypeBuilder setValueClass(Class<?> valueClass) {
-        this.valueClass = valueClass;
-        return this;
-    }
-
-    public Class<?> getValueClass(){
-        return valueClass;
-    }
-
-    public SingleAttributeTypeBuilder setDefaultValue(Object defaultValue) {
-        this.defaultValue = defaultValue;
-        return this;
-    }
-
-    public Object getDefaultValue() {
-        return defaultValue;
-    }
-
-    public SingleAttributeTypeBuilder setMinimumOccurs(int minimumOccurs) {
-        this.minimumOccurs = minimumOccurs;
-        return this;
-    }
-
-    public int getMinimumOccurs() {
-        return minimumOccurs;
-    }
-
-    public SingleAttributeTypeBuilder setMaximumOccurs(int maximumOccurs) {
-        this.maximumOccurs = maximumOccurs;
-        return this;
-    }
-
-    public int getMaximumOccurs() {
-        return maximumOccurs;
-    }
-
-    /**
-     * Set maximum string length.
-     *
-     * @param  length maximal number of characters.
-     * @return {@code this} for method call chaining.
-     */
-    public SingleAttributeTypeBuilder setLength(int length) {
-        return addCharacteristic(AttributeConvention.MAXIMAL_LENGTH_CHARACTERISTIC, Integer.class, 0, 1, length);
-    }
-
-    public SingleAttributeTypeBuilder setCRS(CoordinateReferenceSystem crs) {
-        return addCharacteristic(AttributeConvention.CRS_CHARACTERISTIC, CoordinateReferenceSystem.class, 0, 1, crs);
-    }
-
-    public SingleAttributeTypeBuilder setPossibleValues(Collection<?> values) {
-        return addCharacteristic(AttributeConvention.VALID_VALUES_CHARACTERISTIC, Object.class, 0, 1, values);
-    }
-
-    public SingleAttributeTypeBuilder addCharacteristic(String localPart, Class<?> valueClass, int minimumOccurs, int maximumOccurs, Object defaultValue) {
-        final GenericName name = DefaultFactories.forBuildin(NameFactory.class).createGenericName(null, localPart);
-        return addCharacteristic(name,valueClass,minimumOccurs,maximumOccurs,defaultValue);
-    }
-
-    public SingleAttributeTypeBuilder addCharacteristic(GenericName name, Class<?> valueClass, int minimumOccurs, int maximumOccurs, Object defaultValue) {
-        return addCharacteristic(new DefaultAttributeType(
-                    Collections.singletonMap(NAME_KEY, name),
-                    valueClass,minimumOccurs,maximumOccurs,defaultValue));
-    }
-
-    public SingleAttributeTypeBuilder addCharacteristic(AttributeType<?> characteristic) {
-        //search and remove previous characteristic with the same id if it exist
-        for (AttributeType<?> at : characteristics) {
-            if (at.getName().equals(characteristic.getName())) {
-                characteristics.remove(at);
-                break;
-            }
-        }
-        characteristics.add(characteristic);
-        return this;
-    }
-
-    public AttributeType<?> build(){
-        return new DefaultAttributeType(properties, valueClass,
-                minimumOccurs, maximumOccurs,
-                defaultValue, characteristics.toArray(new AttributeType[characteristics.size()]));
-    }
-
-    public static AttributeType<?> create(GenericName name, Class<?> valueClass) {
-        return new DefaultAttributeType(Collections.singletonMap("name", name), valueClass, 1, 1, null);
-    }
-}
diff --git a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java
index 6bd82cd..2ec1041 100644
--- a/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java
+++ b/storage/sis-sql/src/main/java/org/apache/sis/internal/sql/postgres/PostgresDialect.java
@@ -23,16 +23,16 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import org.apache.sis.internal.sql.feature.SingleAttributeTypeBuilder;
 import org.apache.sis.internal.sql.feature.ColumnMetaModel;
-import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.internal.sql.feature.Dialect;
+import org.apache.sis.feature.builder.AttributeTypeBuilder;
+import org.apache.sis.storage.DataStoreException;
 
 
 /**
  * Implements PostgreSQL-specific functionalities.
  *
- * @author Johann Sorel (Geomatys)
+ * @author  Johann Sorel (Geomatys)
  * @version 1.0
  * @since   1.0
  * @module
@@ -51,11 +51,6 @@ final class PostgresDialect extends Dialect {
     }
 
     @Override
-    public boolean supportGlobalMetadata() {
-        return true;
-    }
-
-    @Override
     public boolean isTableIgnored(String name) {
         return IGNORE_TABLES.contains(name.toLowerCase());
     }
@@ -66,16 +61,6 @@ final class PostgresDialect extends Dialect {
     }
 
     @Override
-    public void encodeColumnName(StringBuilder sql, String name) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public void encodeSchemaAndTableName(StringBuilder sql, String databaseSchema, String tableName) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
     public Object nextValue(ColumnMetaModel column, Connection cx) throws SQLException, DataStoreException {
         throw new UnsupportedOperationException("Not supported yet.");
     }
@@ -86,12 +71,12 @@ final class PostgresDialect extends Dialect {
     }
 
     @Override
-    public void decodeColumnType(SingleAttributeTypeBuilder atb, Connection cx, String typeName, int datatype, String schemaName, String tableName, String columnName) throws SQLException {
+    public void decodeColumnType(AttributeTypeBuilder<?> atb, Connection cx, String typeName, int datatype, String schemaName, String tableName, String columnName) throws SQLException {
         throw new UnsupportedOperationException("Not supported yet.");
     }
 
     @Override
-    public void decodeGeometryColumnType(SingleAttributeTypeBuilder atb, Connection cx, ResultSet rs, int columnIndex, boolean customquery) throws SQLException {
+    public void decodeGeometryColumnType(AttributeTypeBuilder<?> atb, Connection cx, ResultSet rs, int columnIndex, boolean customquery) throws SQLException {
         throw new UnsupportedOperationException("Not supported yet.");
     }
 


[sis] 03/03: Leverage Reflection constants in other modules.

Posted by de...@apache.org.
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 8b9558f54bf55dced1819f5d93093855686b212d
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Wed Jul 4 17:51:18 2018 +0200

    Leverage Reflection constants in other modules.
---
 .../sis/internal/metadata/sql/Reflection.java       | 21 +++++++++++++--------
 .../org/apache/sis/metadata/sql/MetadataSource.java |  3 ++-
 .../org/apache/sis/metadata/sql/MetadataWriter.java | 11 ++++++-----
 .../sis/referencing/factory/sql/SQLTranslator.java  |  9 +++++----
 .../referencing/factory/sql/EPSGInstallerTest.java  |  3 ++-
 5 files changed, 28 insertions(+), 19 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 45f21b2..71ea48a 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
@@ -41,6 +41,13 @@ import java.sql.DatabaseMetaData;
  */
 public final class Reflection {
     /**
+     * The {@value} key for getting a catalog name. This column appears in all reflection
+     * operations (listing schemas, tables, columns, constraints, <i>etc.</i>) used by SIS.
+     * The value in that column may be null.
+     */
+    public static final String TABLE_CAT = "TABLE_CAT";
+
+    /**
      * The {@value} key for getting a schema name. This column appears in all reflection
      * operations (listing schemas, tables, columns, constraints, <i>etc.</i>) used by SIS.
      * The value in that column may be null.
@@ -86,14 +93,6 @@ public final class Reflection {
     public static final String COLUMN_SIZE = "COLUMN_SIZE";
 
     /**
-     * The {@value} key for the number of fractional digits.
-     * Null is returned for data types where {@code DECIMAL_DIGITS} is not applicable.
-     *
-     * <p>Values in this column are integers ({@code int}) rather than {@code String}.</p>
-     */
-    public static final String DECIMAL_DIGITS = "DECIMAL_DIGITS";
-
-    /**
      * The {@value} key for the nullability of a column. Possible values are {@code "YES"} if
      * the parameter can include NULLs, {@code "NO"} if the parameter cannot include NULLs,
      * and empty string if the nullability for the parameter is unknown.
@@ -120,6 +119,12 @@ public final class Reflection {
     public static final String PK_NAME = "PK_NAME";
 
     /**
+     * The {@value} key for the primary key table catalog being imported.
+     * Values in this column may be null.
+     */
+    public static final String PKTABLE_CAT = "PKTABLE_CAT";
+
+    /**
      * The {@value} key for the primary key table schema being imported.
      * Values in this column may be null.
      */
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
index e268e80..4501b17 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataSource.java
@@ -56,6 +56,7 @@ import org.apache.sis.internal.system.SystemListener;
 import org.apache.sis.internal.system.DelayedExecutor;
 import org.apache.sis.internal.system.DelayedRunnable;
 import org.apache.sis.internal.metadata.sql.Initializer;
+import org.apache.sis.internal.metadata.sql.Reflection;
 import org.apache.sis.internal.metadata.sql.SQLBuilder;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.CollectionsExt;
@@ -792,7 +793,7 @@ public class MetadataSource implements AutoCloseable {
             final DatabaseMetaData md = connection().getMetaData();
             try (ResultSet rs = md.getColumns(catalog, schema, table, null)) {
                 while (rs.next()) {
-                    if (!columns.add(rs.getString("COLUMN_NAME"))) {
+                    if (!columns.add(rs.getString(Reflection.COLUMN_NAME))) {
                         // Paranoiac check, but should never happen.
                         throw new SQLNonTransientException(table);
                     }
diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java
index f205d0f..4b96b98 100644
--- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java
+++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/MetadataWriter.java
@@ -51,6 +51,7 @@ import org.apache.sis.metadata.ValueExistencePolicy;
 import org.apache.sis.metadata.TitleProperty;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.internal.metadata.sql.SQLBuilder;
+import org.apache.sis.internal.metadata.sql.Reflection;
 import org.apache.sis.xml.IdentifiedObject;
 
 // Branch-dependent imports
@@ -446,12 +447,12 @@ public class MetadataWriter extends MetadataSource {
                                     referencedTables = new HashMap<>();
                                     try (ResultSet rs = stmt.getConnection().getMetaData().getImportedKeys(catalog, schema(), table)) {
                                         while (rs.next()) {
-                                            if ((schema() == null || schema().equals(rs.getString("PKTABLE_SCHEM"))) &&
-                                                (catalog  == null || catalog.equals(rs.getString("PKTABLE_CAT"))))
+                                            if ((schema() == null || schema().equals(rs.getString(Reflection.PKTABLE_SCHEM))) &&
+                                                (catalog  == null || catalog.equals(rs.getString(Reflection.PKTABLE_CAT))))
                                             {
-                                                referencedTables.put(rs.getString("FKCOLUMN_NAME"),
-                                                            new FKey(rs.getString("PKTABLE_NAME"), null,
-                                                                     rs.getString("FK_NAME")));
+                                                referencedTables.put(rs.getString(Reflection.FKCOLUMN_NAME),
+                                                            new FKey(rs.getString(Reflection.PKTABLE_NAME), null,
+                                                                     rs.getString(Reflection.FK_NAME)));
                                             }
                                         }
                                     }
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
index 43c8641..dcf96ee 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
@@ -28,6 +28,7 @@ import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.internal.metadata.sql.Reflection;
 
 
 /**
@@ -264,8 +265,8 @@ public class SQLTranslator implements Function<String,String> {
                     isPrefixed      = table.startsWith(TABLE_PREFIX);
                     quoteTableNames = (i == MIXED_CASE);
                     do {
-                        catalog = result.getString("TABLE_CAT");
-                        schema  = result.getString("TABLE_SCHEM");
+                        catalog = result.getString(Reflection.TABLE_CAT);
+                        schema  = result.getString(Reflection.TABLE_SCHEM);
                     } while (!Constants.EPSG.equalsIgnoreCase(schema) && result.next());
                     if (schema == null) schema = "";
                     break;
@@ -304,8 +305,8 @@ public class SQLTranslator implements Function<String,String> {
         }
         try (ResultSet result = md.getColumns(catalog, schema, null, deprecated)) {
             while (result.next()) {
-                if (CharSequences.endsWith(result.getString("TABLE_NAME"), "Datum", true)) {
-                    final int type = result.getInt("DATA_TYPE");
+                if (CharSequences.endsWith(result.getString(Reflection.TABLE_NAME), "Datum", true)) {
+                    final int type = result.getInt(Reflection.DATA_TYPE);
                     useBoolean = (type == Types.BOOLEAN) || (type == Types.BIT);
                     break;
                 }
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java b/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
index b247659..2fcdfb3 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
@@ -35,6 +35,7 @@ import org.opengis.referencing.crs.ProjectedCRS;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.internal.system.Loggers;
 import org.apache.sis.internal.util.Constants;
+import org.apache.sis.internal.metadata.sql.Reflection;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.Utilities;
 
@@ -240,7 +241,7 @@ public final strictfp class EPSGInstallerTest extends TestCase {
         try (Connection c = ds.getConnection()) {
             try (ResultSet r = c.getMetaData().getTables(null, null, "Coordinate Reference System", null)) {
                 while (r.next()) {
-                    final String schema = r.getString("TABLE_SCHEM");
+                    final String schema = r.getString(Reflection.TABLE_SCHEM);
                     assertTrue(schema, "EPSG".equalsIgnoreCase(schema));
                     count++;
                 }