/** * Copyright 2016 Hortonworks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **/ package com.hortonworks.registries.storage.impl.jdbc.provider.mysql.query; import com.hortonworks.registries.storage.exception.NonIncrementalColumnException; import com.hortonworks.registries.storage.impl.jdbc.config.ExecutionConfig; import com.hortonworks.registries.storage.impl.jdbc.provider.sql.query.MetadataHelper; import com.hortonworks.registries.storage.impl.jdbc.provider.sql.statement.PreparedStatementBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * */ public class MySqlQueryUtils { private static final Logger log = LoggerFactory.getLogger(MySqlQueryUtils.class); private MySqlQueryUtils() { } public static long nextIdMySql(Connection connection, String namespace, int queryTimeoutSecs) throws SQLException { if (!MetadataHelper.isAutoIncrement(connection, namespace, queryTimeoutSecs)) { throw new NonIncrementalColumnException(); } final ResultSet resultSet = getResultSet(connection, queryTimeoutSecs, buildNextIdMySql(connection, namespace)); resultSet.next(); final long nextId = resultSet.getLong("AUTO_INCREMENT"); log.debug("Next id for auto increment table [{}] = {}", namespace, nextId); return nextId; } private static ResultSet getResultSet(Connection connection, int queryTimeoutSecs, String sql) throws SQLException { final MySqlQuery sqlBuilder = new MySqlQuery(sql); return PreparedStatementBuilder.of(connection, new ExecutionConfig(queryTimeoutSecs), sqlBuilder).getPreparedStatement(sqlBuilder).executeQuery(); } private static String buildNextIdMySql(Connection connection, String namespace) throws SQLException { final String database = connection.getCatalog(); final String sql = "SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '" + namespace + "' AND TABLE_SCHEMA = '" + database + "'"; log.debug("nextIdMySql() SQL query: {}", sql); return sql; } public static long nextIdH2(Connection connection, String namespace, int queryTimeoutSecs) throws SQLException { if (!MetadataHelper.isAutoIncrement(connection, namespace, queryTimeoutSecs)) { throw new NonIncrementalColumnException(); } final ResultSet resultSet = getResultSet(connection, queryTimeoutSecs, buildNextIdH2(getH2SequenceName(connection, namespace, queryTimeoutSecs))); resultSet.next(); final long nextId = resultSet.getLong("CURRENT_VALUE"); log.debug("Next id for auto increment table [{}] = {}", namespace, nextId); return nextId; } private static String buildNextIdH2(String sequenceName) throws SQLException { final String sql = "SELECT CURRENT_VALUE FROM INFORMATION_SCHEMA.SEQUENCES WHERE SEQUENCE_NAME = '" + sequenceName + "'"; log.debug("nextIdH2() SQL query: {}", sql); return sql; } private static String getH2SequenceName(Connection connection, String namespace, int queryTimeoutSecs) throws SQLException { final ResultSet resultSet = getResultSet(connection, queryTimeoutSecs, getH2InfoSchemaSql(namespace)); resultSet.next(); String sql = resultSet.getString("SQL"); Pattern p = Pattern.compile("(?i)(SYSTEM_SEQUENCE.*?)([)])"); Matcher m = p.matcher(sql); String seqName = null; if (m.find()) { seqName = m.group(1); log.debug("SQL: {} => \n\t", sql, seqName); } if (seqName == null) { throw new RuntimeException("No sequence name found for namespace [" + namespace + "]"); } return seqName; } private static String getH2InfoSchemaSql(String namespace) { return "SELECT `SQL` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '" + namespace + "'"; } }