
net.sourceforge.squirrel_sql.client.session.mainpanel.SQLExecutionHandler Maven / Gradle / Ivy
package net.sourceforge.squirrel_sql.client.session.mainpanel;
import net.sourceforge.squirrel_sql.client.preferences.SquirrelPreferences;
import net.sourceforge.squirrel_sql.client.session.ISQLExecuterHandler;
import net.sourceforge.squirrel_sql.client.session.ISession;
import net.sourceforge.squirrel_sql.client.session.SQLExecuterTask;
import net.sourceforge.squirrel_sql.client.session.SQLExecutionInfo;
import net.sourceforge.squirrel_sql.client.session.event.ISQLExecutionListener;
import net.sourceforge.squirrel_sql.client.session.properties.SessionProperties;
import net.sourceforge.squirrel_sql.fw.datasetviewer.DataSetException;
import net.sourceforge.squirrel_sql.fw.datasetviewer.IDataSetUpdateableTableModel;
import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetDataSet;
import net.sourceforge.squirrel_sql.fw.datasetviewer.ResultSetMetaDataDataSet;
import net.sourceforge.squirrel_sql.fw.dialects.DialectFactory;
import net.sourceforge.squirrel_sql.fw.dialects.DialectType;
import net.sourceforge.squirrel_sql.fw.sql.SQLExecutionException;
import net.sourceforge.squirrel_sql.fw.util.StringManager;
import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
import net.sourceforge.squirrel_sql.fw.util.StringUtilities;
import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
import java.sql.ResultSet;
import java.sql.SQLWarning;
import java.text.NumberFormat;
import java.util.ArrayList;
/**
* This class is the handler for the execution of sql against the SQLExecuterPanel
*/
class SQLExecutionHandler implements ISQLExecuterHandler
{
private static final ILogger s_log =
LoggerController.createLogger(SQLExecutionHandler.class);
private static final StringManager s_stringMgr =
StringManagerFactory.getStringManager(SQLExecutionHandler.class);
private CancelPanelCtrl _cancelPanelCtrl;
private SQLExecuterTask _executer;
private ISession _session;
private ISQLExecutionHandlerListener _executionHandlerListener;
private static enum SQLType
{
INSERT, SELECT, UPDATE, DELETE, UNKNOWN
}
/**
* Hold onto the current ResultDataSet so if the execution is
* cancelled then this can be cancelled.
*/
private ResultSetDataSet rsds = null;
private String sqlToBeExecuted = null;
private SQLType sqlType = null;
private IResultTab _resultTabToReplace;
private boolean _largeScript = false;
private double _scriptTotalTime = 0;
private double _scriptQueryTime = 0;
private double _scriptOutptutTime = 0;
private int _scriptRowsInserted = 0;
private int _scriptRowsSelected = 0;
private int _scriptRowsUpdated = 0;
private int _scriptRowsDeleted = 0;
public SQLExecutionHandler(IResultTab resultTabToReplace,
ISession session,
String sql,
ISQLExecutionHandlerListener executionHandlerListener,
ISQLExecutionListener[] executionListeners)
{
_session = session;
_executionHandlerListener = executionHandlerListener;
_executer = new SQLExecuterTask(_session, sql, this, executionListeners);
SquirrelPreferences prefs = _session.getApplication().getSquirrelPreferences();
if (prefs.getLargeScriptStmtCount() > 0
&& _executer.getQueryCount() > prefs.getLargeScriptStmtCount())
{
_executer.setExecutionListeners(new ISQLExecutionListener[0]);
setLargeScript(true);
}
_resultTabToReplace = resultTabToReplace;
_cancelPanelCtrl = new CancelPanelCtrl(new CancelPanelListener()
{
@Override
public void cancelRequested()
{
onCancelRequested();
}
});
_executionHandlerListener.setCancelPanel(_cancelPanelCtrl);
_session.getApplication().getThreadPool().addTask(_executer);
}
private void onCancelRequested()
{
try
{
if (_executer != null)
{
_executer.cancel();
}
}
catch (Throwable th)
{
s_log.error("Error occured cancelling SQL", th);
}
}
/**
* Set whether or not the script is large. If the script is large, then
* do some performance optimizations with the GUI so that it remains
* responsive. If the UI is not responsive, then the user is not able
* to see what is happening, nor are they able to control it (cancelling
* becomes ineffective)
*
* @param aBoolean whether or not the script is large.
*/
public void setLargeScript(boolean aBoolean)
{
_largeScript = aBoolean;
}
/**
* Determines whether or not the current statement SQL should be rendered.
* Since too many statements can cause the UI to stop rendering the
* statements, we back off rendering after many statements so that the UI
* can continue to provide feedback to the user.
*
* @param current
* @param total
* @return
*/
private boolean shouldRenderSQL(int current, int total)
{
if (!_largeScript)
{
return true;
}
boolean result = true;
// Back-off a bit after a hundred updates to allow the UI to update
if (total > 200 && current > 100 && current % 10 != 0)
{
result = false;
}
if (total > 1000 && current > 500 && current % 50 != 0)
{
result = false;
}
if (total > 2000 && current > 1000 && current % 100 != 0)
{
result = false;
}
return result;
}
public void sqlToBeExecuted(final String sql)
{
_cancelPanelCtrl.incCurrentQueryIndex();
int currentStmtCount = _cancelPanelCtrl.getCurrentQueryIndex();
if (!shouldRenderSQL(currentStmtCount, _cancelPanelCtrl.getTotalCount()))
{
return;
}
final String cleanSQL = StringUtilities.cleanString(sql);
sqlToBeExecuted = cleanSQL;
sqlType = getSQLType(cleanSQL);
_cancelPanelCtrl.setSQL(sqlToBeExecuted);
// i18n[SQLResultExecuterPanel.execStatus=Executing SQL...]
String status = s_stringMgr.getString("SQLResultExecuterPanel.execStatus");
_cancelPanelCtrl.setStatusLabel(status);
}
private SQLType getSQLType(String sql)
{
SQLType result = SQLType.UNKNOWN;
if (sql.toLowerCase().startsWith("insert"))
{
result = SQLType.INSERT;
}
if (sql.toLowerCase().startsWith("update"))
{
result = SQLType.UPDATE;
}
if (sql.toLowerCase().startsWith("select"))
{
result = SQLType.SELECT;
}
if (sql.toLowerCase().startsWith("delete"))
{
result = SQLType.DELETE;
}
return result;
}
/**
* This will - depending on the size of the script - print a message
* indicating the time that it took to execute one or more queries.
* When executing a large script (as defined by the user, but default is
* > 200 statements) we don't want to keep sending messages to the
* message panel, otherwise the UI will get behind and slow the execution
* of the script and prevent the user from cancelling the operation. So
* this method will track the total time when executing a large script,
* otherwise for small scripts it puts out a message for every statemselect * from employeeent.
*/
public void sqlExecutionComplete(SQLExecutionInfo exInfo,
int processedStatementCount,
int statementCount)
{
double executionLength = ((double) exInfo.getSQLExecutionElapsedMillis()) / 1000;
double outputLength = ((double) exInfo.getResultsProcessingElapsedMillis()) / 1000;
double totalLength = executionLength + outputLength;
Integer numberResultRowsRead = exInfo.getNumberResultRowsRead();
if (_largeScript)
{
// Track the time in aggregate for the script.
_scriptQueryTime += executionLength;
_scriptOutptutTime += outputLength;
_scriptTotalTime += totalLength;
// When we get to the last statement, if the script is large,
// show the user the total execution time.
if (statementCount == processedStatementCount)
{
printScriptExecDetails(statementCount,
_scriptQueryTime,
_scriptOutptutTime,
_scriptTotalTime);
}
}
else
{
printStatementExecTime(
processedStatementCount,
statementCount,
numberResultRowsRead,
executionLength,
outputLength,
totalLength);
}
}
private void printScriptExecDetails(int statementCount,
double executionLength,
double outputLength,
double totalLength)
{
final NumberFormat nbrFmt = NumberFormat.getNumberInstance();
Object[] args = new Object[]{
Integer.valueOf(statementCount),
nbrFmt.format(totalLength),
nbrFmt.format(executionLength),
nbrFmt.format(outputLength)
};
//i18n[SQLResultExecuterPanel.scriptQueryStatistics=Executed {0}
//queries; elapsed time (seconds) - Total: {1}, SQL query: {2},
//Building output: {3}]
String stats = s_stringMgr.getString("SQLResultExecuterPanel.scriptQueryStatistics", args);
String[] counts =
new String[]{Integer.toString(_scriptRowsInserted),
Integer.toString(_scriptRowsSelected),
Integer.toString(_scriptRowsUpdated),
Integer.toString(_scriptRowsDeleted)};
//i18n[SQLResultExecuterPanel.scriptStmtCounts=Row update
//counts: {0} Inserts, {1} Selects, {2} Updates, {3} Deletes
String msg =
s_stringMgr.getString("SQLResultExecuterPanel.scriptStmtCounts", counts);
_session.showMessage(msg);
_session.showMessage(stats);
}
private void printStatementExecTime(
int processedStatementCount,
int statementCount,
Integer numberResultRowsRead,
double executionLength,
double outputLength,
double totalLength)
{
final NumberFormat nbrFmt = NumberFormat.getNumberInstance();
Object[] args = new Object[]{
Integer.valueOf(processedStatementCount),
Integer.valueOf(statementCount),
numberResultRowsRead == null ? 0 : numberResultRowsRead,
nbrFmt.format(totalLength),
nbrFmt.format(executionLength),
nbrFmt.format(outputLength)
};
//i18n[SQLResultExecuterPanel.queryStatistics=Query {0} of {1}
//elapsed time (seconds) - Total: {2}, SQL query: {3},
//Building output: {4}]
String stats = s_stringMgr.getString("SQLResultExecuterPanel.queryStatistics", args);
_session.showMessage(stats);
}
public void sqlExecutionCancelled()
{
if (rsds != null)
{
rsds.cancelProcessing();
}
// i18n[SQLResultExecuterPanel.canceleRequested=Query execution cancel requested by user.]
// String canc =
// s_stringMgr.getString("SQLResultExecuterPanel.canceleRequested");
// getSession().getMessageHandler().showMessage(canc);
}
public void sqlDataUpdated(int updateCount)
{
Integer count = Integer.valueOf(updateCount);
String msg = "";
switch (sqlType)
{
case INSERT:
if (_largeScript)
{
_scriptRowsInserted++;
}
else
{
// i18n[SQLResultExecuterPanel.rowsUpdated={0} Row(s) Inserted]
msg = s_stringMgr.getString("SQLResultExecuterPanel.rowsInserted", count);
}
break;
case SELECT:
if (_largeScript)
{
_scriptRowsSelected++;
}
else
{
// i18n[SQLResultExecuterPanel.rowsSelected={0} Row(s) Selected]
msg = s_stringMgr.getString("SQLResultExecuterPanel.rowsSelected", count);
}
break;
case UPDATE:
if (_largeScript)
{
_scriptRowsUpdated++;
}
else
{
// i18n[SQLResultExecuterPanel.rowsUpdated={0} Row(s) Updated]
msg = s_stringMgr.getString("SQLResultExecuterPanel.rowsUpdated", count);
}
break;
case DELETE:
if (_largeScript)
{
_scriptRowsDeleted++;
}
else
{
// i18n[SQLResultExecuterPanel.rowsDeleted={0} Row(s) Deleted]
msg = s_stringMgr.getString("SQLResultExecuterPanel.rowsDeleted", count);
}
break;
}
if (_largeScript)
{
return;
}
_session.showMessage(msg);
}
public void sqlResultSetAvailable(ResultSet rs, SQLExecutionInfo info, IDataSetUpdateableTableModel model)
throws DataSetException
{
// i18n[SQLResultExecuterPanel.outputStatus=Building output...]
String outputStatus = s_stringMgr.getString("SQLResultExecuterPanel.outputStatus");
_cancelPanelCtrl.setStatusLabel(outputStatus);
rsds = new ResultSetDataSet();
try {
SessionProperties props = _session.getProperties();
ResultSetMetaDataDataSet rsmdds = null;
if (props.getShowResultsMetaData())
{
rsmdds = new ResultSetMetaDataDataSet(rs);
}
DialectType dialectType =
DialectFactory.getDialectType(_session.getMetaData());
info.setNumberResultRowsRead(rsds.setContentsTabResultSet(rs, null, dialectType));
_executionHandlerListener.addResultsTab(info, rsds, rsmdds, model, _resultTabToReplace);
}finally{
/*
* Make sure, that in any case, even when a exception occurs, the rsds is set to null, so that
* the GC can clean them.
*/
rsds = null;
}
}
public void sqlExecutionWarning(SQLWarning warn)
{
_session.showMessage(warn);
}
public void sqlStatementCount(int statementCount)
{
_cancelPanelCtrl.setQueryCount(statementCount);
}
public void sqlCloseExecutionHandler(ArrayList sqlExecErrorMsgs, String lastExecutedStatement)
{
_executionHandlerListener.removeCancelPanel(_cancelPanelCtrl, _resultTabToReplace);
if (null != sqlExecErrorMsgs && 0 < sqlExecErrorMsgs.size() && _session.getProperties().getShowSQLErrorsInTab())
{
_executionHandlerListener.displayErrors(sqlExecErrorMsgs, lastExecutedStatement);
}
_executer = null;
}
public String sqlExecutionException(Throwable th, String postErrorString)
{
SQLExecutionException ex =
new SQLExecutionException(th, postErrorString);
String message = _session.formatException(ex);
_session.showErrorMessage(message);
if (_session.getProperties().getWriteSQLErrorsToLog())
{
s_log.info(message);
}
return message;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy