Skip to content

Commit bf8eb95

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 06755d5 commit bf8eb95

23 files changed

+1531
-209
lines changed

src/main/java/org/tarantool/JDBCBridge.java

+12-34
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,26 @@
11
package org.tarantool;
22

3+
import org.tarantool.protocol.TarantoolPacket;
4+
35
import java.util.ArrayList;
46
import java.util.Collections;
5-
import java.util.LinkedHashMap;
67
import java.util.List;
7-
import java.util.ListIterator;
8-
import java.util.Map;
9-
10-
import org.tarantool.jdbc.SQLResultSet;
11-
import org.tarantool.protocol.TarantoolPacket;
128

9+
@Deprecated
1310
public class JDBCBridge {
1411

15-
public static final JDBCBridge EMPTY = new JDBCBridge(Collections.<TarantoolBase.SQLMetaData>emptyList(), Collections.<List<Object>>emptyList());
12+
public static final JDBCBridge EMPTY = new JDBCBridge(Collections.emptyList(), Collections.emptyList());
1613

17-
final List<TarantoolBase.SQLMetaData> sqlMetadata;
18-
final Map<String,Integer> columnsByName;
14+
final List<SqlProtoUtils.SQLMetaData> sqlMetadata;
1915
final List<List<Object>> rows;
2016

2117
protected JDBCBridge(TarantoolPacket pack) {
2218
this(SqlProtoUtils.getSQLMetadata(pack), SqlProtoUtils.getSQLData(pack));
2319
}
2420

25-
protected JDBCBridge(List<TarantoolBase.SQLMetaData> sqlMetadata, List<List<Object>> rows) {
21+
protected JDBCBridge(List<SqlProtoUtils.SQLMetaData> sqlMetadata, List<List<Object>> rows) {
2622
this.sqlMetadata = sqlMetadata;
2723
this.rows = rows;
28-
columnsByName = new LinkedHashMap<String, Integer>((int) Math.ceil(sqlMetadata.size() / 0.75), 0.75f);
29-
for (int i = 0; i < sqlMetadata.size(); i++) {
30-
columnsByName.put(sqlMetadata.get(i).getName(), i + 1);
31-
}
3224
}
3325

3426
public static JDBCBridge query(TarantoolConnection connection, String sql, Object ... params) {
@@ -41,9 +33,9 @@ public static int update(TarantoolConnection connection, String sql, Object ...
4133
}
4234

4335
public static JDBCBridge mock(List<String> fields, List<List<Object>> values) {
44-
List<TarantoolBase.SQLMetaData> meta = new ArrayList<TarantoolBase.SQLMetaData>(fields.size());
36+
List<SqlProtoUtils.SQLMetaData> meta = new ArrayList<>(fields.size());
4537
for(String field : fields) {
46-
meta.add(new TarantoolBase.SQLMetaData(field));
38+
meta.add(new SqlProtoUtils.SQLMetaData(field));
4739
}
4840
return new JDBCBridge(meta, values);
4941
}
@@ -57,32 +49,18 @@ public static Object execute(TarantoolConnection connection, String sql, Object
5749
return rowCount.intValue();
5850
}
5951

60-
61-
public String getColumnName(int columnIndex) {
62-
return columnIndex > sqlMetadata.size() ? null : sqlMetadata.get(columnIndex - 1).getName();
63-
}
64-
65-
public Integer getColumnIndex(String columnName) {
66-
return columnsByName.get(columnName);
67-
}
68-
69-
public int getColumnCount() {
70-
return columnsByName.size();
71-
}
72-
73-
public ListIterator<List<Object>> iterator() {
74-
return rows.listIterator();
52+
public List<List<Object>> getRows() {
53+
return rows;
7554
}
7655

77-
public int size() {
78-
return rows.size();
56+
public List<SqlProtoUtils.SQLMetaData> getSqlMetadata() {
57+
return sqlMetadata;
7958
}
8059

8160
@Override
8261
public String toString() {
8362
return "JDBCBridge{" +
8463
"sqlMetadata=" + sqlMetadata +
85-
", columnsByName=" + columnsByName +
8664
", rows=" + rows +
8765
'}';
8866
}

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
}

src/main/java/org/tarantool/TarantoolBase.java

-19
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,6 @@ public TarantoolBase(String username, String password, Socket socket) {
3131
}
3232
}
3333

34-
protected static class SQLMetaData {
35-
protected String name;
36-
37-
public SQLMetaData(String name) {
38-
this.name = name;
39-
}
40-
41-
public String getName() {
42-
return name;
43-
}
44-
45-
@Override
46-
public String toString() {
47-
return "SQLMetaData{" +
48-
"name='" + name + '\'' +
49-
'}';
50-
}
51-
}
52-
5334
protected TarantoolException serverError(long code, Object error) {
5435
return new TarantoolException(code, error instanceof String ? (String) error : new String((byte[]) error));
5536
}

src/main/java/org/tarantool/jdbc/SQLConnection.java

+69-5
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@
4040
import static org.tarantool.jdbc.SQLDriver.PROP_SOCKET_TIMEOUT;
4141
import static org.tarantool.jdbc.SQLDriver.PROP_USER;
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;
@@ -91,6 +95,7 @@ public class SQLConnection implements Connection {
9195
* to honor this timeout for the following read/write operations as well.
9296
*
9397
* @return Connected socket.
98+
*
9499
* @throws SQLException if failed.
95100
*/
96101
protected Socket getConnectedSocket() throws SQLException {
@@ -140,7 +145,9 @@ protected Socket makeSocket() {
140145
* @param user User name.
141146
* @param pass Password.
142147
* @param socket Connected socket.
148+
*
143149
* @return Native tarantool connection.
150+
*
144151
* @throws IOException if failed.
145152
*/
146153
protected TarantoolConnection makeConnection(String user, String pass, Socket socket) throws IOException {
@@ -171,7 +178,7 @@ public String nativeSQL(String sql) throws SQLException {
171178

172179
@Override
173180
public void setAutoCommit(boolean autoCommit) throws SQLException {
174-
if (autoCommit == false) {
181+
if (!autoCommit) {
175182
throw new SQLFeatureNotSupportedException();
176183
}
177184
}
@@ -319,7 +326,7 @@ public Statement createStatement(int resultSetType,
319326
int resultSetConcurrency,
320327
int resultSetHoldability) throws SQLException {
321328
checkNotClosed();
322-
checkHoldabilitySupport(resultSetHoldability);
329+
checkStatementParams(resultSetType, resultSetConcurrency, resultSetHoldability);
323330
return new SQLStatement(this, resultSetType, resultSetConcurrency, resultSetHoldability);
324331
}
325332

@@ -329,7 +336,7 @@ public PreparedStatement prepareStatement(String sql,
329336
int resultSetConcurrency,
330337
int resultSetHoldability) throws SQLException {
331338
checkNotClosed();
332-
checkHoldabilitySupport(resultSetHoldability);
339+
checkStatementParams(resultSetType, resultSetConcurrency, resultSetHoldability);
333340
return new SQLPreparedStatement(this, sql, resultSetType, resultSetConcurrency, resultSetHoldability);
334341
}
335342

@@ -540,12 +547,68 @@ private void handleException(Exception e) {
540547
}
541548
}
542549

550+
/**
551+
* Checks all params required to make statements
552+
*
553+
* @param resultSetType scroll type
554+
* @param resultSetConcurrency concurrency level
555+
* @param resultSetHoldability holdability type
556+
*
557+
* @throws SQLFeatureNotSupportedException if any param is not supported
558+
* @throws SQLNonTransientException if any param has an invalid value
559+
*/
560+
private void checkStatementParams(int resultSetType,
561+
int resultSetConcurrency,
562+
int resultSetHoldability) throws SQLException {
563+
checkResultSetType(resultSetType);
564+
checkResultSetConcurrency(resultSetType, resultSetConcurrency);
565+
checkHoldabilitySupport(resultSetHoldability);
566+
}
567+
568+
/**
569+
* Checks whether <code>resultSetType</code> is supported
570+
*
571+
* @param resultSetType param to be checked
572+
*
573+
* @throws SQLFeatureNotSupportedException param is not supported
574+
* @throws SQLNonTransientException param has invalid value
575+
*/
576+
private void checkResultSetType(int resultSetType) throws SQLException {
577+
if (resultSetType != ResultSet.TYPE_FORWARD_ONLY
578+
&& resultSetType != ResultSet.TYPE_SCROLL_INSENSITIVE
579+
&& resultSetType != ResultSet.TYPE_SCROLL_SENSITIVE) {
580+
throw new SQLNonTransientException("", SQLStates.INVALID_PARAMETER_VALUE.getSqlState());
581+
}
582+
if (!getMetaData().supportsResultSetType(resultSetType)) {
583+
throw new SQLFeatureNotSupportedException();
584+
}
585+
}
586+
587+
/**
588+
* Checks whether <code>resultSetType</code> is supported
589+
*
590+
* @param resultSetConcurrency param to be checked
591+
*
592+
* @throws SQLFeatureNotSupportedException param is not supported
593+
* @throws SQLNonTransientException param has invalid value
594+
*/
595+
private void checkResultSetConcurrency(int resultSetType, int resultSetConcurrency) throws SQLException {
596+
if (resultSetConcurrency != ResultSet.CONCUR_READ_ONLY
597+
&& resultSetConcurrency != ResultSet.CONCUR_UPDATABLE) {
598+
throw new SQLNonTransientException("", SQLStates.INVALID_PARAMETER_VALUE.getSqlState());
599+
}
600+
if (!getMetaData().supportsResultSetConcurrency(resultSetType, resultSetConcurrency)) {
601+
throw new SQLFeatureNotSupportedException();
602+
}
603+
}
604+
543605
/**
544606
* Checks whether <code>holdability</code> is supported
545607
*
546608
* @param holdability param to be checked
609+
*
547610
* @throws SQLFeatureNotSupportedException param is not supported
548-
* @throws SQLNonTransientException param has invalid value
611+
* @throws SQLNonTransientException param has invalid value
549612
*/
550613
private void checkHoldabilitySupport(int holdability) throws SQLException {
551614
if (holdability != ResultSet.CLOSE_CURSORS_AT_COMMIT
@@ -562,6 +625,7 @@ private void checkHoldabilitySupport(int holdability) throws SQLException {
562625
*
563626
* @param sql SQL Text.
564627
* @param params Parameters of the SQL statement.
628+
*
565629
* @return Formatted error message.
566630
*/
567631
private static String formatError(String sql, Object... params) {

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) {
@@ -880,12 +880,13 @@ public ResultSet getIndexInfo(String catalog, String schema, String table, boole
880880

881881
@Override
882882
public boolean supportsResultSetType(int type) throws SQLException {
883-
return false;
883+
return type == ResultSet.TYPE_FORWARD_ONLY
884+
|| type == ResultSet.TYPE_SCROLL_INSENSITIVE;
884885
}
885886

886887
@Override
887888
public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException {
888-
return false;
889+
return supportsResultSetType(type) && concurrency == ResultSet.CONCUR_READ_ONLY;
889890
}
890891

891892
@Override

src/main/java/org/tarantool/jdbc/SQLPreparedStatement.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,7 @@ private void setParameter(int parameterIndex, Object value) throws SQLException
181181
@Override
182182
public boolean execute() throws SQLException {
183183
checkNotClosed();
184-
discardLastResults();
185-
return handleResult(connection.execute(sql, getParams()));
184+
return executeInternal(sql, getParams());
186185
}
187186

188187
@Override

0 commit comments

Comments
 (0)