Author: reschke
Date: Wed Sep 16 12:50:49 2015
New Revision: 1703395
URL: http://svn.apache.org/r1703395
Log:
OAK-3394: RDBDocumentStore startup: log more DDL information (incl. index
information)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBJDBCTools.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=1703395&r1=1703394&r2=1703395&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
Wed Sep 16 12:50:49 2015
@@ -38,9 +38,11 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Lock;
@@ -602,12 +604,99 @@ public class RDBDocumentStore implements
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, int bdataType, String bdataTypeName, int
bdataPrecision) {
- return String
- .format("type of ID: %d (%s) precision %d (-> %s), type of
DATA: %d (%s) precision %d, type of BDATA: %d (%s) precision %d",
- idType, idTypeName, idPrecision, isBinaryType(idType)
? "binary" : "character", dataType, dataTypeName,
- dataPrecision, bdataType, bdataTypeName,
bdataPrecision);
+ private void obtainFlagsFromResultSetMeta(ResultSetMetaData met) throws
SQLException {
+ for (int i = 1; i <= met.getColumnCount(); i++) {
+ String lcName = met.getColumnName(i).toLowerCase(Locale.ENGLISH);
+ if ("id".equals(lcName)) {
+ this.isIdBinary = isBinaryType(met.getColumnType(i));
+ }
+ if ("data".equals(lcName)) {
+ this.dataLimitInOctets = met.getPrecision(i);
+ }
+ }
+ }
+
+ private String asQualifiedDbName(String one, String two) {
+ if (one == null && two == null) {
+ return null;
+ }
+ else {
+ one = one == null ? "" : one.trim();
+ two = two == null ? "" : two.trim();
+ return one.isEmpty() ? two : one + "." + two;
+ }
+ }
+
+ private String dumpIndexData(DatabaseMetaData met, ResultSetMetaData rmet,
String tableName) {
+
+ ResultSet rs = null;
+ try {
+ // if the result set metadata provides a table name, use that (the
other one
+ // might be inaccurate due to case insensitivity issues
+ String rmetTableName = rmet.getTableName(1);
+ if (rmetTableName != null && !rmetTableName.trim().isEmpty()) {
+ tableName = rmetTableName.trim();
+ }
+
+ String rmetSchemaName = rmet.getSchemaName(1);
+ rmetSchemaName = rmetSchemaName == null ? "" :
rmetSchemaName.trim();
+
+ Map<String, Map<String, Object>> indices = new TreeMap<String,
Map<String, Object>>();
+ StringBuilder sb = new StringBuilder();
+ rs = met.getIndexInfo(null, null, tableName, false, true);
+ while (rs.next()) {
+ String name = asQualifiedDbName(rs.getString(5),
rs.getString(6));
+ if (name != null) {
+ Map<String, Object> info = indices.get(name);
+ if (info == null) {
+ info = new HashMap<String, Object>();
+ indices.put(name, info);
+ info.put("fields", new TreeMap<Integer, String>());
+ }
+ info.put("nonunique", rs.getBoolean(4));
+ info.put("type", rs.getInt(7));
+ String inSchema = rs.getString(2);
+ inSchema = inSchema == null ? "" : inSchema.trim();
+ // skip indices on tables in other schemas in case we have
that information
+ if (rmetSchemaName.isEmpty() || inSchema.isEmpty() ||
rmetSchemaName.equals(inSchema)) {
+ String tname = asQualifiedDbName(inSchema,
rs.getString(3));
+ info.put("tname", tname);
+ String cname = rs.getString(9);
+ if (cname != null) {
+ String order = "A".equals(rs.getString(10)) ? "
ASC" : ("D".equals(rs.getString(10)) ? " DESC" : "");
+ ((Map<Integer, String>)
info.get("fields")).put(rs.getInt(8), cname + order);
+ }
+ }
+ }
+ }
+ for (Entry<String, Map<String, Object>> index :
indices.entrySet()) {
+ boolean nonUnique = ((Boolean)
index.getValue().get("nonunique"));
+ Map<Integer, String> fields = (Map<Integer, String>)
index.getValue().get("fields");
+ if (!fields.isEmpty()) {
+ if (sb.length() != 0) {
+ sb.append(", ");
+ }
+ sb.append(String.format("%sindex %s on %s (", nonUnique ?
"" : "unique ", index.getKey(),
+ index.getValue().get("tname")));
+ String delim = "";
+ for (String field : fields.values()) {
+ sb.append(delim);
+ delim = ", ";
+ sb.append(field);
+ }
+ sb.append(")");
+ }
+ }
+ if (sb.length() != 0) {
+ sb.insert(0, "/* ").append(" */");
+ }
+ return sb.toString();
+ } catch (SQLException ex) {
+ // well it was best-effort
+ return "";
+ } finally {
+ this.ch.closeResultSet(rs);
+ }
}
private void createTableFor(Connection con, Collection<? extends Document>
col, List<String> tablesCreated,
@@ -622,18 +711,20 @@ public class RDBDocumentStore implements
ResultSet checkResultSet = null;
Statement creatStatement = null;
try {
- checkStatement = con.prepareStatement("select ID, DATA, BDATA from
" + tableName + " where ID = ?");
+ checkStatement = con.prepareStatement("select * 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.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), met.getColumnType(3),
- met.getColumnTypeName(3), met.getPrecision(3)));
+ obtainFlagsFromResultSetMeta(met);
+ String tableInfo = RDBJDBCTools.dumpResultSetMeta(met);
+ diagnostics.append(tableInfo);
+ String indexInfo = dumpIndexData(con.getMetaData(), met,
tableName);
+ if (!indexInfo.isEmpty()) {
+ diagnostics.append(" ").append(indexInfo);
+ }
}
tablesPresent.add(tableName);
} catch (SQLException ex) {
@@ -656,15 +747,17 @@ public class RDBDocumentStore implements
tablesCreated.add(tableName);
if (col.equals(Collection.NODES)) {
- PreparedStatement pstmt = con.prepareStatement("select ID,
DATA, BDATA from " + tableName + " where ID = ?");
+ PreparedStatement pstmt = con.prepareStatement("select *
from " + tableName + " where ID = ?");
pstmt.setString(1, "0:/");
ResultSet rs = pstmt.executeQuery();
ResultSetMetaData met = rs.getMetaData();
- 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), met.getColumnType(3),
- met.getColumnTypeName(3), met.getPrecision(3)));
+ obtainFlagsFromResultSetMeta(met);
+ String tableInfo = RDBJDBCTools.dumpResultSetMeta(met);
+ diagnostics.append(tableInfo);
+ String indexInfo = dumpIndexData(con.getMetaData(), met,
tableName);
+ if (!indexInfo.isEmpty()) {
+ diagnostics.append(" ").append(indexInfo);
+ }
}
}
catch (SQLException ex2) {
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBJDBCTools.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBJDBCTools.java?rev=1703395&r1=1703394&r2=1703395&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBJDBCTools.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBJDBCTools.java
Wed Sep 16 12:50:49 2015
@@ -18,10 +18,14 @@ package org.apache.jackrabbit.oak.plugin
import java.sql.Connection;
import java.sql.DatabaseMetaData;
+import java.sql.ResultSetMetaData;
import java.sql.SQLException;
+import java.sql.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
import javax.annotation.Nonnull;
@@ -123,6 +127,36 @@ public class RDBJDBCTools {
return String.format("%s (%d)", name, isolationLevel);
}
+ private static String dumpColumnMeta(String columnName, int type, String
typeName, int precision) {
+ boolean skipPrecision = precision == 0 || (type == Types.SMALLINT &&
precision == 5)
+ || (type == Types.BIGINT && precision == 19);
+ return skipPrecision ? String.format("%s %s", columnName, typeName)
+ : String.format("%s %s(%d)", columnName, typeName, precision);
+ }
+
+ /**
+ * Return approximated string representation of table DDL.
+ */
+ protected static String dumpResultSetMeta(ResultSetMetaData met) {
+ try {
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("%s.%s: ", met.getSchemaName(1).trim(),
met.getTableName(1).trim()));
+ Map<String, Integer> types = new TreeMap<String, Integer>();
+ for (int i = 1; i <= met.getColumnCount(); i++) {
+ if (i > 1) {
+ sb.append(", ");
+ }
+ sb.append(
+ dumpColumnMeta(met.getColumnName(i),
met.getColumnType(i), met.getColumnTypeName(i), met.getPrecision(i)));
+ types.put(met.getColumnTypeName(i), met.getColumnType(i));
+ }
+ sb.append(" /* " + types.toString() + " */");
+ return sb.toString();
+ } catch (SQLException ex) {
+ return "Column metadata unavailable: " + ex.getMessage();
+ }
+ }
+
/**
* Return a string containing additional messages from chained exceptions.
*/