in oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java [1284:1416]
private void createTableFor(Connection con, Collection<? extends Document> col, RDBTableMetaData tmd, List<String> tablesCreated,
List<String> tablesPresent, int initialSchema, int upgradeToSchema) throws SQLException {
String dbname = this.dbInfo.toString();
if (con.getMetaData().getURL() != null) {
dbname += " (" + con.getMetaData().getURL() + ")";
}
String tableName = tmd.getName();
Statement checkStatement = null;
ResultSet checkResultSet = null;
Statement creatStatement = null;
try {
// avoid PreparedStatement due to weird DB2 behavior (OAK-6237)
checkStatement = con.createStatement();
checkResultSet = checkStatement.executeQuery("select * from " + tableName + " where ID = '0'");
// try to discover size of DATA column and binary-ness of ID
ResultSetMetaData met = checkResultSet.getMetaData();
obtainFlagsFromResultSetMeta(met, tmd);
// check that all required columns are present
Set<String> requiredColumns = new HashSet<String>(REQUIREDCOLUMNS);
Set<String> unknownColumns = new HashSet<String>();
boolean hasVersionColumn = false;
boolean hasSDTypeColumn = false;
for (int i = 1; i <= met.getColumnCount(); i++) {
String cname = met.getColumnName(i).toLowerCase(Locale.ENGLISH);
if (!requiredColumns.remove(cname)) {
if (!OPTIONALCOLUMNS.contains(cname)) {
unknownColumns.add(cname);
}
}
if (cname.equals("version")) {
hasVersionColumn = true;
}
if (cname.equals("sdtype")) {
hasSDTypeColumn = true;
}
}
if (!requiredColumns.isEmpty()) {
String message = String.format("Table %s: the following required columns are missing: %s", tableName,
requiredColumns.toString());
LOG.error(message);
throw new DocumentStoreException(message);
}
if (!unknownColumns.isEmpty()) {
String message = String.format("Table %s: the following columns are unknown and will not be maintained: %s",
tableName, unknownColumns.toString());
LOG.info(message);
}
String tableInfo = RDBJDBCTools.dumpResultSetMeta(met);
tmd.setSchemaInfo(tableInfo);
Set<String> indexOn = new HashSet<String>();
String indexInfo = dumpIndexData(con.getMetaData(), met, tableName, indexOn);
tmd.setIndexInfo(indexInfo);
closeResultSet(checkResultSet);
boolean dbWasChanged = false;
if (this.readOnly) {
LOG.debug("Skipping table update code because store is initialized in readOnly mode");
}
else {
if (!hasVersionColumn && upgradeToSchema >= 1) {
dbWasChanged |= upgradeTable(con, tableName, 1);
}
if (!hasSDTypeColumn && upgradeToSchema >= 2) {
dbWasChanged |= upgradeTable(con, tableName, 2);
}
if (!indexOn.contains("MODIFIED") && col == Collection.NODES) {
dbWasChanged |= addModifiedIndex(con, tableName);
}
}
tablesPresent.add(tableName);
if (dbWasChanged) {
getTableMetaData(con, col, tmd);
}
} catch (SQLException ex) {
// table does not appear to exist
con.rollback();
LOG.debug("trying to read from '" + tableName + "'", ex);
if (this.readOnly) {
throw new SQLException("Would like to create table '" + tableName
+ "', but RDBDocumentStore has been initialized in 'readonly' mode");
}
try {
creatStatement = con.createStatement();
creatStatement.execute(this.dbInfo.getTableCreationStatement(tableName, initialSchema));
creatStatement.close();
for (String ic : this.dbInfo.getIndexCreationStatements(tableName, initialSchema)) {
creatStatement = con.createStatement();
creatStatement.execute(ic);
creatStatement.close();
}
con.commit();
if (initialSchema < 1 && upgradeToSchema >= 1) {
upgradeTable(con, tableName, 1);
}
if (initialSchema < 2 && upgradeToSchema >= 2) {
upgradeTable(con, tableName, 2);
}
tablesCreated.add(tableName);
getTableMetaData(con, col, tmd);
}
catch (SQLException ex2) {
LOG.error("Failed to create table '" + tableName + "' in '" + dbname + "'", ex2);
throw ex2;
}
}
finally {
closeResultSet(checkResultSet);
closeStatement(checkStatement);
closeStatement(creatStatement);
}
}