HHH-5373 - Better account for SQLWarnings in temp table creation
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19931 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
21b68ef40f
commit
e197d208b6
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,12 +20,12 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.hql.ast.exec;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
|
@ -43,12 +43,14 @@ import org.hibernate.persister.entity.Queryable;
|
|||
import org.hibernate.sql.InsertSelect;
|
||||
import org.hibernate.sql.Select;
|
||||
import org.hibernate.sql.SelectFragment;
|
||||
import org.hibernate.util.JDBCExceptionReporter;
|
||||
import org.hibernate.util.StringHelper;
|
||||
|
||||
import antlr.RecognitionException;
|
||||
import antlr.collections.AST;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Implementation of AbstractStatementExecutor.
|
||||
|
@ -56,6 +58,7 @@ import org.slf4j.Logger;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public abstract class AbstractStatementExecutor implements StatementExecutor {
|
||||
private static final Logger LOG = LoggerFactory.getLogger( AbstractStatementExecutor.class );
|
||||
|
||||
private final Logger log;
|
||||
private final HqlSqlWalker walker;
|
||||
|
@ -141,24 +144,24 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
|
|||
// simply allow the failure to be eaten and the subsequent insert-selects/deletes should fail
|
||||
IsolatedWork work = new IsolatedWork() {
|
||||
public void doWork(Connection connection) throws HibernateException {
|
||||
Statement stmnt = null;
|
||||
try {
|
||||
stmnt = connection.createStatement();
|
||||
stmnt.executeUpdate( persister.getTemporaryIdTableDDL() );
|
||||
}
|
||||
catch( Throwable t ) {
|
||||
log.debug( "unable to create temporary id table [" + t.getMessage() + "]" );
|
||||
}
|
||||
finally {
|
||||
if ( stmnt != null ) {
|
||||
Statement statement = connection.createStatement();
|
||||
try {
|
||||
statement.executeUpdate( persister.getTemporaryIdTableDDL() );
|
||||
JDBCExceptionReporter.handleAndClearWarnings( statement, CREATION_WARNING_HANDLER );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
stmnt.close();
|
||||
statement.close();
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception e ) {
|
||||
log.debug( "unable to create temporary id table [" + e.getMessage() + "]" );
|
||||
}
|
||||
}
|
||||
};
|
||||
if ( shouldIsolateTemporaryTableDDL() ) {
|
||||
|
@ -175,30 +178,46 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
private static JDBCExceptionReporter.WarningHandler CREATION_WARNING_HANDLER = new JDBCExceptionReporter.WarningHandlerLoggingSupport() {
|
||||
public boolean doProcess() {
|
||||
return LOG.isDebugEnabled();
|
||||
}
|
||||
|
||||
public void prepare(SQLWarning warning) {
|
||||
LOG.debug( "Warnings creating temp table", warning );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logWarning(String description, String message) {
|
||||
LOG.debug( description );
|
||||
LOG.debug( message );
|
||||
}
|
||||
};
|
||||
|
||||
protected void dropTemporaryTableIfNecessary(final Queryable persister, final SessionImplementor session) {
|
||||
if ( getFactory().getDialect().dropTemporaryTableAfterUse() ) {
|
||||
IsolatedWork work = new IsolatedWork() {
|
||||
public void doWork(Connection connection) throws HibernateException {
|
||||
Statement stmnt = null;
|
||||
final String command = session.getFactory().getSettings().getDialect().getDropTemporaryTableString()
|
||||
+ ' ' + persister.getTemporaryIdTableName();
|
||||
try {
|
||||
final String command = session.getFactory().getSettings().getDialect().getDropTemporaryTableString()
|
||||
+ " " + persister.getTemporaryIdTableName();
|
||||
stmnt = connection.createStatement();
|
||||
stmnt.executeUpdate( command );
|
||||
}
|
||||
catch( Throwable t ) {
|
||||
log.warn( "unable to drop temporary id table after use [" + t.getMessage() + "]" );
|
||||
}
|
||||
finally {
|
||||
if ( stmnt != null ) {
|
||||
Statement statement = connection.createStatement();
|
||||
try {
|
||||
statement = connection.createStatement();
|
||||
statement.executeUpdate( command );
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
stmnt.close();
|
||||
statement.close();
|
||||
}
|
||||
catch( Throwable ignore ) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception e ) {
|
||||
log.warn( "unable to drop temporary id table after use [" + e.getMessage() + "]" );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -249,6 +268,7 @@ public abstract class AbstractStatementExecutor implements StatementExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "UnnecessaryUnboxing" })
|
||||
protected boolean shouldIsolateTemporaryTableDDL() {
|
||||
Boolean dialectVote = getFactory().getDialect().performTemporaryTableDDLInIsolation();
|
||||
if ( dialectVote != null ) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
|
@ -20,64 +20,197 @@
|
|||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.util;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public final class JDBCExceptionReporter {
|
||||
|
||||
public static final Logger log = LoggerFactory.getLogger(JDBCExceptionReporter.class);
|
||||
public static final String DEFAULT_EXCEPTION_MSG = "SQL Exception";
|
||||
public static final String DEFAULT_WARNING_MSG = "SQL Warning";
|
||||
|
||||
private JDBCExceptionReporter() {}
|
||||
|
||||
|
||||
/**
|
||||
* Standard (legacy) behavior for logging warnings associated with a JDBC {@link Connection} and clearing them.
|
||||
* <p/>
|
||||
* Calls {@link #handleAndClearWarnings(Connection, WarningHandler)} using {@link #STANDARD_WARNING_HANDLER}
|
||||
*
|
||||
* @param connection The JDBC connection potentially containing warnings
|
||||
*/
|
||||
public static void logAndClearWarnings(Connection connection) {
|
||||
if ( log.isWarnEnabled() ) {
|
||||
try {
|
||||
logWarnings( connection.getWarnings() );
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
//workaround for WebLogic
|
||||
log.debug("could not log warnings", sqle);
|
||||
}
|
||||
handleAndClearWarnings( connection, STANDARD_WARNING_HANDLER );
|
||||
}
|
||||
|
||||
/**
|
||||
* General purpose handling of warnings associated with a JDBC {@link Connection}.
|
||||
*
|
||||
* @param connection The JDBC connection potentially containing warnings
|
||||
* @param handler The handler for each individual warning in the stack.
|
||||
*
|
||||
* @see #walkWarnings
|
||||
*/
|
||||
@SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
|
||||
public static void handleAndClearWarnings(Connection connection, WarningHandler handler) {
|
||||
try {
|
||||
walkWarnings( connection.getWarnings(), handler );
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
//workaround for WebLogic
|
||||
log.debug( "could not log warnings", sqle );
|
||||
}
|
||||
try {
|
||||
//Sybase fail if we don't do that, sigh...
|
||||
connection.clearWarnings();
|
||||
}
|
||||
catch (SQLException sqle) {
|
||||
log.debug("could not clear warnings", sqle);
|
||||
catch ( SQLException sqle ) {
|
||||
log.debug( "could not clear warnings", sqle );
|
||||
}
|
||||
}
|
||||
|
||||
public static void logWarnings(SQLWarning warning) {
|
||||
logWarnings(warning, null);
|
||||
/**
|
||||
* General purpose handling of warnings associated with a JDBC {@link Statement}.
|
||||
*
|
||||
* @param statement The JDBC statement potentially containing warnings
|
||||
* @param handler The handler for each individual warning in the stack.
|
||||
*
|
||||
* @see #walkWarnings
|
||||
*/
|
||||
@SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
|
||||
public static void handleAndClearWarnings(Statement statement, WarningHandler handler) {
|
||||
try {
|
||||
walkWarnings( statement.getWarnings(), handler );
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
//workaround for WebLogic
|
||||
log.debug( "could not log warnings", sqle );
|
||||
}
|
||||
try {
|
||||
//Sybase fail if we don't do that, sigh...
|
||||
statement.clearWarnings();
|
||||
}
|
||||
catch ( SQLException sqle ) {
|
||||
log.debug( "could not clear warnings", sqle );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given warning and all of its nested warnings, preceded with the {@link #DEFAULT_WARNING_MSG default message}
|
||||
*
|
||||
* @param warning The warning to log
|
||||
*
|
||||
* @deprecated Use {@link #walkWarnings} instead
|
||||
*/
|
||||
@Deprecated()
|
||||
@SuppressWarnings({ "UnusedDeclaration" })
|
||||
public static void logWarnings(SQLWarning warning) {
|
||||
walkWarnings( warning, STANDARD_WARNING_HANDLER );
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the given warning and all of its nested warnings, preceded with the given message
|
||||
*
|
||||
* @param warning The warning to log
|
||||
* @param message The prologue message
|
||||
*
|
||||
* @deprecated Use {@link #walkWarnings} instead
|
||||
*/
|
||||
@Deprecated()
|
||||
@SuppressWarnings({ "UnusedDeclaration" })
|
||||
public static void logWarnings(SQLWarning warning, String message) {
|
||||
if ( log.isWarnEnabled() ) {
|
||||
if ( log.isDebugEnabled() && warning != null ) {
|
||||
message = StringHelper.isNotEmpty(message) ? message : DEFAULT_WARNING_MSG;
|
||||
log.debug( message, warning );
|
||||
}
|
||||
while (warning != null) {
|
||||
StringBuffer buf = new StringBuffer(30)
|
||||
.append( "SQL Warning: ")
|
||||
.append( warning.getErrorCode() )
|
||||
.append( ", SQLState: ")
|
||||
.append( warning.getSQLState() );
|
||||
log.warn( buf.toString() );
|
||||
log.warn( warning.getMessage() );
|
||||
warning = warning.getNextWarning();
|
||||
}
|
||||
final WarningHandler handler = StringHelper.isNotEmpty(message)
|
||||
? new StandardWarningHandler( message )
|
||||
: STANDARD_WARNING_HANDLER;
|
||||
walkWarnings( warning, handler );
|
||||
}
|
||||
|
||||
/**
|
||||
* Contract for handling {@link SQLWarning warnings}
|
||||
*/
|
||||
public static interface WarningHandler {
|
||||
/**
|
||||
* Should processing be done? Allows short-circuiting if not.
|
||||
*
|
||||
* @return True to process warnings, false otherwise.
|
||||
*/
|
||||
public boolean doProcess();
|
||||
|
||||
/**
|
||||
* Prepare for processing of a {@link SQLWarning warning} stack.
|
||||
* <p/>
|
||||
* Note that the warning here is also the first passed to {@link #handleWarning}
|
||||
*
|
||||
* @param warning The first warning in the stack.
|
||||
*/
|
||||
public void prepare(SQLWarning warning);
|
||||
|
||||
/**
|
||||
* Handle an individual warning in the stack.
|
||||
*
|
||||
* @param warning The warning to handle.
|
||||
*/
|
||||
public void handleWarning(SQLWarning warning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic support for {@link WarningHandler} implementations which log
|
||||
*/
|
||||
public static abstract class WarningHandlerLoggingSupport implements WarningHandler {
|
||||
public final void handleWarning(SQLWarning warning) {
|
||||
StringBuffer buf = new StringBuffer(30)
|
||||
.append( "SQL Warning Code: ").append( warning.getErrorCode() )
|
||||
.append( ", SQLState: ").append( warning.getSQLState() );
|
||||
logWarning( buf.toString(), warning.getMessage() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegate to log common details of a {@link SQLWarning warning}
|
||||
*
|
||||
* @param description A description of the warning
|
||||
* @param message The warning message
|
||||
*/
|
||||
protected abstract void logWarning(String description, String message);
|
||||
}
|
||||
|
||||
public static class StandardWarningHandler extends WarningHandlerLoggingSupport {
|
||||
private final String introMessage;
|
||||
|
||||
public StandardWarningHandler(String introMessage) {
|
||||
this.introMessage = introMessage;
|
||||
}
|
||||
|
||||
public boolean doProcess() {
|
||||
return log.isWarnEnabled();
|
||||
}
|
||||
|
||||
public void prepare(SQLWarning warning) {
|
||||
log.debug( introMessage, warning );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void logWarning(String description, String message) {
|
||||
log.warn( description );
|
||||
log.warn( message );
|
||||
}
|
||||
}
|
||||
|
||||
public static StandardWarningHandler STANDARD_WARNING_HANDLER = new StandardWarningHandler( DEFAULT_WARNING_MSG );
|
||||
|
||||
public static void walkWarnings(SQLWarning warning, WarningHandler handler) {
|
||||
if ( warning == null || handler.doProcess() ) {
|
||||
return;
|
||||
}
|
||||
handler.prepare( warning );
|
||||
while ( warning != null ) {
|
||||
handler.handleWarning( warning );
|
||||
warning = warning.getNextWarning();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,20 +236,6 @@ public final class JDBCExceptionReporter {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// public static JDBCException newJDBCException(String string, SQLException root, String sql) {
|
||||
// string = string + " [" + sql + ']';
|
||||
// log.error(string, root);
|
||||
// logExceptions(root);
|
||||
// return new JDBCException(string, root, sql);
|
||||
// }
|
||||
//
|
||||
// public static JDBCException newJDBCException(String string, SQLException root) {
|
||||
// log.error(string, root);
|
||||
// logExceptions(root);
|
||||
// return new JDBCException(string, root);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue