Skip to content

Commit 5b6524e

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 supports the prepared statements then each PreparedStatement object acts as a corresponding server prepared statement in terms of its behaviour (including expiration or invalidation of statements - i.e. after DDL 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 that works in two different modes now: legacy mode when server 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 supported (each PreparedStatement covers the server prepared statement and sends statement id + parameters). There are a few issues on 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() method is called. It causes the second 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 it on the server side. The third, the prepared statement is invalidated by DDL queries or the disconnection. Tarantool does not support auto re-preparing after DDL operation at this moment, so it requires to be re-prepared for all cached statements. Here, the PreparedStatement repeats behaviour of Lua implementation for `box` module - returns an error when it expired or deleted. Closes: #198
1 parent 02bf9ad commit 5b6524e

12 files changed

+732
-111
lines changed

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

Lines changed: 14 additions & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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)