OPENJPA-698: Decorate callable statements with logging. Added a new inner class LoggingConnection.LoggingCallableStatement which is almost a duplicate of LoggingPreparedStatement -- but existing hierarchy prohibits a direct inheritance. The logging with parameter tracking code needs to be refactored for a cleaner and less duplicated code, but has not be done with this commit.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@688111 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Pinaki Poddar 2008-08-22 16:19:07 +00:00
parent 3ee2f9e40e
commit 04c292c761
2 changed files with 452 additions and 4 deletions

View File

@ -63,7 +63,7 @@ public class DelegatingCallableStatement
_del = null; _del = null;
} }
private ResultSet wrapResult(boolean wrap, ResultSet rs) { protected ResultSet wrapResult(boolean wrap, ResultSet rs) {
if (!wrap) if (!wrap)
return rs; return rs;
@ -102,7 +102,7 @@ public class DelegatingCallableStatement
} }
public String toString() { public String toString() {
StringBuffer buf = new StringBuffer("prepstmnt ").append(hashCode()); StringBuffer buf = new StringBuffer("callstmnt ").append(hashCode());
appendInfo(buf); appendInfo(buf);
return buf.toString(); return buf.toString();
} }

View File

@ -24,6 +24,7 @@ import java.math.BigDecimal;
import java.sql.Array; import java.sql.Array;
import java.sql.BatchUpdateException; import java.sql.BatchUpdateException;
import java.sql.Blob; import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob; import java.sql.Clob;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
@ -250,6 +251,16 @@ public class LoggingConnectionDecorator implements ConnectionDecorator {
Statement stmnt = super.createStatement(type, concurrency, false); Statement stmnt = super.createStatement(type, concurrency, false);
return new LoggingStatement(stmnt); return new LoggingStatement(stmnt);
} }
protected CallableStatement prepareCall(String sql, boolean wrap)
throws SQLException {
try {
CallableStatement stmt = super.prepareCall(sql, wrap);
return new LoggingCallableStatement(stmt, sql);
} catch (SQLException se) {
throw wrap(se, sql);
}
}
public void commit() throws SQLException { public void commit() throws SQLException {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
@ -892,7 +903,7 @@ public class LoggingConnectionDecorator implements ConnectionDecorator {
for (int i = 0; i < count.length; i++) { for (int i = 0; i < count.length; i++) {
// -3 is Statement.STATEMENT_FAILED, but is // -3 is Statement.STATEMENT_FAILED, but is
// only available in JDK 1.4+ // only available in JDK 1.4+
if (count[i] == -3) { if (count[i] == Statement.EXECUTE_FAILED) {
index = i; index = i;
break; break;
} }
@ -1295,5 +1306,442 @@ public class LoggingConnectionDecorator implements ConnectionDecorator {
} }
} }
} }
}
/**
* CallableStatement decorated with logging.
* Similar to {@link LoggingPreparedStatement} but can not be extended
* due to the existing delegation hierarchy.
*/
private class LoggingCallableStatement extends
DelegatingCallableStatement {
private final String _sql;
private List _params = null;
private List _paramBatch = null;
public LoggingCallableStatement(CallableStatement stmt, String sql)
throws SQLException {
super(stmt, LoggingConnection.this);
_sql = sql;
}
protected ResultSet wrapResult(ResultSet rs, boolean wrap) {
if (!wrap || rs == null)
return super.wrapResult(wrap, rs);
return new LoggingResultSet(rs, this);
}
protected ResultSet executeQuery(String sql, boolean wrap)
throws SQLException {
logSQL(this);
long start = System.currentTimeMillis();
try {
return super.executeQuery(sql, wrap);
} catch (SQLException se) {
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
public int executeUpdate(String sql) throws SQLException {
logSQL(this);
long start = System.currentTimeMillis();
try {
return super.executeUpdate(sql);
} catch (SQLException se) {
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
public boolean execute(String sql) throws SQLException {
logSQL(this);
long start = System.currentTimeMillis();
try {
return super.execute(sql);
} catch (SQLException se) {
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
protected ResultSet executeQuery(boolean wrap) throws SQLException {
logSQL(this);
long start = System.currentTimeMillis();
try {
return super.executeQuery(wrap);
} catch (SQLException se) {
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
public int executeUpdate() throws SQLException {
logSQL(this);
long start = System.currentTimeMillis();
try {
return super.executeUpdate();
} catch (SQLException se) {
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
public int[] executeBatch() throws SQLException {
logBatchSQL(this);
long start = System.currentTimeMillis();
try {
return super.executeBatch();
} catch (SQLException se) {
// if the exception is a BatchUpdateException, and
// we are tracking parameters, then set the current
// parameter set to be the index of the failed
// statement so that the ReportingSQLException will
// show the correct param
if (se instanceof BatchUpdateException
&& _paramBatch != null && shouldTrackParameters()) {
int[] count = ((BatchUpdateException) se).
getUpdateCounts();
if (count != null && count.length <= _paramBatch.size())
{
int index = -1;
for (int i = 0; i < count.length; i++) {
// -3 is Statement.STATEMENT_FAILED, but is
// only available in JDK 1.4+
if (count[i] == Statement.EXECUTE_FAILED) {
index = i;
break;
}
}
// no -3 element: it may be that the server stopped
// processing, so the size of the count will be
// the index
if (index == -1)
index = count.length + 1;
// set the current params to the saved values
if (index < _paramBatch.size())
_params = (List) _paramBatch.get(index);
}
}
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
public boolean execute() throws SQLException {
logSQL(this);
long start = System.currentTimeMillis();
try {
return super.execute();
} catch (SQLException se) {
throw wrap(se, LoggingCallableStatement.this);
} finally {
logTime(start);
clearLogParameters(true);
handleSQLWarning(LoggingCallableStatement.this);
}
}
public void cancel() throws SQLException {
if (_logs.isJDBCEnabled())
_logs.logJDBC("cancel " + this + ": " + _sql,
LoggingConnection.this);
super.cancel();
}
public void setNull(int i1, int i2) throws SQLException {
setLogParameter(i1, "null", null);
super.setNull(i1, i2);
}
public void setBoolean(int i, boolean b) throws SQLException {
setLogParameter(i, b);
super.setBoolean(i, b);
}
public void setByte(int i, byte b) throws SQLException {
setLogParameter(i, b);
super.setByte(i, b);
}
public void setShort(int i, short s) throws SQLException {
setLogParameter(i, s);
super.setShort(i, s);
}
public void setInt(int i1, int i2) throws SQLException {
setLogParameter(i1, i2);
super.setInt(i1, i2);
}
public void setLong(int i, long l) throws SQLException {
setLogParameter(i, l);
super.setLong(i, l);
}
public void setFloat(int i, float f) throws SQLException {
setLogParameter(i, f);
super.setFloat(i, f);
}
public void setDouble(int i, double d) throws SQLException {
setLogParameter(i, d);
super.setDouble(i, d);
}
public void setBigDecimal(int i, BigDecimal bd)
throws SQLException {
setLogParameter(i, "BigDecimal", bd);
super.setBigDecimal(i, bd);
}
public void setString(int i, String s) throws SQLException {
setLogParameter(i, "String", s);
super.setString(i, s);
}
public void setBytes(int i, byte[] b) throws SQLException {
setLogParameter(i, "byte[]", b);
super.setBytes(i, b);
}
public void setDate(int i, Date d) throws SQLException {
setLogParameter(i, "Date", d);
super.setDate(i, d);
}
public void setTime(int i, Time t) throws SQLException {
setLogParameter(i, "Time", t);
super.setTime(i, t);
}
public void setTimestamp(int i, Timestamp t) throws SQLException {
setLogParameter(i, "Timestamp", t);
super.setTimestamp(i, t);
}
public void setAsciiStream(int i1, InputStream is, int i2)
throws SQLException {
setLogParameter(i1, "InputStream", is);
super.setAsciiStream(i1, is, i2);
}
public void setUnicodeStream(int i1, InputStream is, int i2)
throws SQLException {
setLogParameter(i1, "InputStream", is);
super.setUnicodeStream(i2, is, i2);
}
public void setBinaryStream(int i1, InputStream is, int i2)
throws SQLException {
setLogParameter(i1, "InputStream", is);
super.setBinaryStream(i1, is, i2);
}
public void clearParameters() throws SQLException {
clearLogParameters(false);
super.clearParameters();
}
public void setObject(int i1, Object o, int i2, int i3)
throws SQLException {
setLogParameter(i1, "Object", o);
super.setObject(i1, o, i2, i3);
}
public void setObject(int i1, Object o, int i2)
throws SQLException {
setLogParameter(i1, "Object", o);
super.setObject(i1, o, i2);
}
public void setObject(int i, Object o) throws SQLException {
setLogParameter(i, "Object", o);
super.setObject(i, o);
}
public void addBatch() throws SQLException {
if (_logs.isSQLEnabled())
_logs.logSQL("batching " + this, LoggingConnection.this);
long start = System.currentTimeMillis();
try {
super.addBatch();
if (shouldTrackParameters()) {
// make sure our list is initialized
if (_paramBatch == null)
_paramBatch = new ArrayList();
// copy parameters since they will be re-used
if (_params != null)
_paramBatch.add(new ArrayList(_params));
else
_paramBatch.add(null);
}
}
finally {
logTime(start);
}
}
public void setCharacterStream(int i1, Reader r, int i2)
throws SQLException {
setLogParameter(i1, "Reader", r);
super.setCharacterStream(i1, r, i2);
}
public void setRef(int i, Ref r) throws SQLException {
setLogParameter(i, "Ref", r);
super.setRef(i, r);
}
public void setBlob(int i, Blob b) throws SQLException {
setLogParameter(i, "Blob", b);
super.setBlob(i, b);
}
public void setClob(int i, Clob c) throws SQLException {
setLogParameter(i, "Clob", c);
super.setClob(i, c);
}
public void setArray(int i, Array a) throws SQLException {
setLogParameter(i, "Array", a);
super.setArray(i, a);
}
public ResultSetMetaData getMetaData() throws SQLException {
return super.getMetaData();
}
public void setDate(int i, Date d, Calendar c) throws SQLException {
setLogParameter(i, "Date", d);
super.setDate(i, d, c);
}
public void setTime(int i, Time t, Calendar c) throws SQLException {
setLogParameter(i, "Time", t);
super.setTime(i, t, c);
}
public void setTimestamp(int i, Timestamp t, Calendar c)
throws SQLException {
setLogParameter(i, "Timestamp", t);
super.setTimestamp(i, t, c);
}
public void setNull(int i1, int i2, String s) throws SQLException {
setLogParameter(i1, "null", null);
super.setNull(i1, i2, s);
}
protected void appendInfo(StringBuffer buf) {
buf.append(" ");
if (_formatter != null) {
buf.append(SEP);
buf.append(_formatter.prettyPrint(_sql));
buf.append(SEP);
} else {
buf.append(_sql);
}
StringBuffer paramBuf = null;
if (_params != null && !_params.isEmpty()) {
paramBuf = new StringBuffer();
for (Iterator itr = _params.iterator(); itr.hasNext();) {
paramBuf.append(itr.next());
if (itr.hasNext())
paramBuf.append(", ");
}
}
if (paramBuf != null) {
if (!_prettyPrint)
buf.append(" ");
buf.append("[params=").
append(paramBuf.toString()).append("]");
}
super.appendInfo(buf);
}
protected void clearLogParameters(boolean batch) {
if (_params != null)
_params.clear();
if (batch && _paramBatch != null)
_paramBatch.clear();
}
private boolean shouldTrackParameters() {
return _trackParameters || _logs.isSQLEnabled();
}
private void setLogParameter(int index, boolean val) {
if (shouldTrackParameters())
setLogParameter(index, "(boolean) " + val);
}
private void setLogParameter(int index, byte val) {
if (shouldTrackParameters())
setLogParameter(index, "(byte) " + val);
}
private void setLogParameter(int index, double val) {
if (shouldTrackParameters())
setLogParameter(index, "(double) " + val);
}
private void setLogParameter(int index, float val) {
if (shouldTrackParameters())
setLogParameter(index, "(float) " + val);
}
private void setLogParameter(int index, int val) {
if (shouldTrackParameters())
setLogParameter(index, "(int) " + val);
}
private void setLogParameter(int index, long val) {
if (shouldTrackParameters())
setLogParameter(index, "(long) " + val);
}
private void setLogParameter(int index, short val) {
if (shouldTrackParameters())
setLogParameter(index, "(short) " + val);
}
private void setLogParameter(int index, String type, Object val) {
if (shouldTrackParameters())
setLogParameter(index, "(" + type + ") " + val);
}
private void setLogParameter(int index, String val) {
if (_params == null)
_params = new ArrayList();
while (_params.size() < index)
_params.add(null);
if (val.length() > 80)
val = val.substring(0, 77) + "...";
_params.set(index - 1, val);
}
}
}
} }