/*
* Copyright 2000-2013 Enonic AS
* http://www.enonic.com/license
*/
package com.enonic.cms.upgrade.service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import com.enonic.cms.framework.jdbc.dialect.Dialect;
import com.enonic.cms.store.support.ConnectionFactory;
public final class SqlOperationHelper
{
private final static String MODEL_VERSION_TABLE = "tModelVersion";
private final static String SELECT_MODEL_VERSION_SQL = "SELECT mve_lversion FROM tModelVersion WHERE mve_skey = 'model'";
private final static String UPDATE_MODEL_VERSION_SQL = "UPDATE tModelVersion SET mve_lversion = ? WHERE mve_skey = 'model'";
private final static String SELECT_KEY_SQL = "SELECT key_lLastKey FROM tKey WHERE lower(key_sTableName) = ?";
private final static String UPDATE_KEY_SQL = "UPDATE tKey SET key_lLastKey = key_lLastKey + 1 WHERE lower(key_sTableName) = ?";
private final Dialect dialect;
private final ConnectionFactory connectionFactory;
private final TransactionTemplate transactionTemplate;
public SqlOperationHelper( Dialect dialect, ConnectionFactory connectionFactory, TransactionTemplate transactionTemplate )
{
this.dialect = dialect;
this.connectionFactory = connectionFactory;
this.transactionTemplate = transactionTemplate;
}
public Dialect getDialect()
{
return this.dialect;
}
public Connection getConnection()
throws SQLException
{
return this.connectionFactory.getConnection( true );
}
public void close( Connection conn )
{
}
public int generateNextKey( String tableName )
throws Exception
{
Connection conn = this.connectionFactory.getConnection( false );
try
{
return generateNextKey( conn, tableName );
}
finally
{
conn.close();
}
}
private int generateNextKey( Connection conn, String tableName )
throws Exception
{
incrementKeyValue( conn, tableName );
return selectKeyValue( conn, tableName );
}
private void incrementKeyValue( Connection conn, String tableName )
throws Exception
{
PreparedStatement stmt = conn.prepareStatement( UPDATE_KEY_SQL );
try
{
stmt.setString( 1, tableName.toLowerCase() );
stmt.executeUpdate();
}
finally
{
close( stmt );
}
}
private int selectKeyValue( Connection conn, String tableName )
throws Exception
{
PreparedStatement stmt = conn.prepareStatement( SELECT_KEY_SQL );
ResultSet result;
try
{
stmt.setString( 1, tableName.toLowerCase() );
result = stmt.executeQuery();
if ( result.next() )
{
return result.getInt( 1 );
}
else
{
throw new SQLException( "Failed to generate key value for table: " + tableName );
}
}
finally
{
close( stmt );
}
}
public int getModelNumber()
throws Exception
{
Connection conn = getConnection();
try
{
return getModelNumber( conn );
}
finally
{
close( conn );
}
}
private int getModelNumber( Connection conn )
throws Exception
{
if ( hasTable( conn, MODEL_VERSION_TABLE ) )
{
return selectModelNumber( conn );
}
else
{
return -1;
}
}
public void updateModelNumber( int number )
throws Exception
{
Connection conn = getConnection();
try
{
updateModelNumber( conn, number );
}
finally
{
close( conn );
}
}
private int selectModelNumber( Connection conn )
throws Exception
{
Statement stmt = conn.createStatement();
ResultSet result = null;
try
{
result = stmt.executeQuery( SELECT_MODEL_VERSION_SQL );
if ( result.next() )
{
return result.getInt( 1 );
}
else
{
return 0;
}
}
finally
{
close( result );
close( stmt );
}
}
private void updateModelNumber( Connection conn, int number )
throws Exception
{
PreparedStatement stmt = conn.prepareStatement( UPDATE_MODEL_VERSION_SQL );
try
{
stmt.setInt( 1, number );
stmt.executeUpdate();
}
finally
{
close( stmt );
}
}
public boolean hasTable( Connection conn, String tableName )
{
Statement stmt = null;
try
{
stmt = conn.createStatement();
close( stmt.executeQuery( "SELECT * FROM " + tableName ) );
return true;
}
catch ( SQLException e )
{
try
{
conn.rollback();
}
catch ( Exception e2 )
{
// Do nothing
}
return false;
}
finally
{
close( stmt );
}
}
public boolean columnExist( Connection conn, String tableName, String columnName )
throws Exception
{
Statement stmt = null;
try
{
stmt = conn.createStatement();
close( stmt.executeQuery( "SELECT " + columnName + " FROM " + tableName ) );
return true;
}
catch ( SQLException e )
{
try
{
conn.rollback();
}
catch ( Exception e2 )
{
// Do nothing
}
return false;
}
finally
{
close( stmt );
}
}
public void close( Statement stmt )
{
JdbcUtils.closeStatement( stmt );
}
public void close( ResultSet result )
{
JdbcUtils.closeResultSet( result );
}
public Object execute( TransactionCallback callback )
{
return this.transactionTemplate.execute( callback );
}
public int getTransactionTimeout()
{
return transactionTemplate.getTimeout();
}
public void setTransactionTimeout( final int timeout )
{
transactionTemplate.setTimeout( timeout );
}
}