You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by re...@apache.org on 2015/06/22 14:50:57 UTC

svn commit: r1686854 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java

Author: reschke
Date: Mon Jun 22 12:50:57 2015
New Revision: 1686854

URL: http://svn.apache.org/r1686854
Log:
OAK-3010: dynamically check binary-ness of IF column using JDBC metadata, improve diagnostics

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java?rev=1686854&r1=1686853&r2=1686854&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java Mon Jun 22 12:50:57 2015
@@ -562,12 +562,6 @@ public class RDBDocumentStore implements
             }
 
             @Override
-            public boolean isPrimaryColumnByteEncoded() {
-                // TODO: we should dynamically detect this
-                return true;
-            }
-
-            @Override
             public String getTableCreationStatement(String tableName) {
                 // see https://issues.apache.org/jira/browse/OAK-1913
                 return ("create table " + tableName + " (ID varbinary(512) not null primary key, MODIFIED bigint, HASBINARY smallint, DELETEDONCE smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA varchar(16000), BDATA longblob)");
@@ -617,12 +611,6 @@ public class RDBDocumentStore implements
             }
 
             @Override
-            public boolean isPrimaryColumnByteEncoded() {
-                // TODO: we should dynamically detect this
-                return true;
-            }
-
-            @Override
             public String getTableCreationStatement(String tableName) {
                 // see https://issues.apache.org/jira/browse/OAK-2395
                 return ("create table " + tableName + " (ID varbinary(512) not null primary key, MODIFIED bigint, HASBINARY smallint, DELETEDONCE smallint, MODCOUNT bigint, CMODCOUNT bigint, DSIZE bigint, DATA nvarchar(4000), BDATA varbinary(max))");
@@ -680,15 +668,6 @@ public class RDBDocumentStore implements
         }
 
         /**
-         * If the primary column is encoded in bytes.
-         * Default false
-         * @return boolean
-         */
-        public boolean isPrimaryColumnByteEncoded() {
-            return false;
-        }
-
-        /**
          * Allows case in select. Default true.
          */
         public boolean allowsCaseInSelect() {
@@ -816,6 +795,9 @@ public class RDBDocumentStore implements
     // capacity of DATA column
     private int dataLimitInOctets = 16384;
 
+    // whether the ID column is a binary type
+    private boolean isIdBinary = false;
+
     // number of retries for updates
     private static final int RETRIES = 10;
 
@@ -893,11 +875,12 @@ public class RDBDocumentStore implements
 
         List<String> tablesCreated = new ArrayList<String>();
         List<String> tablesPresent = new ArrayList<String>();
+        StringBuilder tableDiags = new StringBuilder();
         try {
-            createTableFor(con, Collection.CLUSTER_NODES, tablesCreated, tablesPresent);
-            createTableFor(con, Collection.NODES, tablesCreated, tablesPresent);
-            createTableFor(con, Collection.SETTINGS, tablesCreated, tablesPresent);
-            createTableFor(con, Collection.JOURNAL, tablesCreated, tablesPresent);
+            createTableFor(con, Collection.CLUSTER_NODES, tablesCreated, tablesPresent, tableDiags);
+            createTableFor(con, Collection.NODES, tablesCreated, tablesPresent, tableDiags);
+            createTableFor(con, Collection.SETTINGS, tablesCreated, tablesPresent, tableDiags);
+            createTableFor(con, Collection.JOURNAL, tablesCreated, tablesPresent, tableDiags);
         } finally {
             con.commit();
             con.close();
@@ -907,11 +890,15 @@ public class RDBDocumentStore implements
             tablesToBeDropped.addAll(tablesCreated);
         }
 
+        if (tableDiags.length() != 0) {
+            tableDiags.insert(0, ", ");
+        }
+
         String diag = db.getAdditionalDiagnostics(this.ch, this.tnNodes);
 
         LOG.info("RDBDocumentStore instantiated for database " + dbDesc + ", using driver: " + driverDesc + ", connecting to: "
                 + dbUrl + (diag.isEmpty() ? "" : (", properties: " + diag)) + ", transaction isolation level: " + isolationDiags
-                + ", detected size of DATA column: " + this.dataLimitInOctets);
+                + tableDiags);
         if (!tablesPresent.isEmpty()) {
             LOG.info("Tables present upon startup: " + tablesPresent);
         }
@@ -921,7 +908,18 @@ public class RDBDocumentStore implements
         }
     }
 
-    private void createTableFor(Connection con, Collection<? extends Document> col, List<String> tablesCreated, List<String> tablesPresent) throws SQLException {
+    private static boolean isBinaryType(int sqlType) {
+        return sqlType == Types.VARBINARY || sqlType == Types.BINARY || sqlType == Types.LONGVARBINARY;
+    }
+
+    private static String dumpTableMeta(int idType, String idTypeName, int idPrecision, int dataType, String dataTypeName,
+            int dataPrecision) {
+        return String.format("type of ID: %d (%s) precision %d (-> %s), type of DATA: %d (%s) precision %d", idType, idTypeName,
+                idPrecision, isBinaryType(idType) ? "binary" : "character", dataType, dataTypeName, dataPrecision);
+    }
+
+    private void createTableFor(Connection con, Collection<? extends Document> col, List<String> tablesCreated,
+            List<String> tablesPresent, StringBuilder diagnostics) throws SQLException {
         String dbname = this.db.toString();
         if (con.getMetaData().getURL() != null) {
             dbname += " (" + con.getMetaData().getURL() + ")";
@@ -932,14 +930,17 @@ public class RDBDocumentStore implements
         ResultSet checkResultSet = null;
         Statement creatStatement = null;
         try {
-            checkStatement = con.prepareStatement("select DATA from " + tableName + " where ID = ?");
+            checkStatement = con.prepareStatement("select ID, DATA from " + tableName + " where ID = ?");
             checkStatement.setString(1, "0:/");
             checkResultSet = checkStatement.executeQuery();
 
             if (col.equals(Collection.NODES)) {
                 // try to discover size of DATA column
                 ResultSetMetaData met = checkResultSet.getMetaData();
-                this.dataLimitInOctets = met.getPrecision(1);
+                this.isIdBinary = isBinaryType(met.getColumnType(1));
+                this.dataLimitInOctets = met.getPrecision(2);
+                diagnostics.append(dumpTableMeta(met.getColumnType(1), met.getColumnTypeName(1), met.getPrecision(1),
+                        met.getColumnType(2), met.getColumnTypeName(2), met.getPrecision(2)));
             }
             tablesPresent.add(tableName);
         } catch (SQLException ex) {
@@ -962,11 +963,14 @@ public class RDBDocumentStore implements
                 tablesCreated.add(tableName);
 
                 if (col.equals(Collection.NODES)) {
-                    PreparedStatement pstmt = con.prepareStatement("select DATA from " + tableName + " where ID = ?");
+                    PreparedStatement pstmt = con.prepareStatement("select ID, DATA from " + tableName + " where ID = ?");
                     pstmt.setString(1, "0:/");
                     ResultSet rs = pstmt.executeQuery();
                     ResultSetMetaData met = rs.getMetaData();
-                    this.dataLimitInOctets = met.getPrecision(1);
+                    this.isIdBinary = isBinaryType(met.getColumnType(1));
+                    this.dataLimitInOctets = met.getPrecision(2);
+                    diagnostics.append(dumpTableMeta(met.getColumnType(1), met.getColumnTypeName(1), met.getPrecision(1),
+                            met.getColumnType(2), met.getColumnTypeName(2), met.getPrecision(2)));
                 }
             }
             catch (SQLException ex2) {
@@ -1553,7 +1557,7 @@ public class RDBDocumentStore implements
     }
 
     private void setIdInStatement(PreparedStatement stmt, int idx, String id) throws SQLException {
-        if (db.isPrimaryColumnByteEncoded()) {
+        if (this.isIdBinary) {
             try {
                 stmt.setBytes(idx, id.getBytes("UTF-8"));
             } catch (UnsupportedEncodingException ex) {
@@ -1566,19 +1570,16 @@ public class RDBDocumentStore implements
     }
 
     private String getIdFromRS(ResultSet rs, int idx) throws SQLException {
-        String id;
-        if (db.isPrimaryColumnByteEncoded()) {
+        if (this.isIdBinary) {
             try {
-                id = new String(rs.getBytes(idx), "UTF-8");
-
+                return new String(rs.getBytes(idx), "UTF-8");
             } catch (UnsupportedEncodingException ex) {
                 LOG.error("UTF-8 not supported??", ex);
                 throw new DocumentStoreException(ex);
             }
         } else {
-            id = rs.getString(idx);
+            return rs.getString(idx);
         }
-        return id;
     }
 
     @CheckForNull