Skip to content

Commit

Permalink
Add support for JDBC result set type
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.

Extend SQLStates constants. '24000' state was added in scope of
iterator 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
Affectes: #119, #108
  • Loading branch information
nicktorwald committed Apr 5, 2019
1 parent 06755d5 commit 30427b3
Show file tree
Hide file tree
Showing 20 changed files with 1,328 additions and 186 deletions.
46 changes: 12 additions & 34 deletions src/main/java/org/tarantool/JDBCBridge.java
Original file line number Diff line number Diff line change
@@ -1,34 +1,26 @@
package org.tarantool;

import org.tarantool.protocol.TarantoolPacket;

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

import org.tarantool.jdbc.SQLResultSet;
import org.tarantool.protocol.TarantoolPacket;

@Deprecated
public class JDBCBridge {

public static final JDBCBridge EMPTY = new JDBCBridge(Collections.<TarantoolBase.SQLMetaData>emptyList(), Collections.<List<Object>>emptyList());
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 @@ -41,9 +33,9 @@ public static int update(TarantoolConnection connection, String sql, Object ...
}

public static JDBCBridge mock(List<String> fields, List<List<Object>> values) {
List<TarantoolBase.SQLMetaData> meta = new ArrayList<TarantoolBase.SQLMetaData>(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 @@ -57,32 +49,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 + '\'' +
'}';
}
}
}
19 changes: 0 additions & 19 deletions src/main/java/org/tarantool/TarantoolBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,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 Down
36 changes: 33 additions & 3 deletions src/main/java/org/tarantool/jdbc/SQLConnection.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
import static org.tarantool.jdbc.SQLDriver.PROP_SOCKET_TIMEOUT;
import static org.tarantool.jdbc.SQLDriver.PROP_USER;

@SuppressWarnings("Since15")
/**
* Tarantool {@link Connection} implementation
*
* Supports creating {@link Statement} and {@link PreparedStatement} instances
*/
public class SQLConnection implements Connection {

private static final int UNSET_HOLDABILITY = 0;
Expand Down Expand Up @@ -91,6 +95,7 @@ public class SQLConnection implements Connection {
* to honor this timeout for the following read/write operations as well.
*
* @return Connected socket.
*
* @throws SQLException if failed.
*/
protected Socket getConnectedSocket() throws SQLException {
Expand Down Expand Up @@ -140,7 +145,9 @@ protected Socket makeSocket() {
* @param user User name.
* @param pass Password.
* @param socket Connected socket.
*
* @return Native tarantool connection.
*
* @throws IOException if failed.
*/
protected TarantoolConnection makeConnection(String user, String pass, Socket socket) throws IOException {
Expand Down Expand Up @@ -171,7 +178,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 @@ -319,6 +326,7 @@ public Statement createStatement(int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkNotClosed();
checkResultSetType(resultSetType);
checkHoldabilitySupport(resultSetHoldability);
return new SQLStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
}
Expand All @@ -329,6 +337,7 @@ public PreparedStatement prepareStatement(String sql,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
checkNotClosed();
checkResultSetType(resultSetType);
checkHoldabilitySupport(resultSetHoldability);
return new SQLPreparedStatement(this, sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
Expand Down Expand Up @@ -540,12 +549,32 @@ private void handleException(Exception e) {
}
}

/**
* Checks wether <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>holdability</code> is supported
*
* @param holdability param to be checked
*
* @throws SQLFeatureNotSupportedException param is not supported
* @throws SQLNonTransientException param has invalid value
* @throws SQLNonTransientException param has invalid value
*/
private void checkHoldabilitySupport(int holdability) throws SQLException {
if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT
Expand All @@ -562,6 +591,7 @@ private void checkHoldabilitySupport(int holdability) throws SQLException {
*
* @param sql SQL Text.
* @param params Parameters of the SQL statement.
*
* @return Formatted error message.
*/
private static String formatError(String sql, Object... params) {
Expand Down
15 changes: 8 additions & 7 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 @@ -880,7 +880,8 @@ 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
Expand Down
Loading

0 comments on commit 30427b3

Please sign in to comment.