Author: steve.ebersole(a)jboss.com
Date: 2010-07-11 18:16:38 -0400 (Sun, 11 Jul 2010)
New Revision: 19931
Modified:
core/trunk/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
core/trunk/core/src/main/java/org/hibernate/util/JDBCExceptionReporter.java
Log:
HHH-5373 - Better account for SQLWarnings in temp table creation
Modified:
core/trunk/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java
===================================================================
---
core/trunk/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2010-07-10
13:48:34 UTC (rev 19930)
+++
core/trunk/core/src/main/java/org/hibernate/hql/ast/exec/AbstractStatementExecutor.java 2010-07-11
22:16:38 UTC (rev 19931)
@@ -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.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 @@
* @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 @@
// 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 @@
}
}
+ 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 @@
}
}
+ @SuppressWarnings({ "UnnecessaryUnboxing" })
protected boolean shouldIsolateTemporaryTableDDL() {
Boolean dialectVote = getFactory().getDialect().performTemporaryTableDDLInIsolation();
if ( dialectVote != null ) {
Modified: core/trunk/core/src/main/java/org/hibernate/util/JDBCExceptionReporter.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/util/JDBCExceptionReporter.java 2010-07-10
13:48:34 UTC (rev 19930)
+++ core/trunk/core/src/main/java/org/hibernate/util/JDBCExceptionReporter.java 2010-07-11
22:16:38 UTC (rev 19931)
@@ -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,67 +20,200 @@
* 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 );
}
}
+ /**
+ * 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) {
- logWarnings(warning, null);
+ 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();
+ }
+ }
+
public static void logExceptions(SQLException ex) {
logExceptions(ex, null);
}
@@ -103,20 +236,6 @@
}
}
}
-
-// 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);
-// }
-
}