package org.infinispan.persistence.jdbc.table.management; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Objects; import org.infinispan.persistence.jdbc.JdbcUtil; import org.infinispan.persistence.jdbc.configuration.TableManipulationConfiguration; import org.infinispan.persistence.jdbc.connectionfactory.ConnectionFactory; import org.infinispan.persistence.jdbc.logging.Log; import org.infinispan.persistence.spi.PersistenceException; import org.infinispan.util.logging.LogFactory; /** * @author Ryan Emerson */ class OracleTableManager extends AbstractTableManager { private static final Log LOG = LogFactory.getLog(OracleTableManager.class, Log.class); private static final int MAX_INDEX_IDENTIFIER_SIZE = 30; private static final String INDEX_PREFIX = "IDX"; OracleTableManager(ConnectionFactory connectionFactory, TableManipulationConfiguration config, DbMetaData metaData) { super(connectionFactory, config, metaData, LOG); } @Override public boolean tableExists(Connection connection, TableName tableName) throws PersistenceException { Objects.requireNonNull(tableName, "table name is mandatory"); ResultSet rs = null; try { DatabaseMetaData metaData = connection.getMetaData(); String schemaPattern = tableName.getSchema() == null ? metaData.getUserName() : tableName.getSchema(); rs = metaData.getTables(null, schemaPattern, tableName.getName(), new String[]{"TABLE"}); return rs.next(); } catch (SQLException e) { if (LOG.isTraceEnabled()) LOG.tracef(e, "SQLException occurs while checking the table %s", tableName); return false; } finally { JdbcUtil.safeClose(rs); } } @Override protected boolean timestampIndexExists(Connection conn) throws PersistenceException { ResultSet rs = null; try { DatabaseMetaData meta = conn.getMetaData(); rs = meta.getIndexInfo(null, null, getTableName().toString(), false, false); String indexName = getIndexName(false); while (rs.next()) { if (indexName.equalsIgnoreCase(rs.getString("INDEX_NAME"))) { return true; } } } catch (SQLException e) { throw new PersistenceException(e); } finally { JdbcUtil.safeClose(rs); } return false; } @Override public String getIndexName(boolean withIdentifier) { int maxNameSize = MAX_INDEX_IDENTIFIER_SIZE - INDEX_PREFIX.length() - 1; if (withIdentifier) { maxNameSize -= 2; } String tableName = getTableName().toString().replace(identifierQuoteString, ""); String truncatedName = tableName.length() > maxNameSize ? tableName.substring(0, maxNameSize) : tableName; String indexName = INDEX_PREFIX + "_" + truncatedName; if (withIdentifier) { return identifierQuoteString + indexName + identifierQuoteString; } return indexName; } @Override public String getUpsertRowSql() { if (upsertRowSql == null) { upsertRowSql = String.format("MERGE INTO %1$s t " + "USING (SELECT ? %2$s, ? %3$s, ? %4$s from dual) tmp ON (t.%4$s = tmp.%4$s) " + "WHEN MATCHED THEN UPDATE SET t.%2$s = tmp.%2$s, t.%3$s = tmp.%3$s " + "WHEN NOT MATCHED THEN INSERT VALUES (tmp.%4$s, tmp.%2$s, tmp.%3$s)", this.getTableName(), config.dataColumnName(), config.timestampColumnName(), config.idColumnName()); } return upsertRowSql; } }