1 package SQLite.JDBC2z1; 2 3 import java.sql.BatchUpdateException; 4 import java.sql.Connection; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 import java.sql.SQLFeatureNotSupportedException; 8 import java.sql.SQLWarning; 9 import java.sql.Statement; 10 import java.util.ArrayList; 11 12 public class JDBCStatement implements java.sql.Statement { 13 14 protected JDBCConnection conn; 15 protected JDBCResultSet rs; 16 protected int updcnt; 17 protected int maxrows = 0; 18 private ArrayList<String> batch; 19 JDBCStatement(JDBCConnection conn)20 public JDBCStatement(JDBCConnection conn) { 21 this.conn = conn; 22 this.updcnt = 0; 23 this.rs = null; 24 this.batch = null; 25 } 26 27 @Override setFetchSize(int fetchSize)28 public void setFetchSize(int fetchSize) throws SQLException { 29 if (fetchSize != 1) { 30 throw new SQLException("fetch size not 1"); 31 } 32 } 33 34 @Override getFetchSize()35 public int getFetchSize() throws SQLException { 36 return 1; 37 } 38 39 @Override getMaxRows()40 public int getMaxRows() throws SQLException { 41 return maxrows; 42 } 43 44 @Override setMaxRows(int max)45 public void setMaxRows(int max) throws SQLException { 46 if (max < 0) { 47 throw new SQLException("max must be >= 0 (was " + max + ")"); 48 } 49 maxrows = max; 50 } 51 52 @Override setFetchDirection(int fetchDirection)53 public void setFetchDirection(int fetchDirection) throws SQLException { 54 throw new SQLException("not supported"); 55 } 56 57 @Override getFetchDirection()58 public int getFetchDirection() throws SQLException { 59 return ResultSet.FETCH_UNKNOWN; 60 } 61 62 @Override getResultSetConcurrency()63 public int getResultSetConcurrency() throws SQLException { 64 return ResultSet.CONCUR_READ_ONLY; 65 } 66 67 @Override getResultSetType()68 public int getResultSetType() throws SQLException { 69 return ResultSet.TYPE_SCROLL_INSENSITIVE; 70 } 71 72 @Override setQueryTimeout(int seconds)73 public void setQueryTimeout(int seconds) throws SQLException { 74 if (isClosed()) { 75 throw new SQLException("can't set query timeout on " + 76 "a closed statement"); 77 } else if (seconds < 0) { 78 throw new SQLException("can't set a query timeout of " + 79 "less than 0 seconds"); 80 } else if (seconds == 0) { 81 conn.timeout = 5000; 82 } else { 83 conn.timeout = seconds * 1000; 84 } 85 } 86 87 @Override getQueryTimeout()88 public int getQueryTimeout() throws SQLException { 89 return conn.timeout / 1000; 90 } 91 92 @Override getResultSet()93 public ResultSet getResultSet() throws SQLException { 94 return rs; 95 } 96 executeQuery(String sql, String args[], boolean updonly)97 ResultSet executeQuery(String sql, String args[], boolean updonly) 98 throws SQLException { 99 SQLite.TableResult tr = null; 100 if (rs != null) { 101 rs.close(); 102 rs = null; 103 } 104 updcnt = -1; 105 if (conn == null || conn.db == null) { 106 throw new SQLException("stale connection"); 107 } 108 int busy = 0; 109 boolean starttrans = !conn.autocommit && !conn.intrans; 110 while (true) { 111 try { 112 if (starttrans) { 113 conn.db.exec("BEGIN TRANSACTION", null); 114 conn.intrans = true; 115 } 116 if (args == null) { 117 if (updonly) { 118 conn.db.exec(sql, null); 119 } else { 120 tr = conn.db.get_table(sql, maxrows); 121 } 122 } else { 123 if (updonly) { 124 conn.db.exec(sql, null, args); 125 } else { 126 tr = conn.db.get_table(sql, maxrows, args); 127 } 128 } 129 updcnt = (int) conn.db.changes(); 130 } catch (SQLite.Exception e) { 131 if (conn.db.is3() && 132 conn.db.last_error() == SQLite.Constants.SQLITE_BUSY && 133 conn.busy3(conn.db, ++busy)) { 134 try { 135 if (starttrans && conn.intrans) { 136 conn.db.exec("ROLLBACK", null); 137 conn.intrans = false; 138 } 139 } catch (SQLite.Exception ee) { 140 } 141 try { 142 int ms = 20 + busy * 10; 143 if (ms > 1000) { 144 ms = 1000; 145 } 146 synchronized (this) { 147 this.wait(ms); 148 } 149 } catch (java.lang.Exception eee) { 150 } 151 continue; 152 } 153 throw new SQLException(e); 154 } 155 break; 156 } 157 if (!updonly && tr == null) { 158 throw new SQLException("no result set produced"); 159 } 160 if (!updonly && tr != null) { 161 rs = new JDBCResultSet(new TableResultX(tr), this); 162 } 163 return rs; 164 } 165 166 @Override executeQuery(String sql)167 public ResultSet executeQuery(String sql) throws SQLException { 168 return executeQuery(sql, null, false); 169 } 170 171 @Override execute(String sql)172 public boolean execute(String sql) throws SQLException { 173 return executeQuery(sql) != null; 174 } 175 176 @Override cancel()177 public void cancel() throws SQLException { 178 if (conn == null || conn.db == null) { 179 throw new SQLException("stale connection"); 180 } 181 conn.db.interrupt(); 182 } 183 184 @Override clearWarnings()185 public void clearWarnings() throws SQLException { 186 } 187 188 @Override getConnection()189 public Connection getConnection() throws SQLException { 190 return conn; 191 } 192 193 @Override addBatch(String sql)194 public void addBatch(String sql) throws SQLException { 195 if (batch == null) { 196 batch = new ArrayList<String>(1); 197 } 198 batch.add(sql); 199 } 200 201 @Override executeBatch()202 public int[] executeBatch() throws SQLException { 203 if (batch == null) { 204 return new int[0]; 205 } 206 int[] ret = new int[batch.size()]; 207 for (int i = 0; i < ret.length; i++) { 208 ret[i] = EXECUTE_FAILED; 209 } 210 int errs = 0; 211 Exception cause = null; 212 for (int i = 0; i < ret.length; i++) { 213 try { 214 execute(batch.get(i)); 215 ret[i] = updcnt; 216 } catch (SQLException e) { 217 ++errs; 218 if (cause == null) { 219 cause = e; 220 } 221 } 222 } 223 if (errs > 0) { 224 throw new BatchUpdateException("batch failed", ret, cause); 225 } 226 return ret; 227 } 228 229 @Override clearBatch()230 public void clearBatch() throws SQLException { 231 if (batch != null) { 232 batch.clear(); 233 batch = null; 234 } 235 } 236 237 @Override close()238 public void close() throws SQLException { 239 clearBatch(); 240 conn = null; 241 } 242 243 @Override executeUpdate(String sql)244 public int executeUpdate(String sql) throws SQLException { 245 executeQuery(sql, null, true); 246 return updcnt; 247 } 248 249 @Override getMaxFieldSize()250 public int getMaxFieldSize() throws SQLException { 251 return 0; 252 } 253 254 @Override getMoreResults()255 public boolean getMoreResults() throws SQLException { 256 if (rs != null) { 257 rs.close(); 258 rs = null; 259 } 260 return false; 261 } 262 263 @Override getUpdateCount()264 public int getUpdateCount() throws SQLException { 265 return updcnt; 266 } 267 268 @Override getWarnings()269 public SQLWarning getWarnings() throws SQLException { 270 return null; 271 } 272 273 @Override setCursorName(String name)274 public void setCursorName(String name) throws SQLException { 275 throw new SQLFeatureNotSupportedException(); 276 } 277 278 @Override setEscapeProcessing(boolean enable)279 public void setEscapeProcessing(boolean enable) throws SQLException { 280 throw new SQLException("not supported"); 281 } 282 283 @Override setMaxFieldSize(int max)284 public void setMaxFieldSize(int max) throws SQLException { 285 throw new SQLException("not supported"); 286 } 287 288 @Override getMoreResults(int x)289 public boolean getMoreResults(int x) throws SQLException { 290 throw new SQLFeatureNotSupportedException(); 291 } 292 293 @Override getGeneratedKeys()294 public ResultSet getGeneratedKeys() throws SQLException { 295 throw new SQLFeatureNotSupportedException(); 296 } 297 298 @Override executeUpdate(String sql, int autokeys)299 public int executeUpdate(String sql, int autokeys) 300 throws SQLException { 301 if (autokeys != Statement.NO_GENERATED_KEYS) { 302 throw new SQLFeatureNotSupportedException("generated keys not supported"); 303 } 304 return executeUpdate(sql); 305 } 306 307 @Override executeUpdate(String sql, int colIndexes[])308 public int executeUpdate(String sql, int colIndexes[]) 309 throws SQLException { 310 throw new SQLFeatureNotSupportedException(); 311 } 312 313 @Override executeUpdate(String sql, String colIndexes[])314 public int executeUpdate(String sql, String colIndexes[]) 315 throws SQLException { 316 throw new SQLFeatureNotSupportedException(); 317 } 318 319 @Override execute(String sql, int autokeys)320 public boolean execute(String sql, int autokeys) 321 throws SQLException { 322 if (autokeys != Statement.NO_GENERATED_KEYS) { 323 throw new SQLFeatureNotSupportedException("autogenerated keys not supported"); 324 } 325 return execute(sql); 326 } 327 328 @Override execute(String sql, int colIndexes[])329 public boolean execute(String sql, int colIndexes[]) 330 throws SQLException { 331 throw new SQLFeatureNotSupportedException(); 332 } 333 334 @Override execute(String sql, String colIndexes[])335 public boolean execute(String sql, String colIndexes[]) 336 throws SQLException { 337 throw new SQLFeatureNotSupportedException(); 338 } 339 340 @Override getResultSetHoldability()341 public int getResultSetHoldability() throws SQLException { 342 return ResultSet.HOLD_CURSORS_OVER_COMMIT; 343 } 344 345 @Override isClosed()346 public boolean isClosed() throws SQLException { 347 return conn == null; 348 } 349 350 @Override setPoolable(boolean yes)351 public void setPoolable(boolean yes) throws SQLException { 352 if (yes) { 353 throw new SQLException("poolable statements not supported"); 354 } 355 } 356 357 @Override isPoolable()358 public boolean isPoolable() throws SQLException { 359 return false; 360 } 361 362 @Override unwrap(java.lang.Class<T> iface)363 public <T> T unwrap(java.lang.Class<T> iface) throws SQLException { 364 throw new SQLException("unsupported"); 365 } 366 367 @Override isWrapperFor(java.lang.Class iface)368 public boolean isWrapperFor(java.lang.Class iface) throws SQLException { 369 return false; 370 } 371 372 @Override closeOnCompletion()373 public void closeOnCompletion() throws SQLException { 374 throw new SQLFeatureNotSupportedException(); 375 } 376 377 @Override isCloseOnCompletion()378 public boolean isCloseOnCompletion() throws SQLException { 379 throw new SQLFeatureNotSupportedException(); 380 } 381 382 } 383