Skip to content

Commit 54ba30e

Browse files
committed
jdbc: support server prepared statements
Tarantool supports prepared statements since 2.3.1 that can be used by java.sql.PreparedStatement to prepare the underlying query in advance. If the driver connects to Tarantool which support prepared the statements each PreparedStatement object acts as a corresponding server prepared statement in terms of its behaviour (including expiration or invalidation of statements - i.e. after DML operations). It also makes possible to obtain statement meta data via getMetaData and getParameterMetaData without having to execute the query. This commit extends TarantoolConnection API by new `prepare` and `deallocate` methods that allow to deal with server prepared statements. It caused a small reworking of a query execution process in SQLConnection where QueryCommand abstraction was introduced. Another extension is support of PreparedStatement works in two different modes: legacy mode when prepared statements are not available (driver will send sql text + parameters as a separate queries when each execution is performed) and new mode when they are (each PreparedStatement covers the server prepared statement and sends statement id + parameters). There are a few issues when using the prepared statement now. The first, it is required to deallocate prepared statements explicitly, (no an eviction strategy on the server side) so PreparedStatement tries to perform it when close() is called. It causes next issue. The second, Tarantool does not distinguish query duplicates within one session that can cause unexpected user experience. Let's say there are two PreparedStatements that were prepared using the same query string. If one of them closes it makes another statement broken because of they reused the same session prepared statement. To overcome this issue the driver connection tracks its own statements references. When the particular statement reference count reaches zero it will safely unprepared on the server side. The third, the prepared statement is invalidated by DDL queries or the disconnection. Here, the PreparedStatement repeats behaviour of structure implemented in LUA (box.prepare()) - return an error when it runs. Tarantool does not support auto re-preparing after DDL operation at this moment. Closes: #198
1 parent 02bf9ad commit 54ba30e

12 files changed

+713
-111
lines changed

src/main/java/org/tarantool/SqlProtoUtils.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,17 @@ public static List<List<Object>> getSQLData(TarantoolPacket pack) {
3030
return (List<List<Object>>) pack.getBody().get(Key.DATA.getId());
3131
}
3232

33+
public static List<SQLMetaData> getSQLBindMetadata(TarantoolPacket pack) {
34+
return getMetadata(pack, Key.SQL_BIND_METADATA);
35+
}
36+
3337
public static List<SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
34-
List<Map<Integer, Object>> meta = (List<Map<Integer, Object>>) pack.getBody().get(Key.SQL_METADATA.getId());
38+
return getMetadata(pack, Key.SQL_METADATA);
39+
}
40+
41+
private static List<SQLMetaData> getMetadata(TarantoolPacket pack, Key targetKey) {
42+
List<Map<Integer, Object>> meta = (List<Map<Integer, Object>>) pack.getBody()
43+
.getOrDefault(targetKey.getId(), Collections.emptyList());
3544
List<SQLMetaData> values = new ArrayList<>(meta.size());
3645
for (Map<Integer, Object> item : meta) {
3746
values.add(new SQLMetaData(
@@ -42,6 +51,10 @@ public static List<SQLMetaData> getSQLMetadata(TarantoolPacket pack) {
4251
return values;
4352
}
4453

54+
public static Long getStatementId(TarantoolPacket pack) {
55+
return ((Number) pack.getBody().get(Key.SQL_STATEMENT_ID.getId())).longValue();
56+
}
57+
4558
public static Long getSQLRowCount(TarantoolPacket pack) {
4659
Map<Key, Object> info = (Map<Key, Object>) pack.getBody().get(Key.SQL_INFO.getId());
4760
Number rowCount;

src/main/java/org/tarantool/TarantoolClientImpl.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ public TarantoolClientOps<Integer, List<?>, Object, TupleTwo<List<?>, Long>> uns
763763
return unsafeSchemaOps;
764764
}
765765

766-
protected TarantoolRequest makeSqlRequest(String sql, List<Object> bind) {
766+
private TarantoolRequest makeSqlRequest(String sql, List<Object> bind) {
767767
return new TarantoolRequest(
768768
Code.EXECUTE,
769769
TarantoolRequestArgumentFactory.value(Key.SQL_TEXT),

0 commit comments

Comments
 (0)