Skip to content

Commit 62ee0ee

Browse files
committed
Add support for a result set type and concurrency
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
1 parent 7cdb58c commit 62ee0ee

23 files changed

+1653
-247
lines changed

Diff for: src/main/java/org/tarantool/JDBCBridge.java

+9-29
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,23 @@
44

55
import java.util.ArrayList;
66
import java.util.Collections;
7-
import java.util.LinkedHashMap;
87
import java.util.List;
9-
import java.util.ListIterator;
10-
import java.util.Map;
118

9+
@Deprecated
1210
public class JDBCBridge {
1311

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

16-
final List<TarantoolBase.SQLMetaData> sqlMetadata;
17-
final Map<String, Integer> columnsByName;
14+
final List<SqlProtoUtils.SQLMetaData> sqlMetadata;
1815
final List<List<Object>> rows;
1916

2017
protected JDBCBridge(TarantoolPacket pack) {
2118
this(SqlProtoUtils.getSQLMetadata(pack), SqlProtoUtils.getSQLData(pack));
2219
}
2320

24-
protected JDBCBridge(List<TarantoolBase.SQLMetaData> sqlMetadata, List<List<Object>> rows) {
21+
protected JDBCBridge(List<SqlProtoUtils.SQLMetaData> sqlMetadata, List<List<Object>> rows) {
2522
this.sqlMetadata = sqlMetadata;
2623
this.rows = rows;
27-
columnsByName = new LinkedHashMap<String, Integer>((int) Math.ceil(sqlMetadata.size() / 0.75), 0.75f);
28-
for (int i = 0; i < sqlMetadata.size(); i++) {
29-
columnsByName.put(sqlMetadata.get(i).getName(), i + 1);
30-
}
3124
}
3225

3326
public static JDBCBridge query(TarantoolConnection connection, String sql, Object... params) {
@@ -48,9 +41,9 @@ public static int update(TarantoolConnection connection, String sql, Object... p
4841
* @return bridge
4942
*/
5043
public static JDBCBridge mock(List<String> fields, List<List<Object>> values) {
51-
List<TarantoolBase.SQLMetaData> meta = new ArrayList<>(fields.size());
44+
List<SqlProtoUtils.SQLMetaData> meta = new ArrayList<>(fields.size());
5245
for (String field : fields) {
53-
meta.add(new TarantoolBase.SQLMetaData(field));
46+
meta.add(new SqlProtoUtils.SQLMetaData(field));
5447
}
5548
return new JDBCBridge(meta, values);
5649
}
@@ -73,31 +66,18 @@ public static Object execute(TarantoolConnection connection, String sql, Object.
7366
return rowCount.intValue();
7467
}
7568

76-
public String getColumnName(int columnIndex) {
77-
return columnIndex > sqlMetadata.size() ? null : sqlMetadata.get(columnIndex - 1).getName();
78-
}
79-
80-
public Integer getColumnIndex(String columnName) {
81-
return columnsByName.get(columnName);
82-
}
83-
84-
public int getColumnCount() {
85-
return columnsByName.size();
86-
}
87-
88-
public ListIterator<List<Object>> iterator() {
89-
return rows.listIterator();
69+
public List<List<Object>> getRows() {
70+
return rows;
9071
}
9172

92-
public int size() {
93-
return rows.size();
73+
public List<SqlProtoUtils.SQLMetaData> getSqlMetadata() {
74+
return sqlMetadata;
9475
}
9576

9677
@Override
9778
public String toString() {
9879
return "JDBCBridge{" +
9980
"sqlMetadata=" + sqlMetadata +
100-
", columnsByName=" + columnsByName +
10181
", rows=" + rows +
10282
'}';
10383
}

Diff for: src/main/java/org/tarantool/SqlProtoUtils.java

+23-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public static List<Map<String, Object>> readSqlResult(TarantoolPacket pack) {
1212
List<List<?>> data = (List<List<?>>) pack.getBody().get(Key.DATA.getId());
1313

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

30-
public static List<TarantoolBase.SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
30+
public static List<SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
3131
List<Map<Integer, Object>> meta = (List<Map<Integer, Object>>) pack.getBody().get(Key.SQL_METADATA.getId());
32-
List<TarantoolBase.SQLMetaData> values = new ArrayList<TarantoolBase.SQLMetaData>(meta.size());
32+
List<SQLMetaData> values = new ArrayList<>(meta.size());
3333
for (Map<Integer, Object> c : meta) {
34-
values.add(new TarantoolBase.SQLMetaData((String) c.get(Key.SQL_FIELD_NAME.getId())));
34+
values.add(new SQLMetaData((String) c.get(Key.SQL_FIELD_NAME.getId())));
3535
}
3636
return values;
3737
}
@@ -44,4 +44,23 @@ public static Long getSqlRowCount(TarantoolPacket pack) {
4444
}
4545
return null;
4646
}
47+
48+
public static class SQLMetaData {
49+
protected String name;
50+
51+
public SQLMetaData(String name) {
52+
this.name = name;
53+
}
54+
55+
public String getName() {
56+
return name;
57+
}
58+
59+
@Override
60+
public String toString() {
61+
return "SQLMetaData{" +
62+
"name='" + name + '\'' +
63+
'}';
64+
}
65+
}
4766
}

Diff for: src/main/java/org/tarantool/TarantoolBase.java

+1-20
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,6 @@ public TarantoolBase(String username, String password, Socket socket) {
3232
}
3333
}
3434

35-
protected static class SQLMetaData {
36-
protected String name;
37-
38-
public SQLMetaData(String name) {
39-
this.name = name;
40-
}
41-
42-
public String getName() {
43-
return name;
44-
}
45-
46-
@Override
47-
public String toString() {
48-
return "SQLMetaData{" +
49-
"name='" + name + '\'' +
50-
'}';
51-
}
52-
}
53-
5435
protected TarantoolException serverError(long code, Object error) {
5536
return new TarantoolException(code, error instanceof String ? (String) error : new String((byte[]) error));
5637
}
@@ -60,7 +41,7 @@ protected void closeChannel(SocketChannel channel) {
6041
try {
6142
channel.close();
6243
} catch (IOException ignored) {
63-
// No-op
44+
// no-op
6445
}
6546
}
6647
}

Diff for: src/main/java/org/tarantool/jdbc/SQLConnection.java

+63-4
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@
4040
import java.util.Properties;
4141
import java.util.concurrent.Executor;
4242

43-
@SuppressWarnings("Since15")
43+
/**
44+
* Tarantool {@link Connection} implementation.
45+
* <p>
46+
* Supports creating {@link Statement} and {@link PreparedStatement} instances
47+
*/
4448
public class SQLConnection implements Connection {
4549

4650
private static final int UNSET_HOLDABILITY = 0;
@@ -170,7 +174,7 @@ public Statement createStatement(int resultSetType,
170174
int resultSetConcurrency,
171175
int resultSetHoldability) throws SQLException {
172176
checkNotClosed();
173-
checkHoldabilitySupport(resultSetHoldability);
177+
checkStatementParams(resultSetType, resultSetConcurrency, resultSetHoldability);
174178
return new SQLStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
175179
}
176180

@@ -191,7 +195,7 @@ public PreparedStatement prepareStatement(String sql,
191195
int resultSetConcurrency,
192196
int resultSetHoldability) throws SQLException {
193197
checkNotClosed();
194-
checkHoldabilitySupport(resultSetHoldability);
198+
checkStatementParams(resultSetType, resultSetConcurrency, resultSetHoldability);
195199
return new SQLPreparedStatement(this, sql, resultSetType, resultSetConcurrency, resultSetHoldability);
196200
}
197201

@@ -236,7 +240,7 @@ public String nativeSQL(String sql) throws SQLException {
236240

237241
@Override
238242
public void setAutoCommit(boolean autoCommit) throws SQLException {
239-
if (autoCommit == false) {
243+
if (!autoCommit) {
240244
throw new SQLFeatureNotSupportedException();
241245
}
242246
}
@@ -552,6 +556,61 @@ private void handleException(Exception e) {
552556
}
553557
}
554558

559+
/**
560+
* Checks all params required to make statements.
561+
*
562+
* @param resultSetType scroll type
563+
* @param resultSetConcurrency concurrency level
564+
* @param resultSetHoldability holdability type
565+
*
566+
* @throws SQLFeatureNotSupportedException if any param is not supported
567+
* @throws SQLNonTransientException if any param has an invalid value
568+
*/
569+
private void checkStatementParams(int resultSetType,
570+
int resultSetConcurrency,
571+
int resultSetHoldability) throws SQLException {
572+
checkResultSetType(resultSetType);
573+
checkResultSetConcurrency(resultSetType, resultSetConcurrency);
574+
checkHoldabilitySupport(resultSetHoldability);
575+
}
576+
577+
/**
578+
* Checks whether <code>resultSetType</code> is supported.
579+
*
580+
* @param resultSetType param to be checked
581+
*
582+
* @throws SQLFeatureNotSupportedException param is not supported
583+
* @throws SQLNonTransientException param has invalid value
584+
*/
585+
private void checkResultSetType(int resultSetType) throws SQLException {
586+
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY &&
587+
resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE &&
588+
resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
589+
throw new SQLNonTransientException("", SQLStates.INVALID_PARAMETER_VALUE.getSqlState());
590+
}
591+
if (!getMetaData().supportsResultSetType(resultSetType)) {
592+
throw new SQLFeatureNotSupportedException();
593+
}
594+
}
595+
596+
/**
597+
* Checks whether <code>resultSetType</code> is supported.
598+
*
599+
* @param resultSetConcurrency param to be checked
600+
*
601+
* @throws SQLFeatureNotSupportedException param is not supported
602+
* @throws SQLNonTransientException param has invalid value
603+
*/
604+
private void checkResultSetConcurrency(int resultSetType, int resultSetConcurrency) throws SQLException {
605+
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY &&
606+
resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
607+
throw new SQLNonTransientException("", SQLStates.INVALID_PARAMETER_VALUE.getSqlState());
608+
}
609+
if (!getMetaData().supportsResultSetConcurrency(resultSetType, resultSetConcurrency)) {
610+
throw new SQLFeatureNotSupportedException();
611+
}
612+
}
613+
555614
/**
556615
* Checks whether <code>holdability</code> is supported.
557616
*

Diff for: src/main/java/org/tarantool/jdbc/SQLDatabaseMetadata.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@ public SQLNullResultSet(JDBCBridge bridge, SQLStatement ownerStatement) throws S
3636
}
3737

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

4344
@Override
44-
protected Integer getColumnIndex(String columnLabel) {
45-
Integer idx = super.getColumnIndex(columnLabel);
46-
return idx == null ? Integer.MAX_VALUE : idx;
45+
protected int findColumnIndex(String columnLabel) throws SQLException {
46+
int index = super.findColumnIndex(columnLabel);
47+
return index == 0 ? Integer.MAX_VALUE : index;
4748
}
4849

49-
5050
}
5151

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

909909
@Override
910910
public boolean supportsResultSetType(int type) throws SQLException {
911-
return false;
911+
return type == ResultSet.TYPE_FORWARD_ONLY ||
912+
type == ResultSet.TYPE_SCROLL_INSENSITIVE;
912913
}
913914

914915
@Override
915916
public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
916-
return false;
917+
return supportsResultSetType(type) && concurrency == ResultSet.CONCUR_READ_ONLY;
917918
}
918919

919920
@Override

Diff for: src/main/java/org/tarantool/jdbc/SQLPreparedStatement.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,7 @@ private void setParameter(int parameterIndex, Object value) throws SQLException
239239
@Override
240240
public boolean execute() throws SQLException {
241241
checkNotClosed();
242-
discardLastResults();
243-
return handleResult(connection.execute(sql, getParams()));
242+
return executeInternal(sql, getParams());
244243
}
245244

246245
@Override

0 commit comments

Comments
 (0)