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