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