mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-11-22 18:32:24 +00:00
541 lines
16 KiB
Java
541 lines
16 KiB
Java
/*
|
|
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
package org.sqlite;
|
|
|
|
import java.io.Reader;
|
|
import java.io.StringReader;
|
|
import java.sql.Date;
|
|
import java.sql.ResultSet;
|
|
import java.sql.ResultSetMetaData;
|
|
import java.sql.SQLException;
|
|
import java.sql.SQLWarning;
|
|
import java.sql.Statement;
|
|
import java.sql.Time;
|
|
import java.sql.Timestamp;
|
|
import java.sql.Types;
|
|
import java.util.Calendar;
|
|
|
|
/**
|
|
* Implements a JDBC ResultSet.
|
|
*/
|
|
final class RS extends Unused implements ResultSet, ResultSetMetaData, Codes
|
|
{
|
|
private final Stmt stmt;
|
|
private final DB db;
|
|
|
|
boolean open = false; // true means have results and can iterate them
|
|
int maxRows; // max. number of rows as set by a Statement
|
|
String[] cols = null; // if null, the RS is closed()
|
|
String[] colsMeta = null; // same as cols, but used by Meta interface
|
|
boolean[][] meta = null;
|
|
|
|
private int limitRows; // 0 means no limit, must check against maxRows
|
|
private int row = 0; // number of current row, starts at 1 (0 is for before loading data)
|
|
private int lastCol; // last column accessed, for wasNull(). -1 if none
|
|
|
|
RS(Stmt stmt) {
|
|
this.stmt = stmt;
|
|
this.db = stmt.db;
|
|
}
|
|
|
|
// INTERNAL FUNCTIONS ///////////////////////////////////////////
|
|
|
|
boolean isOpen() {
|
|
return open;
|
|
}
|
|
|
|
/* Throws SQLException if ResultSet is not open. */
|
|
void checkOpen() throws SQLException {
|
|
if (!open)
|
|
throw new SQLException("ResultSet closed");
|
|
}
|
|
|
|
// takes col in [1,x] form, returns in [0,x-1] form
|
|
private int checkCol(int col) throws SQLException {
|
|
if (colsMeta == null)
|
|
throw new IllegalStateException("SQLite JDBC: inconsistent internal state");
|
|
if (col < 1 || col > colsMeta.length)
|
|
throw new SQLException("column " + col + " out of bounds [1," + colsMeta.length + "]");
|
|
return --col;
|
|
}
|
|
|
|
// takes col in [1,x] form, marks it as last accessed and returns [0,x-1]
|
|
private int markCol(int col) throws SQLException {
|
|
checkOpen();
|
|
checkCol(col);
|
|
lastCol = col;
|
|
return --col;
|
|
}
|
|
|
|
private void checkMeta() throws SQLException {
|
|
checkCol(1);
|
|
if (meta == null)
|
|
meta = db.column_metadata(stmt.pointer);
|
|
}
|
|
|
|
// ResultSet Functions //////////////////////////////////////////
|
|
|
|
public void close() throws SQLException {
|
|
cols = null;
|
|
colsMeta = null;
|
|
meta = null;
|
|
open = false;
|
|
limitRows = 0;
|
|
row = 0;
|
|
lastCol = -1;
|
|
|
|
if (stmt == null)
|
|
return;
|
|
if (stmt != null && stmt.pointer != 0)
|
|
db.reset(stmt.pointer);
|
|
}
|
|
|
|
// returns col in [1,x] form
|
|
public int findColumn(String col) throws SQLException {
|
|
checkOpen();
|
|
int c = -1;
|
|
for (int i = 0; i < cols.length; i++) {
|
|
if (col.equalsIgnoreCase(cols[i])
|
|
|| (cols[i].toUpperCase().endsWith(col.toUpperCase()) && cols[i].charAt(cols[i].length()
|
|
- col.length()) == '.')) {
|
|
if (c == -1)
|
|
c = i;
|
|
else
|
|
throw new SQLException("ambiguous column: '" + col + "'");
|
|
}
|
|
}
|
|
if (c == -1)
|
|
throw new SQLException("no such column: '" + col + "'");
|
|
else
|
|
return c + 1;
|
|
}
|
|
|
|
public boolean next() throws SQLException {
|
|
if (!open)
|
|
return false; // finished ResultSet
|
|
lastCol = -1;
|
|
|
|
// first row is loaded by execute(), so do not step() again
|
|
if (row == 0) {
|
|
row++;
|
|
return true;
|
|
}
|
|
|
|
// check if we are row limited by the statement or the ResultSet
|
|
if (maxRows != 0 && row > maxRows)
|
|
return false;
|
|
|
|
// do the real work
|
|
int statusCode = db.step(stmt.pointer);
|
|
switch (statusCode) {
|
|
case SQLITE_DONE:
|
|
close(); // agressive closing to avoid writer starvation
|
|
return false;
|
|
case SQLITE_ROW:
|
|
row++;
|
|
return true;
|
|
case SQLITE_BUSY:
|
|
default:
|
|
db.throwex(statusCode);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public int getType() throws SQLException {
|
|
return TYPE_FORWARD_ONLY;
|
|
}
|
|
|
|
public int getFetchSize() throws SQLException {
|
|
return limitRows;
|
|
}
|
|
|
|
public void setFetchSize(int rows) throws SQLException {
|
|
if (0 > rows || (maxRows != 0 && rows > maxRows))
|
|
throw new SQLException("fetch size " + rows + " out of bounds " + maxRows);
|
|
limitRows = rows;
|
|
}
|
|
|
|
public int getFetchDirection() throws SQLException {
|
|
checkOpen();
|
|
return ResultSet.FETCH_FORWARD;
|
|
}
|
|
|
|
public void setFetchDirection(int d) throws SQLException {
|
|
checkOpen();
|
|
if (d != ResultSet.FETCH_FORWARD)
|
|
throw new SQLException("only FETCH_FORWARD direction supported");
|
|
}
|
|
|
|
public boolean isAfterLast() throws SQLException {
|
|
return !open;
|
|
}
|
|
|
|
public boolean isBeforeFirst() throws SQLException {
|
|
return open && row == 0;
|
|
}
|
|
|
|
public boolean isFirst() throws SQLException {
|
|
return row == 1;
|
|
}
|
|
|
|
public boolean isLast() throws SQLException { // FIXME
|
|
throw new SQLException("function not yet implemented for SQLite");
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws SQLException {
|
|
close();
|
|
}
|
|
|
|
public int getRow() throws SQLException {
|
|
return row;
|
|
}
|
|
|
|
public boolean wasNull() throws SQLException {
|
|
return db.column_type(stmt.pointer, markCol(lastCol)) == SQLITE_NULL;
|
|
}
|
|
|
|
// DATA ACCESS FUNCTIONS ////////////////////////////////////////
|
|
|
|
public boolean getBoolean(int col) throws SQLException {
|
|
return getInt(col) == 0 ? false : true;
|
|
}
|
|
|
|
public boolean getBoolean(String col) throws SQLException {
|
|
return getBoolean(findColumn(col));
|
|
}
|
|
|
|
public byte getByte(int col) throws SQLException {
|
|
return (byte) getInt(col);
|
|
}
|
|
|
|
public byte getByte(String col) throws SQLException {
|
|
return getByte(findColumn(col));
|
|
}
|
|
|
|
public byte[] getBytes(int col) throws SQLException {
|
|
return db.column_blob(stmt.pointer, markCol(col));
|
|
}
|
|
|
|
public byte[] getBytes(String col) throws SQLException {
|
|
return getBytes(findColumn(col));
|
|
}
|
|
|
|
public Reader getCharacterStream(int col) throws SQLException {
|
|
return new StringReader(getString(col));
|
|
}
|
|
|
|
public Reader getCharacterStream(String col) throws SQLException {
|
|
return getCharacterStream(findColumn(col));
|
|
}
|
|
|
|
public Date getDate(int col) throws SQLException {
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return null;
|
|
return new Date(db.column_long(stmt.pointer, markCol(col)));
|
|
}
|
|
|
|
public Date getDate(int col, Calendar cal) throws SQLException {
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return null;
|
|
if (cal == null)
|
|
return getDate(col);
|
|
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
|
|
return new Date(cal.getTime().getTime());
|
|
}
|
|
|
|
public Date getDate(String col) throws SQLException {
|
|
return getDate(findColumn(col), Calendar.getInstance());
|
|
}
|
|
|
|
public Date getDate(String col, Calendar cal) throws SQLException {
|
|
return getDate(findColumn(col), cal);
|
|
}
|
|
|
|
public double getDouble(int col) throws SQLException {
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return 0;
|
|
return db.column_double(stmt.pointer, markCol(col));
|
|
}
|
|
|
|
public double getDouble(String col) throws SQLException {
|
|
return getDouble(findColumn(col));
|
|
}
|
|
|
|
public float getFloat(int col) throws SQLException {
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return 0;
|
|
return (float) db.column_double(stmt.pointer, markCol(col));
|
|
}
|
|
|
|
public float getFloat(String col) throws SQLException {
|
|
return getFloat(findColumn(col));
|
|
}
|
|
|
|
public int getInt(int col) throws SQLException {
|
|
return db.column_int(stmt.pointer, markCol(col));
|
|
}
|
|
|
|
public int getInt(String col) throws SQLException {
|
|
return getInt(findColumn(col));
|
|
}
|
|
|
|
public long getLong(int col) throws SQLException {
|
|
return db.column_long(stmt.pointer, markCol(col));
|
|
}
|
|
|
|
public long getLong(String col) throws SQLException {
|
|
return getLong(findColumn(col));
|
|
}
|
|
|
|
public short getShort(int col) throws SQLException {
|
|
return (short) getInt(col);
|
|
}
|
|
|
|
public short getShort(String col) throws SQLException {
|
|
return getShort(findColumn(col));
|
|
}
|
|
|
|
public String getString(int col) throws SQLException {
|
|
return db.column_text(stmt.pointer, markCol(col));
|
|
}
|
|
|
|
public String getString(String col) throws SQLException {
|
|
return getString(findColumn(col));
|
|
}
|
|
|
|
public Time getTime(int col) throws SQLException {
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return null;
|
|
return new Time(db.column_long(stmt.pointer, markCol(col)));
|
|
}
|
|
|
|
public Time getTime(int col, Calendar cal) throws SQLException {
|
|
if (cal == null)
|
|
return getTime(col);
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return null;
|
|
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
|
|
return new Time(cal.getTime().getTime());
|
|
}
|
|
|
|
public Time getTime(String col) throws SQLException {
|
|
return getTime(findColumn(col));
|
|
}
|
|
|
|
public Time getTime(String col, Calendar cal) throws SQLException {
|
|
return getTime(findColumn(col), cal);
|
|
}
|
|
|
|
public Timestamp getTimestamp(int col) throws SQLException {
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return null;
|
|
return new Timestamp(db.column_long(stmt.pointer, markCol(col)));
|
|
}
|
|
|
|
public Timestamp getTimestamp(int col, Calendar cal) throws SQLException {
|
|
if (cal == null)
|
|
return getTimestamp(col);
|
|
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
|
return null;
|
|
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
|
|
return new Timestamp(cal.getTime().getTime());
|
|
}
|
|
|
|
public Timestamp getTimestamp(String col) throws SQLException {
|
|
return getTimestamp(findColumn(col));
|
|
}
|
|
|
|
public Timestamp getTimestamp(String c, Calendar ca) throws SQLException {
|
|
return getTimestamp(findColumn(c), ca);
|
|
}
|
|
|
|
public Object getObject(int col) throws SQLException {
|
|
switch (db.column_type(stmt.pointer, checkCol(col))) {
|
|
case SQLITE_INTEGER:
|
|
long val = getLong(col);
|
|
if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE)
|
|
return new Long(val);
|
|
else
|
|
return new Integer((int) val);
|
|
case SQLITE_FLOAT:
|
|
return new Double(getDouble(col));
|
|
case SQLITE_BLOB:
|
|
return getBytes(col);
|
|
case SQLITE_NULL:
|
|
return null;
|
|
case SQLITE_TEXT:
|
|
default:
|
|
return getString(col);
|
|
}
|
|
}
|
|
|
|
public Object getObject(String col) throws SQLException {
|
|
return getObject(findColumn(col));
|
|
}
|
|
|
|
public Statement getStatement() {
|
|
return stmt;
|
|
}
|
|
|
|
public String getCursorName() throws SQLException {
|
|
return null;
|
|
}
|
|
|
|
public SQLWarning getWarnings() throws SQLException {
|
|
return null;
|
|
}
|
|
|
|
public void clearWarnings() throws SQLException {}
|
|
|
|
// ResultSetMetaData Functions //////////////////////////////////
|
|
|
|
// we do not need to check the RS is open, only that colsMeta
|
|
// is not null, done with checkCol(int).
|
|
|
|
public ResultSetMetaData getMetaData() throws SQLException {
|
|
return this;
|
|
}
|
|
|
|
public String getCatalogName(int col) throws SQLException {
|
|
return db.column_table_name(stmt.pointer, checkCol(col));
|
|
}
|
|
|
|
public String getColumnClassName(int col) throws SQLException {
|
|
checkCol(col);
|
|
return "java.lang.Object";
|
|
}
|
|
|
|
public int getColumnCount() throws SQLException {
|
|
checkCol(1);
|
|
return colsMeta.length;
|
|
}
|
|
|
|
public int getColumnDisplaySize(int col) throws SQLException {
|
|
return Integer.MAX_VALUE;
|
|
}
|
|
|
|
public String getColumnLabel(int col) throws SQLException {
|
|
return getColumnName(col);
|
|
}
|
|
|
|
public String getColumnName(int col) throws SQLException {
|
|
return db.column_name(stmt.pointer, checkCol(col));
|
|
}
|
|
|
|
public int getColumnType(int col) throws SQLException {
|
|
switch (db.column_type(stmt.pointer, checkCol(col))) {
|
|
case SQLITE_INTEGER:
|
|
return Types.INTEGER;
|
|
case SQLITE_FLOAT:
|
|
return Types.FLOAT;
|
|
case SQLITE_BLOB:
|
|
return Types.BLOB;
|
|
case SQLITE_NULL:
|
|
return Types.NULL;
|
|
case SQLITE_TEXT:
|
|
default:
|
|
return Types.VARCHAR;
|
|
}
|
|
}
|
|
|
|
public String getColumnTypeName(int col) throws SQLException {
|
|
switch (db.column_type(stmt.pointer, checkCol(col))) {
|
|
case SQLITE_INTEGER:
|
|
return "integer";
|
|
case SQLITE_FLOAT:
|
|
return "float";
|
|
case SQLITE_BLOB:
|
|
return "blob";
|
|
case SQLITE_NULL:
|
|
return "null";
|
|
case SQLITE_TEXT:
|
|
default:
|
|
return "text";
|
|
}
|
|
}
|
|
|
|
public int getPrecision(int col) throws SQLException {
|
|
return 0;
|
|
} // FIXME
|
|
|
|
public int getScale(int col) throws SQLException {
|
|
return 0;
|
|
}
|
|
|
|
public String getSchemaName(int col) throws SQLException {
|
|
return "";
|
|
}
|
|
|
|
public String getTableName(int col) throws SQLException {
|
|
return db.column_table_name(stmt.pointer, checkCol(col));
|
|
}
|
|
|
|
public int isNullable(int col) throws SQLException {
|
|
checkMeta();
|
|
return meta[checkCol(col)][1] ? columnNoNulls : columnNullable;
|
|
}
|
|
|
|
public boolean isAutoIncrement(int col) throws SQLException {
|
|
checkMeta();
|
|
return meta[checkCol(col)][2];
|
|
}
|
|
|
|
public boolean isCaseSensitive(int col) throws SQLException {
|
|
return true;
|
|
}
|
|
|
|
public boolean isCurrency(int col) throws SQLException {
|
|
return false;
|
|
}
|
|
|
|
public boolean isDefinitelyWritable(int col) throws SQLException {
|
|
return true;
|
|
} // FIXME: check db file constraints?
|
|
|
|
public boolean isReadOnly(int col) throws SQLException {
|
|
return false;
|
|
}
|
|
|
|
public boolean isSearchable(int col) throws SQLException {
|
|
return true;
|
|
}
|
|
|
|
public boolean isSigned(int col) throws SQLException {
|
|
return false;
|
|
}
|
|
|
|
public boolean isWritable(int col) throws SQLException {
|
|
return true;
|
|
}
|
|
|
|
public int getConcurrency() throws SQLException {
|
|
return CONCUR_READ_ONLY;
|
|
}
|
|
|
|
public boolean rowDeleted() throws SQLException {
|
|
return false;
|
|
}
|
|
|
|
public boolean rowInserted() throws SQLException {
|
|
return false;
|
|
}
|
|
|
|
public boolean rowUpdated() throws SQLException {
|
|
return false;
|
|
}
|
|
}
|