sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1729195 - in /sis/branches/JDK8/core: sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/ sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/
Date Mon, 08 Feb 2016 15:56:00 GMT
Author: desruisseaux
Date: Mon Feb  8 15:56:00 2016
New Revision: 1729195

URL: http://svn.apache.org/viewvc?rev=1729195&view=rev
Log:
Replace empty string by NULL value in EPSG database, and use the BOOLEAN type where appropriate.

Modified:
    sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/AuthorityCodes.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGDataFormatter.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java

Modified: sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/sql/ScriptRunner.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -275,10 +275,10 @@ public class ScriptRunner implements Aut
                  * In addition, we must declare explicitly that we want the tables to be
cached on disk. Finally,
                  * HSQL expects "CHR" to be spelled "CHAR".
                  */
-                replace("UNIQUE", "");
-                replace("CHR", "CHAR");
-                replace("CREATE", MORE_WORDS);
-                replace("CREATE TABLE", "CREATE CACHED TABLE");
+                addReplacement("UNIQUE", "");
+                addReplacement("CHR", "CHAR");
+                addReplacement("CREATE", MORE_WORDS);
+                addReplacement("CREATE TABLE", "CREATE CACHED TABLE");
                 break;
             }
         }
@@ -314,13 +314,24 @@ public class ScriptRunner implements Aut
      * @param inScript The word in the script which need to be replaced.
      * @param replacement The word to use instead.
      */
-    protected final void replace(final String inScript, final String replacement) {
+    protected final void addReplacement(final String inScript, final String replacement)
{
         if (replacements.put(inScript, replacement) != null) {
             throw new IllegalArgumentException(inScript);
         }
     }
 
     /**
+     * Returns the word to use instead than the given one.
+     * If there is no replacement, then {@code inScript} is returned.
+     *
+     * @param inScript The word in the script which need to be replaced.
+     * @return The word to use instead.
+     */
+    protected final String getReplacement(final String inScript) {
+        return replacements.getOrDefault(inScript, inScript);
+    }
+
+    /**
      * For every entries in the replacements map, replace the entry value by the value returned
by
      * {@code function(key, value)}.
      *
@@ -373,8 +384,8 @@ public class ScriptRunner implements Aut
      * @throws SQLException if an error occurred while executing a SQL statement.
      */
     private int run(final LineNumberReader in) throws IOException, SQLException {
-        int     statementCount     = 0;
-        boolean isInsideText       = false;
+        int     statementCount     = 0;         // For informative purpose only.
+        int     posOpeningQuote    = -1;        // -1 if we are not inside a text.
         boolean isInsideIdentifier = false;
         final StringBuilder buffer = new StringBuilder();
         String line;
@@ -423,7 +434,7 @@ public class ScriptRunner implements Aut
 parseLine:  while (pos < length) {
                 int c = buffer.codePointAt(pos);
                 int n = Character.charCount(c);
-                if (!isInsideText && !isInsideIdentifier) {
+                if (posOpeningQuote < 0 && !isInsideIdentifier) {
                     int start = pos;
                     while (Character.isUnicodeIdentifierStart(c)) {
                         /*
@@ -474,7 +485,7 @@ parseLine:  while (pos < length) {
                      * replace the standard quote character by the database-specific one.
                      */
                     case IDENTIFIER_QUOTE: {
-                        if (!isInsideText) {
+                        if (posOpeningQuote < 0) {
                             isInsideIdentifier = !isInsideIdentifier;
                             length = buffer.replace(pos, pos + n, identifierQuote).length();
                             n = identifierQuote.length();
@@ -487,10 +498,12 @@ parseLine:  while (pos < length) {
                      */
                     case QUOTE: {
                         if (!isInsideIdentifier) {
-                            if (!isInsideText) {
-                                isInsideText = true;
+                            if (posOpeningQuote < 0) {
+                                posOpeningQuote = pos;
                             } else if ((pos += n) >= length || buffer.codePointAt(pos)
!= QUOTE) {
-                                isInsideText = false;
+                                editText(buffer, posOpeningQuote, pos);
+                                pos -= length - (length = buffer.length());
+                                posOpeningQuote = -1;
                                 continue;   // Because we already skipped the ' character.
                             } // else found a double ' character, which means to escape it.
                         }
@@ -501,7 +514,7 @@ parseLine:  while (pos < length) {
                      * since SQL statement in JDBC are not expected to contain it.
                      */
                     case END_OF_STATEMENT: {
-                        if (!isInsideText && !isInsideIdentifier) {
+                        if (posOpeningQuote < 0 && !isInsideIdentifier) {
                             if (CharSequences.skipLeadingWhitespaces(buffer, pos + n, length)
>= length) {
                                 buffer.setLength(pos);
                             }
@@ -523,6 +536,19 @@ parseLine:  while (pos < length) {
     }
 
     /**
+     * Invoked for each text found in a SQL statement. The text, <em>including its
quote characters</em>,
+     * is the {@code sql} substring from index {@code lower} inclusive to {@code upper} exclusive.
+     * Subclasses can override this method if they wish to modify the text content.
+     * Modifications are applied directly in the given {@code sql} buffer.
+     *
+     * @param sql   The whole SQL statement.
+     * @param lower Index of the opening quote character ({@code '}) of the text in {@code
sql}.
+     * @param upper Index after the closing quote character ({@code '}) of the text in {@code
sql}.
+     */
+    protected void editText(final StringBuilder sql, final int lower, final int upper) {
+    }
+
+    /**
      * Executes the given SQL statement.
      * This method performs the following choices:
      *
@@ -574,7 +600,7 @@ parseLine:  while (pos < length) {
                                 if (subSQL.charAt(end - 1) == ',') {
                                     end--;
                                 }
-                                count += statement.executeUpdate(sql.append(subSQL, begin,
end).toString());
+                                count += statement.executeUpdate(currentSQL = sql.append(subSQL,
begin, end).toString());
                                 sql.setLength(startOfValues);       // Prepare for next INSERT
INTO statement.
                                 nrows = maxRowsPerInsert;
                                 begin = endOfLine + 1;
@@ -582,7 +608,7 @@ parseLine:  while (pos < length) {
                         }
                         // The remaining of the statement to be executed.
                         int end = CharSequences.skipTrailingWhitespaces(subSQL, begin, subSQL.length());
-                        subSQL = (end > begin) ? sql.append(subSQL, begin, end).toString()
: null;
+                        currentSQL = subSQL = (end > begin) ? sql.append(subSQL, begin,
end).toString() : null;
                     }
                 }
             }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/AuthorityCodes.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/AuthorityCodes.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/AuthorityCodes.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/AuthorityCodes.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -160,7 +160,9 @@ final class AuthorityCodes extends Abstr
         final int conditionStart = buffer.length();
         if (table.showColumn != null) {
             buffer.append(table.showColumn).append("<>0 AND ");
+            // Do not put spaces around "<>" - SQLTranslator searches for this exact
match.
         }
+        // Do not put spaces around "=" - SQLTranslator searches for this exact match.
         buffer.append("DEPRECATED=0 ORDER BY ").append(table.codeColumn);
         sql[ALL] = factory.translator.apply(buffer.toString());
         /*

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -1566,7 +1566,7 @@ addURIs:    for (int i=0; ; i++) {
                       " COORD_OP_METHOD_CODE," +
                       " TARGET_CRS_CODE" +
                 " FROM [Coordinate_Operation]" +
-               " WHERE DEPRECATED=0" +
+               " WHERE DEPRECATED=0" +           // Do not put spaces around "=" - SQLTranslator
searches for this exact match.
                  " AND TARGET_CRS_CODE = "       + BursaWolfInfo.TARGET_CRS +
                  " AND COORD_OP_METHOD_CODE >= " + BursaWolfInfo.MIN_METHOD_CODE +
                  " AND COORD_OP_METHOD_CODE <= " + BursaWolfInfo.MAX_METHOD_CODE +
@@ -2913,7 +2913,7 @@ addURIs:    for (int i=0; ; i++) {
             }
             buffer.append(getSearchDomain() == Domain.ALL_DATASET
                           ? " ORDER BY ABS(DEPRECATED), "
-                          : " AND DEPRECATED=0 ORDER BY ");
+                          : " AND DEPRECATED=0 ORDER BY ");     // Do not put spaces around
"=" - SQLTranslator searches for this exact match.
             if (isFloat) {
                 buffer.append("ABS(").append(select).append("-?), ");
             }
@@ -3023,7 +3023,8 @@ addURIs:    for (int i=0; ; i++) {
                       " FROM [Coordinate_Operation] AS CO" +
                 " INNER JOIN [Coordinate Reference System] AS SRC ON SRC.COORD_REF_SYS_CODE
= CO.SOURCE_CRS_CODE" +
                 " INNER JOIN [Coordinate Reference System] AS TGT ON TGT.COORD_REF_SYS_CODE
= CO.TARGET_CRS_CODE" +
-                      " WHERE CO.DEPRECATED = 0 AND COORD_OP_METHOD_CODE = ?";
+                      " WHERE CO.DEPRECATED=0 AND COORD_OP_METHOD_CODE = ?";
+                // Do not put spaces in "DEPRECATED=0" - SQLTranslator searches for this
exact match.
             } else {
                 key = "DerivedDimensions";
                 sql = "SELECT DISTINCT SRC.COORD_SYS_CODE," +
@@ -3031,7 +3032,7 @@ addURIs:    for (int i=0; ; i++) {
                       " FROM [Coordinate Reference System] AS TGT" +
                 " INNER JOIN [Coordinate Reference System] AS SRC ON TGT.SOURCE_GEOGCRS_CODE
= SRC.COORD_REF_SYS_CODE" +
                 " INNER JOIN [Coordinate_Operation] AS CO ON TGT.PROJECTION_CONV_CODE = CO.COORD_OP_CODE"
+
-                      " WHERE CO.DEPRECATED = 0 AND COORD_OP_METHOD_CODE = ?";
+                      " WHERE CO.DEPRECATED=0 AND COORD_OP_METHOD_CODE = ?";
             }
             try (ResultSet result = executeQuery(key, sql, method)) {
                 while (result.next()) {

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -142,27 +142,27 @@ final class EPSGInstaller extends Script
              * Mapping from the table names used in the SQL scripts to the original names
used in the MS-Access database.
              * We use those original names because they are easier to read than the names
in SQL scripts.
              */
-            replace(SQLTranslator.TABLE_PREFIX + "alias",                      "Alias");
-            replace(SQLTranslator.TABLE_PREFIX + "area",                       "Area");
-            replace(SQLTranslator.TABLE_PREFIX + "change",                     "Change");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinateaxis",             "Coordinate
Axis");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinateaxisname",         "Coordinate
Axis Name");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperation",             "Coordinate_Operation");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationmethod",       "Coordinate_Operation
Method");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationparam",        "Coordinate_Operation
Parameter");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationparamusage",   "Coordinate_Operation
Parameter Usage");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationparamvalue",   "Coordinate_Operation
Parameter Value");
-            replace(SQLTranslator.TABLE_PREFIX + "coordoperationpath",         "Coordinate_Operation
Path");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinatereferencesystem",  "Coordinate
Reference System");
-            replace(SQLTranslator.TABLE_PREFIX + "coordinatesystem",           "Coordinate
System");
-            replace(SQLTranslator.TABLE_PREFIX + "datum",                      "Datum");
-            replace(SQLTranslator.TABLE_PREFIX + "deprecation",                "Deprecation");
-            replace(SQLTranslator.TABLE_PREFIX + "ellipsoid",                  "Ellipsoid");
-            replace(SQLTranslator.TABLE_PREFIX + "namingsystem",               "Naming System");
-            replace(SQLTranslator.TABLE_PREFIX + "primemeridian",              "Prime Meridian");
-            replace(SQLTranslator.TABLE_PREFIX + "supersession",               "Supersession");
-            replace(SQLTranslator.TABLE_PREFIX + "unitofmeasure",              "Unit of Measure");
-            replace(SQLTranslator.TABLE_PREFIX + "versionhistory",             "Version History");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "alias",                      "Alias");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "area",                       "Area");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "change",                     "Change");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinateaxis",             "Coordinate
Axis");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinateaxisname",         "Coordinate
Axis Name");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperation",             "Coordinate_Operation");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationmethod",       "Coordinate_Operation
Method");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationparam",        "Coordinate_Operation
Parameter");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationparamusage",   "Coordinate_Operation
Parameter Usage");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationparamvalue",   "Coordinate_Operation
Parameter Value");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordoperationpath",         "Coordinate_Operation
Path");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinatereferencesystem",  "Coordinate
Reference System");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "coordinatesystem",           "Coordinate
System");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "datum",                      "Datum");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "deprecation",                "Deprecation");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "ellipsoid",                  "Ellipsoid");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "namingsystem",               "Naming
System");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "primemeridian",              "Prime
Meridian");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "supersession",               "Supersession");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "unitofmeasure",              "Unit
of Measure");
+            addReplacement(SQLTranslator.TABLE_PREFIX + "versionhistory",             "Version
History");
             prependNamespace(schema);
         }
     }
@@ -176,6 +176,34 @@ final class EPSGInstaller extends Script
     }
 
     /**
+     * Invoked for each text found in a SQL statement. This method replaces {@code ''} by
{@code Null}.
+     * The intend is to consistently use the null value for meaning "no information", which
is not the
+     * same than "information is an empty string". This replacement is okay in this particular
case
+     * since there is no field in the EPSG database for which we really want an empty string.
+     *
+     * @param sql   The whole SQL statement.
+     * @param lower Index of the first character of the text in {@code sql}.
+     * @param upper Index after the last character of the text in {@code sql}.
+     */
+    @Override
+    protected void editText(final StringBuilder sql, final int lower, final int upper) {
+        final String replacement;
+        switch (upper - lower) {
+            default: {
+                return;
+            }
+            /*
+             * Replace '' by Null for every table.
+             */
+            case 2: {
+                replacement = "Null";
+                break;
+            }
+        }
+        sql.replace(lower, upper, replacement);
+    }
+
+    /**
      * Modifies the SQL statement before to execute it, or omit unsupported statements.
      *
      * @throws SQLException if an error occurred while executing the SQL statement.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/SQLTranslator.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -22,6 +22,7 @@ import java.util.Locale;
 import java.sql.DatabaseMetaData;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Types;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
@@ -129,6 +130,15 @@ public class SQLTranslator implements Fu
     static final String TABLE_PREFIX = "epsg_";
 
     /**
+     * The columns that may be of {@code BOOLEAN} type instead of {@code SMALLINT}.
+     */
+    private static final String[] BOOLEAN_FIELDS = {
+        "SHOW_CRS",
+        "SHOW_OPERATION",
+        "DEPRECATED"
+    };
+
+    /**
      * The name of the catalog that contains the EPSG tables, or {@code null} or an empty
string.
      * <ul>
      *   <li>The {@code ""} value retrieves the EPSG schema without a catalog.</li>
@@ -184,6 +194,12 @@ public class SQLTranslator implements Fu
     private final String quote;
 
     /**
+     * {@code true} if the database uses the {@code BOOLEAN} type instead than {@code SMALLINT}
+     * for the {@code show_crs}, {@code show_operation} and all {@code deprecated} fields.
+     */
+    private boolean useBoolean;
+
+    /**
      * {@code true} if one of the {@link #SENTINEL} tables exist.
      * If {@code false}, then {@link EPSGInstaller} needs to be run.
      *
@@ -270,6 +286,22 @@ public class SQLTranslator implements Fu
         if (translateColumns) {
             accessToAnsi.put("ORDER", "coord_axis_order");
         }
+        /*
+         * Detect if the database uses boolean types where applicable.
+         * We arbitrarily use the Datum table as a representative value.
+         */
+        String deprecated = "DEPRECATED";
+        if (md.storesLowerCaseIdentifiers()) {
+            deprecated = deprecated.toLowerCase(Locale.US);
+        }
+        try (ResultSet result = md.getColumns(catalog, schema, null, deprecated)) {
+            while (result.next()) {
+                if (CharSequences.endsWith(result.getString("TABLE_NAME"), "Datum", true))
{
+                    useBoolean = result.getInt("DATA_TYPE") == Types.BOOLEAN;
+                    break;
+                }
+            }
+        }
     };
 
     /**
@@ -375,6 +407,38 @@ public class SQLTranslator implements Fu
                 }
             }
         }
-        return ansi.append(sql, end, sql.length()).toString();
+        ansi.append(sql, end, sql.length());
+        /*
+         * If the database use the BOOLEAN type instead of SMALLINT, replaces "deprecated=0'
by "deprecated=false".
+         */
+        if (useBoolean) {
+            int w = ansi.indexOf("WHERE");
+            w += 5;
+            if (w >= 0) {
+                for (final String field : BOOLEAN_FIELDS) {
+                    int p = ansi.indexOf(field, w);
+                    if (p >= 0) {
+                        p += field.length();
+                        if (!replaceIfEquals(ansi, p, "=0", "=FALSE")) {
+                            replaceIfEquals(ansi, p, "<>0", "=TRUE");
+                        }
+                    }
+                }
+            }
+        }
+        return ansi.toString();
+    }
+
+    /**
+     * Replaces the text at the given position in the buffer if it is equals to the {@code
expected} text.
+     */
+    private static boolean replaceIfEquals(final StringBuilder ansi, final int pos,
+            final String expected, final String replacement)
+    {
+        if (CharSequences.regionMatches(ansi, pos, expected)) {
+            ansi.replace(pos, pos + expected.length(), replacement);
+            return true;
+        }
+        return false;
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGDataFormatter.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGDataFormatter.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGDataFormatter.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGDataFormatter.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -16,6 +16,8 @@
  */
 package org.apache.sis.referencing.factory.sql;
 
+import java.util.Map;
+import java.util.HashMap;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -70,13 +72,15 @@ import org.apache.sis.internal.metadata.
  *
  *   <li><p>Open the {@code Tables.sql} file for edition:</p>
  *     <ul>
- *       <li>In the statement creating the {@code epsg_datum} table,
- *           change the type of the {@code realization_epoch} column to {@code SMALLINT}.</li>
  *       <li>In the statement creating the {@code coordinateaxis} table,
  *           add the {@code NOT NULL} constraint to the {@code coord_axis_code} column.</li>
  *       <li>In the statement creating the {@code change} table,
  *           remove the {@code UNIQUE} constraint on the {@code change_id} column
  *           and add a {@code CONSTRAINT pk_change PRIMARY KEY (change_id)} line instead.</li>
+ *       <li>In the statement creating the {@code epsg_datum} table,
+ *           change the type of the {@code realization_epoch} column to {@code SMALLINT}.</li>
+ *       <li>Change the type of {@code show_crs}, {@code show_operation} and all {@code
deprecated} fields
+ *           from {@code SMALLINT} to {@code BOOLEAN}.</li>
  *       <li>Suppress trailing spaces and save.</li>
  *     </ul>
  *     <p>Usually this results in no change at all compared to the previous script
(ignoring white spaces),
@@ -135,6 +139,16 @@ public final class EPSGDataFormatter ext
     }
 
     /**
+     * The {@value} keywords.
+     */
+    private static final String INSERT_INTO = "INSERT INTO";
+
+    /**
+     * The {@value} keywords.
+     */
+    private static final String VALUES = "VALUES";
+
+    /**
      * The output stream, or {@code null} if closed or not yet created.
      */
     private Writer out;
@@ -151,6 +165,17 @@ public final class EPSGDataFormatter ext
     private boolean insertDatum;
 
     /**
+     * Number of columns to change from type SMALLINT to type BOOLEAN.
+     * All those columns must be last.
+     */
+    private int numBooleanColumns;
+
+    /**
+     * The {@link #numBooleanColumns} value for each table.
+     */
+    private final Map<String,Integer> numBooleanColumnsForTables;
+
+    /**
      * Creates a new instance.
      *
      * @param  c A dummy connection. Will be used for fetching metadata.
@@ -158,6 +183,28 @@ public final class EPSGDataFormatter ext
      */
     private EPSGDataFormatter(final Connection c) throws SQLException {
         super(c, EPSGInstaller.ENCODING, Integer.MAX_VALUE);
+        numBooleanColumnsForTables = new HashMap<>();
+        numBooleanColumnsForTables.put("epsg_alias",                     0);
+        numBooleanColumnsForTables.put("epsg_area",                      1);
+        numBooleanColumnsForTables.put("epsg_change",                    0);
+        numBooleanColumnsForTables.put("epsg_coordinateaxis",            0);
+        numBooleanColumnsForTables.put("epsg_coordinateaxisname",        1);
+        numBooleanColumnsForTables.put("epsg_coordinatereferencesystem", 2);
+        numBooleanColumnsForTables.put("epsg_coordinatesystem",          1);
+        numBooleanColumnsForTables.put("epsg_coordoperation",            2);
+        numBooleanColumnsForTables.put("epsg_coordoperationmethod",      1);
+        numBooleanColumnsForTables.put("epsg_coordoperationparam",       1);
+        numBooleanColumnsForTables.put("epsg_coordoperationparamusage",  0);
+        numBooleanColumnsForTables.put("epsg_coordoperationparamvalue",  0);
+        numBooleanColumnsForTables.put("epsg_coordoperationpath",        0);
+        numBooleanColumnsForTables.put("epsg_datum",                     1);
+        numBooleanColumnsForTables.put("epsg_deprecation",               0);
+        numBooleanColumnsForTables.put("epsg_ellipsoid",                 1);
+        numBooleanColumnsForTables.put("epsg_namingsystem",              1);
+        numBooleanColumnsForTables.put("epsg_primemeridian",             1);
+        numBooleanColumnsForTables.put("epsg_supersession",              0);
+        numBooleanColumnsForTables.put("epsg_unitofmeasure",             1);
+        numBooleanColumnsForTables.put("epsg_versionhistory",            0);
     }
 
     /**
@@ -200,20 +247,22 @@ public final class EPSGDataFormatter ext
      * @param  sql The SQL statement to compact.
      * @return The number of rows added.
      * @throws IOException if an I/O operation failed.
+     * @throws SQLException if a syntax error happens.
      */
     @Override
-    protected int execute(final StringBuilder sql) throws IOException {
+    protected int execute(final StringBuilder sql) throws IOException, SQLException {
         removeLF(sql);
         String line = CharSequences.trimWhitespaces(sql).toString();
         if (insertStatement != null) {
             if (line.startsWith(insertStatement)) {
                 // The previous instruction was already an INSERT INTO the same table.
                 line = CharSequences.trimWhitespaces(line, insertStatement.length(), line.length()).toString();
+                line = replaceIntegerByBoolean(line);
                 line = removeUselessExponents(line);
                 if (insertDatum) {
                     line = removeRealizationEpochQuotes(line);
                 }
-                out.append(",\n"); // Really want Unix EOL, not the platform-specific one.
+                out.append(",\n");      // Really want Unix EOL, not the platform-specific
one.
                 writeValues(line);
                 return 1;
             }
@@ -221,23 +270,29 @@ public final class EPSGDataFormatter ext
             // We now have a new instruction. Append the pending cariage return.
             out.append(";\n");
         }
-        if (line.startsWith("INSERT INTO")) {
-            insertDatum = line.startsWith("INSERT INTO EPSG_DATUM VALUES");
-            int valuesStart = line.indexOf("VALUES", 11);
-            if (valuesStart >= 0) {
-                // We are beginning insertions in a new table.
-                valuesStart += 6; // Move to the end of "VALUES".
-                insertStatement = CharSequences.trimWhitespaces(line, 0, valuesStart).toString();
-                line = CharSequences.trimWhitespaces(line, insertStatement.length(), line.length()).toString();
-                line = removeUselessExponents(line);
-                if (insertDatum) {
-                    line = removeRealizationEpochQuotes(line);
-                }
-                out.append(insertStatement);
-                out.append('\n');
-                writeValues(line);
-                return 1;
+        if (line.startsWith(INSERT_INTO)) {
+            int valuesStart = line.indexOf(VALUES, INSERT_INTO.length());
+            if (valuesStart < 0) {
+                throw new SQLException("This simple program wants VALUES on the same line
than INSERT INTO.");
+            }
+            final String table = CharSequences.trimWhitespaces(line, INSERT_INTO.length(),
valuesStart).toString();
+            numBooleanColumns = numBooleanColumnsForTables.get(table);
+            insertDatum = table.equals("epsg_datum");
+            /*
+             * We are beginning insertions in a new table.
+             */
+            valuesStart += VALUES.length();     // Move to the end of "VALUES".
+            insertStatement = CharSequences.trimWhitespaces(line, 0, valuesStart).toString();
+            line = CharSequences.trimWhitespaces(line, insertStatement.length(), line.length()).toString();
+            line = replaceIntegerByBoolean(line);
+            line = removeUselessExponents(line);
+            if (insertDatum) {
+                line = removeRealizationEpochQuotes(line);
             }
+            out.append(insertStatement);
+            out.append('\n');
+            writeValues(line);
+            return 1;
         }
         insertStatement = null;
         if (!omit(line)) {
@@ -262,6 +317,30 @@ public final class EPSGDataFormatter ext
     }
 
     /**
+     * Replaces the last {@code SMALLINT} types by {@code BOOLEAN}.
+     * This is for consistency with the table type documented in the class javadoc.
+     */
+    private String replaceIntegerByBoolean(final String line) throws SQLException {
+        final StringBuilder buffer = new StringBuilder(line);
+        int end = line.length();
+        for (int n = 0; n < numBooleanColumns; n++) {
+            end = line.lastIndexOf(',', end - 1);
+            final int p = CharSequences.skipLeadingWhitespaces(line, end+1, line.length());
+            final boolean value;
+            switch (line.charAt(p)) {
+                case '0': value = false; break;
+                case '1': value = true;  break;
+                default: throw new SQLException("Unexpected boolean value at position " +
p + " in:\n" + line);
+            }
+            if (line.charAt(p+1) != (n == 0 ? ' ' : ',')) {
+                throw new SQLException("Unexpected character at position " + (p+1) + " in:\n"
+ line);
+            }
+            buffer.replace(p, p+1, String.valueOf(value));
+        }
+        return buffer.toString();
+    }
+
+    /**
      * For private usage by the following method only.
      */
     private static final Pattern uselessExponentPattern =

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java?rev=1729195&r1=1729194&r2=1729195&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
[UTF-8] Mon Feb  8 15:56:00 2016
@@ -17,7 +17,9 @@
 package org.apache.sis.referencing.factory.sql;
 
 import java.util.Map;
+import java.util.Set;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.regex.Pattern;
 import javax.sql.DataSource;
 import java.sql.Connection;
@@ -168,11 +170,33 @@ public final strictfp class EPSGInstalle
         assertEquals("Should not contain EPSG tables before we created them.", 0, countCRSTables(ds));
         assertEquals("Should not yet have logged anything at this point.", 100, listener.maximumLogCount);
         try (EPSGFactory factory = new EPSGFactory(properties)) {
+            /*
+             * Fetch the "WGS 84" coordinate reference system.
+             */
             final GeographicCRS crs = factory.createGeographicCRS("4326");
             assertTrue(Utilities.deepEquals(CommonCRS.WGS84.geographic(), crs, ComparisonMode.DEBUG));
-
-            final ProjectedCRS p = factory.createProjectedCRS("EPSG:32215");    // UTM zone
15.
+            /*
+             * Fetch the "WGS 72 / UTM zone 15" coordinate system.
+             * This implies the creation of a coordinate operation.
+             */
+            final ProjectedCRS p = factory.createProjectedCRS("EPSG:32215");
             assertTrue(Utilities.deepEquals(CommonCRS.WGS72.UTM(1, -93), p, ComparisonMode.DEBUG));
+            /*
+             * Get the authority codes. We choose a type that implies an SQL statement
+             * with both "DEPRECATED" and "SHOW_CRS" conditions in their "WHERE" clause.
+             */
+            Set<String> codes = factory.getAuthorityCodes(GeographicCRS.class);
+            assertTrue("4979", codes.contains("4979"));     // A non-deprecated code.
+            assertTrue("4329", codes.contains("4329"));     // A deprecated code.
+            /*
+             * Following forces the authority factory to iterate over all codes.
+             * Since the iterator returns only non-deprecated codes, EPSG:4329
+             * should not be included. The intend is to verify that the fields
+             * of type BOOLEAN have been properly handled.
+             */
+            codes = new HashSet<>(codes);
+            assertTrue ("4979", codes.contains("4979"));
+            assertFalse("4329", codes.contains("4329"));
         }
         assertEquals("Should contain EPSG tables after we created them.", 1, countCRSTables(ds));
         assertEquals("Should have logged a message about the database creation.", 99, listener.maximumLogCount);




Mime
View raw message