Skip to content

Commit

Permalink
Add support for a result set type and concurrency
Browse files Browse the repository at this point in the history
Provide support for FORWARD_ONLY and INSENSITIVE scroll types. Now
statements as well as theirs resultSets can be built using a forward
only iterator or full implemented insensitive iterator. To achieve this
iteration logic was extracted into two separate classes to support two
scroll types respectively. This is a cross-cutting support through
SQLMetadata, SQLConnection, SQL(Prepared)Statement, SQLResultSet.

Add support for READ_ONLY concurrency level for a result set.

Extend SQLStates constants in scope of cursors and query execution.
0100E and 02000 for query results; 24000 for cursor iteration support.

Add missed implementation of a closing for SQLStatement and
SQLResultSet.

Deprecate JDBCBridge. This redundant class should be removed completely
in scope of another task. Mapping of field labels was moved to
SQLResultSet.

Closes: #85, #86
Affects: #119, #108
  • Loading branch information
nicktorwald committed Apr 17, 2019
1 parent af74a8c commit 122be31
Show file tree
Hide file tree
Showing 23 changed files with 1,635 additions and 228 deletions.
38 changes: 9 additions & 29 deletions src/main/java/org/tarantool/JDBCBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,23 @@

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;

@Deprecated
public class JDBCBridge {

public static final JDBCBridge EMPTY = new JDBCBridge(Collections.emptyList(), Collections.emptyList());

final List<TarantoolBase.SQLMetaData> sqlMetadata;
final Map<String, Integer> columnsByName;
final List<SqlProtoUtils.SQLMetaData> sqlMetadata;
final List<List<Object>> rows;

protected JDBCBridge(TarantoolPacket pack) {
this(SqlProtoUtils.getSQLMetadata(pack), SqlProtoUtils.getSQLData(pack));
}

protected JDBCBridge(List<TarantoolBase.SQLMetaData> sqlMetadata, List<List<Object>> rows) {
protected JDBCBridge(List<SqlProtoUtils.SQLMetaData> sqlMetadata, List<List<Object>> rows) {
this.sqlMetadata = sqlMetadata;
this.rows = rows;
columnsByName = new LinkedHashMap<String, Integer>((int) Math.ceil(sqlMetadata.size() / 0.75), 0.75f);
for (int i = 0; i < sqlMetadata.size(); i++) {
columnsByName.put(sqlMetadata.get(i).getName(), i + 1);
}
}

public static JDBCBridge query(TarantoolConnection connection, String sql, Object... params) {
Expand All @@ -48,9 +41,9 @@ public static int update(TarantoolConnection connection, String sql, Object... p
* @return bridge
*/
public static JDBCBridge mock(List<String> fields, List<List<Object>> values) {
List<TarantoolBase.SQLMetaData> meta = new ArrayList<>(fields.size());
List<SqlProtoUtils.SQLMetaData> meta = new ArrayList<>(fields.size());
for (String field : fields) {
meta.add(new TarantoolBase.SQLMetaData(field));
meta.add(new SqlProtoUtils.SQLMetaData(field));
}
return new JDBCBridge(meta, values);
}
Expand All @@ -73,31 +66,18 @@ public static Object execute(TarantoolConnection connection, String sql, Object.
return rowCount.intValue();
}

public String getColumnName(int columnIndex) {
return columnIndex > sqlMetadata.size() ? null : sqlMetadata.get(columnIndex - 1).getName();
}

public Integer getColumnIndex(String columnName) {
return columnsByName.get(columnName);
}

public int getColumnCount() {
return columnsByName.size();
}

public ListIterator<List<Object>> iterator() {
return rows.listIterator();
public List<List<Object>> getRows() {
return rows;
}

public int size() {
return rows.size();
public List<SqlProtoUtils.SQLMetaData> getSqlMetadata() {
return sqlMetadata;
}

@Override
public String toString() {
return "JDBCBridge{" +
"sqlMetadata=" + sqlMetadata +
", columnsByName=" + columnsByName +
", rows=" + rows +
'}';
}
Expand Down
27 changes: 23 additions & 4 deletions src/main/java/org/tarantool/SqlProtoUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static List<Map<String, Object>> readSqlResult(TarantoolPacket pack) {
List<List<?>> data = (List<List<?>>) pack.getBody().get(Key.DATA.getId());

List<Map<String, Object>> values = new ArrayList<>(data.size());
List<TarantoolBase.SQLMetaData> metaData = getSQLMetadata(pack);
List<SQLMetaData> metaData = getSQLMetadata(pack);
for (List row : data) {
LinkedHashMap<String, Object> value = new LinkedHashMap<>();
for (int i = 0; i < row.size(); i++) {
Expand All @@ -27,11 +27,11 @@ public static List<List<Object>> getSQLData(TarantoolPacket pack) {
return (List<List<Object>>) pack.getBody().get(Key.DATA.getId());
}

public static List<TarantoolBase.SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
public static List<SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
List<Map<Integer, Object>> meta = (List<Map<Integer, Object>>) pack.getBody().get(Key.SQL_METADATA.getId());
List<TarantoolBase.SQLMetaData> values = new ArrayList<TarantoolBase.SQLMetaData>(meta.size());
List<SQLMetaData> values = new ArrayList<>(meta.size());
for (Map<Integer, Object> c : meta) {
values.add(new TarantoolBase.SQLMetaData((String) c.get(Key.SQL_FIELD_NAME.getId())));
values.add(new SQLMetaData((String) c.get(Key.SQL_FIELD_NAME.getId())));
}
return values;
}
Expand All @@ -44,4 +44,23 @@ public static Long getSqlRowCount(TarantoolPacket pack) {
}
return null;
}

public static class SQLMetaData {
protected String name;

public SQLMetaData(String name) {
this.name = name;
}

public String getName() {
return name;
}

@Override
public String toString() {
return "SQLMetaData{" +
"name='" + name + '\'' +
'}';
}
}
}
21 changes: 1 addition & 20 deletions src/main/java/org/tarantool/TarantoolBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,6 @@ public TarantoolBase(String username, String password, Socket socket) {
}
}

protected static class SQLMetaData {
protected String name;

public SQLMetaData(String name) {
this.name = name;
}

public String getName() {
return name;
}

@Override
public String toString() {
return "SQLMetaData{" +
"name='" + name + '\'' +
'}';
}
}

protected TarantoolException serverError(long code, Object error) {
return new TarantoolException(code, error instanceof String ? (String) error : new String((byte[]) error));
}
Expand All @@ -60,7 +41,7 @@ protected void closeChannel(SocketChannel channel) {
try {
channel.close();
} catch (IOException ignored) {
// No-op
// no-op
}
}
}
Expand Down
66 changes: 63 additions & 3 deletions src/main/java/org/tarantool/jdbc/SQLConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
import java.util.Properties;
import java.util.concurrent.Executor;

/**
* Tarantool {@link Connection} implementation.
* <p>
* Supports creating {@link Statement} and {@link PreparedStatement} instances
*/
public class SQLConnection implements Connection {

private static final int UNSET_HOLDABILITY = 0;
Expand Down Expand Up @@ -171,7 +176,7 @@ public Statement createStatement(int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkNotClosed();
checkHoldabilitySupport(resultSetHoldability);
checkStatementParams(resultSetType, resultSetConcurrency, resultSetHoldability);
return new SQLStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
}

Expand All @@ -192,7 +197,7 @@ public PreparedStatement prepareStatement(String sql,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkNotClosed();
checkHoldabilitySupport(resultSetHoldability);
checkStatementParams(resultSetType, resultSetConcurrency, resultSetHoldability);
return new SQLPreparedStatement(this, sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}

Expand Down Expand Up @@ -242,7 +247,7 @@ public String nativeSQL(String sql) throws SQLException {

@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
if (autoCommit == false) {
if (!autoCommit) {
throw new SQLFeatureNotSupportedException();
}
}
Expand Down Expand Up @@ -589,6 +594,61 @@ private void handleException(Exception e) {
}
}

/**
* Checks all params required to make statements.
*
* @param resultSetType scroll type
* @param resultSetConcurrency concurrency level
* @param resultSetHoldability holdability type
*
* @throws SQLFeatureNotSupportedException if any param is not supported
* @throws SQLNonTransientException if any param has an invalid value
*/
private void checkStatementParams(int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkResultSetType(resultSetType);
checkResultSetConcurrency(resultSetType, resultSetConcurrency);
checkHoldabilitySupport(resultSetHoldability);
}

/**
* Checks whether <code>resultSetType</code> is supported.
*
* @param resultSetType param to be checked
*
* @throws SQLFeatureNotSupportedException param is not supported
* @throws SQLNonTransientException param has invalid value
*/
private void checkResultSetType(int resultSetType) throws SQLException {
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY &&
resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE &&
resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
throw new SQLNonTransientException("", SQLStates.INVALID_PARAMETER_VALUE.getSqlState());
}
if (!getMetaData().supportsResultSetType(resultSetType)) {
throw new SQLFeatureNotSupportedException();
}
}

/**
* Checks whether <code>resultSetType</code> is supported.
*
* @param resultSetConcurrency param to be checked
*
* @throws SQLFeatureNotSupportedException param is not supported
* @throws SQLNonTransientException param has invalid value
*/
private void checkResultSetConcurrency(int resultSetType, int resultSetConcurrency) throws SQLException {
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY &&
resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
throw new SQLNonTransientException("", SQLStates.INVALID_PARAMETER_VALUE.getSqlState());
}
if (!getMetaData().supportsResultSetConcurrency(resultSetType, resultSetConcurrency)) {
throw new SQLFeatureNotSupportedException();
}
}

/**
* Checks whether <code>holdability</code> is supported.
*
Expand Down
17 changes: 9 additions & 8 deletions src/main/java/org/tarantool/jdbc/SQLDatabaseMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,17 @@ public SQLNullResultSet(JDBCBridge bridge, SQLStatement ownerStatement) throws S
}

@Override
protected Object getRaw(int columnIndex) {
return columnIndex > getCurrentRow().size() ? null : getCurrentRow().get(columnIndex - 1);
protected Object getRaw(int columnIndex) throws SQLException {
List<Object> row = getCurrentRow();
return columnIndex > row.size() ? null : row.get(columnIndex - 1);
}

@Override
protected Integer getColumnIndex(String columnLabel) {
Integer idx = super.getColumnIndex(columnLabel);
return idx == null ? Integer.MAX_VALUE : idx;
protected int findColumnIndex(String columnLabel) throws SQLException {
int index = super.findColumnIndex(columnLabel);
return index == 0 ? Integer.MAX_VALUE : index;
}


}

public SQLDatabaseMetadata(SQLConnection connection) {
Expand Down Expand Up @@ -908,12 +908,13 @@ public ResultSet getIndexInfo(String catalog, String schema, String table, boole

@Override
public boolean supportsResultSetType(int type) throws SQLException {
return false;
return type == ResultSet.TYPE_FORWARD_ONLY ||
type == ResultSet.TYPE_SCROLL_INSENSITIVE;
}

@Override
public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
return false;
return supportsResultSetType(type) && concurrency == ResultSet.CONCUR_READ_ONLY;
}

@Override
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/org/tarantool/jdbc/SQLPreparedStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,7 @@ private void setParameter(int parameterIndex, Object value) throws SQLException
@Override
public boolean execute() throws SQLException {
checkNotClosed();
discardLastResults();
return handleResult(connection.execute(sql, getParams()));
return executeInternal(sql, getParams());
}

@Override
Expand Down
Loading

0 comments on commit 122be31

Please sign in to comment.