1 16 package scriptella.jdbc; 17 18 import scriptella.core.EtlCancelledException; 19 import scriptella.spi.AbstractConnection; 20 import scriptella.spi.ParametersCallback; 21 import scriptella.spi.QueryCallback; 22 import scriptella.spi.Resource; 23 import scriptella.util.StringUtils; 24 25 import java.io.Closeable ; 26 import java.io.IOException ; 27 import java.io.Reader ; 28 import java.io.StringReader ; 29 import java.sql.SQLException ; 30 import java.sql.SQLWarning ; 31 import java.util.ArrayList ; 32 import java.util.List ; 33 import java.util.logging.Level ; 34 import java.util.logging.Logger ; 35 36 37 43 class SqlExecutor extends SqlParserBase implements Closeable { 44 private static final Logger LOG = Logger.getLogger(SqlExecutor.class.getName()); 45 protected final Resource resource; 46 protected final JdbcConnection connection; 47 protected final JdbcTypesConverter converter; 48 protected final StatementCache cache; 49 private QueryCallback callback; 50 private ParametersCallback paramsCallback; 51 private List <Object > params = new ArrayList <Object >(); 52 private int updateCount; private final AbstractConnection.StatementCounter counter; 54 private SqlTokenizer cachedTokenizer; 55 56 public SqlExecutor(final Resource resource, final JdbcConnection connection) { 57 this.resource = resource; 58 this.connection = connection; 59 converter = new JdbcTypesConverter(); 60 cache = new StatementCache(connection.getNativeConnection(), connection.statementCacheSize); 61 counter = connection.getStatementCounter(); 62 } 63 64 final void execute(final ParametersCallback parametersCallback) { 65 execute(parametersCallback, null); 66 } 67 68 final void execute(final ParametersCallback parametersCallback, final QueryCallback queryCallback) { 69 paramsCallback = parametersCallback; 70 callback = queryCallback; 71 updateCount = 0; 72 SqlTokenizer tok = cachedTokenizer; 73 boolean cache = false; 74 if (tok==null) { try { 76 final Reader reader = resource.open(); 77 tok = new SqlReaderTokenizer(reader, connection.separator, 78 connection.separatorSingleLine, connection.keepformat); 79 cache = reader instanceof StringReader ; 80 if (cache) { tok = new CachedSqlTokenizer(tok); 82 } 83 } catch (IOException e) { 84 throw new JdbcException("Failed to open resource", e); 85 } 86 } 87 parse(tok); 88 if (cache) { 91 cachedTokenizer=tok; 92 } 93 94 95 } 96 97 int getUpdateCount() { 98 return updateCount; 99 } 100 101 102 @Override 103 protected String handleParameter(final String name, 104 final boolean expression, boolean jdbcParam) { 105 Object p; 106 107 if (expression) { 108 p = connection.getParametersParser().evaluate(name, paramsCallback); 109 } else { 110 p = paramsCallback.getParameter(name); 111 } 112 113 if (jdbcParam) { params.add(p); 115 return "?"; 116 } else { return p == null ? super.handleParameter(name, expression, jdbcParam) : p.toString(); 119 } 120 } 121 122 @Override 123 public void statementParsed(final String sql) { 124 EtlCancelledException.checkEtlCancelled(); 125 StatementWrapper sw = null; 126 try { 127 sw = cache.prepare(sql, params, converter); 128 int updatedRows = -1; 129 if (callback != null) { 130 sw.query(callback, paramsCallback); 131 } else { 132 updatedRows = sw.update(); 133 } 134 logExecutedStatement(sql, params, updatedRows); 135 } catch (SQLException e) { 136 throw new JdbcException("Unable to execute statement", e, sql, params); 137 } catch (JdbcException e) { 138 if (e.getErrorStatement() == null) { 140 e.setErrorStatement(sql, params); 141 } 142 throw e; } finally { 144 params.clear(); 145 if (sw != null) { 146 cache.releaseStatement(sw); 147 } 148 } 149 150 } 151 152 private void logExecutedStatement(final String sql, final List <?> parameters, final int updateCount) { 153 counter.statements++; 154 if (updateCount > 0) { 155 this.updateCount += updateCount; 156 } 157 SQLWarning warnings = null; 158 try { 159 warnings = connection.getNativeConnection().getWarnings(); 160 } catch (Exception e) { 161 LOG.log(Level.WARNING, "Failed to obtain SQL warnings", e); 162 163 } 164 Level level = warnings == null ? Level.FINE : Level.INFO; 165 if (warnings != null) { level = Level.INFO; 167 } 168 169 if (LOG.isLoggable(level)) { 170 StringBuilder sb = new StringBuilder (" Executed statement "); 171 sb.append(StringUtils.consoleFormat(sql)); 172 if (!parameters.isEmpty()) { 173 sb.append(", Parameters: ").append(parameters); 174 } 175 if (updateCount >= 0) { 176 sb.append(". Update count: ").append(updateCount); 177 } 178 if (warnings != null) { sb.append(". SQL Warnings:"); 180 do { 181 sb.append("\n * ").append(warnings); 182 warnings = warnings.getNextWarning(); 183 } while (warnings != null); 184 try { 185 connection.getNativeConnection().clearWarnings(); 186 } catch (Exception e) { LOG.log(Level.WARNING, "Failed to clear SQL warnings", e); 188 } 189 } 190 191 LOG.log(level, sb.toString()); 192 } 193 } 194 195 196 public void close() { 197 cache.close(); 198 } 199 } 200 | Popular Tags |