Skip to content

Commit c9c1798

Browse files
committed
Added auto batch mode
1 parent 265022f commit c9c1798

File tree

4 files changed

+95
-40
lines changed

4 files changed

+95
-40
lines changed

jdbc/src/main/java/tech/ydb/jdbc/context/YdbContext.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@
88
import java.util.concurrent.atomic.AtomicInteger;
99
import java.util.logging.Level;
1010
import java.util.logging.Logger;
11+
import java.util.stream.Collectors;
1112

1213
import com.google.common.cache.Cache;
1314
import com.google.common.cache.CacheBuilder;
1415

16+
import tech.ydb.core.Result;
1517
import tech.ydb.core.UnexpectedResultException;
1618
import tech.ydb.core.grpc.GrpcTransport;
1719
import tech.ydb.core.grpc.GrpcTransportBuilder;
@@ -34,8 +36,11 @@
3436
import tech.ydb.scheme.SchemeClient;
3537
import tech.ydb.table.SessionRetryContext;
3638
import tech.ydb.table.TableClient;
39+
import tech.ydb.table.description.TableColumn;
40+
import tech.ydb.table.description.TableDescription;
3741
import tech.ydb.table.impl.PooledTableClient;
3842
import tech.ydb.table.rpc.grpc.GrpcTableRpc;
43+
import tech.ydb.table.settings.DescribeTableSettings;
3944
import tech.ydb.table.settings.PrepareDataQuerySettings;
4045
import tech.ydb.table.settings.RequestSettings;
4146
import tech.ydb.table.values.Type;
@@ -271,17 +276,44 @@ public YdbQuery findOrParseYdbQuery(String sql) throws SQLException {
271276
}
272277

273278
public YdbPreparedQuery findOrPrepareParams(YdbQuery query, YdbPrepareMode mode) throws SQLException {
279+
if (query.getYqlBatcher() != null && mode == YdbPrepareMode.AUTO) {
280+
Map<String, Type> types = queryParamsCache.getIfPresent(query.getOriginQuery());
281+
if (types == null) {
282+
String tableName = query.getYqlBatcher().getTableName();
283+
String tablePath = tableName.startsWith("/") ? tableName : getDatabase() + "/" + tableName;
284+
285+
DescribeTableSettings settings = withDefaultTimeout(new DescribeTableSettings());
286+
Result<TableDescription> result = retryCtx.supplyResult(
287+
session -> session.describeTable(tablePath, settings)
288+
).join();
289+
290+
if (result.isSuccess()) {
291+
TableDescription d = result.getValue();
292+
types = result.getValue().getColumns().stream()
293+
.collect(Collectors.toMap(TableColumn::getName, TableColumn::getType));
294+
queryParamsCache.put(query.getOriginQuery(), types);
295+
}
296+
}
297+
if (types != null) {
298+
BatchedQuery params = BatchedQuery.createAutoBatched(query.getYqlBatcher(), types);
299+
if (params != null) {
300+
return params;
301+
}
302+
}
303+
}
304+
274305
if (!query.isPlainYQL()
275306
|| mode == YdbPrepareMode.IN_MEMORY
276307
|| !queryOptions.isPrepareDataQueries()) {
277308
return new InMemoryQuery(query, queryOptions.isDeclareJdbcParameters());
278309
}
279310

280-
String yql = query.getPreparedYql();
281-
PrepareDataQuerySettings settings = withDefaultTimeout(new PrepareDataQuerySettings());
311+
// try to prepare data query
282312
try {
283313
Map<String, Type> types = queryParamsCache.getIfPresent(query.getOriginQuery());
284314
if (types == null) {
315+
String yql = query.getPreparedYql();
316+
PrepareDataQuerySettings settings = withDefaultTimeout(new PrepareDataQuerySettings());
285317
types = retryCtx.supplyResult(session -> session.prepareDataQuery(yql, settings))
286318
.join()
287319
.getValue()

jdbc/src/main/java/tech/ydb/jdbc/query/YdbQuery.java

Lines changed: 13 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@ public class YdbQuery {
1515
private final String originQuery;
1616
private final String preparedYQL;
1717
private final List<QueryStatement> statements;
18+
private final YqlBatcher batch;
1819

1920
private final QueryType type;
2021
private final boolean isPlainYQL;
2122

2223
YdbQuery(String originQuery, String preparedYQL, List<QueryStatement> stats, QueryType type) {
24+
this(originQuery, preparedYQL, stats, null, type);
25+
}
26+
27+
YdbQuery(String originQuery, String preparedYQL, List<QueryStatement> stats, YqlBatcher batch, QueryType type) {
2328
this.originQuery = originQuery;
2429
this.preparedYQL = preparedYQL;
2530
this.statements = stats;
2631
this.type = type;
32+
this.batch = batch;
2733

2834
boolean hasJdbcParamters = false;
2935
for (QueryStatement st: statements) {
@@ -36,6 +42,10 @@ public QueryType getType() {
3642
return type;
3743
}
3844

45+
public YqlBatcher getYqlBatcher() {
46+
return batch;
47+
}
48+
3949
public boolean isPlainYQL() {
4050
return isPlainYQL;
4151
}
@@ -52,43 +62,6 @@ public List<QueryStatement> getStatements() {
5262
return statements;
5363
}
5464

55-
// public String withParams(Params params) throws SQLException {
56-
// if (isPlainYQL) {
57-
// return preparedYQL;
58-
// }
59-
//
60-
// if (params == null) {
61-
// if (isAutoDeclare) {
62-
// int paramCount = statements.stream().mapToInt(st -> st.getParams().size()).sum();
63-
// // Comment in place where must be declare section
64-
// return "-- DECLARE " + paramCount + " PARAMETERS\n" + preparedYQL;
65-
// }
66-
// return preparedYQL;
67-
// }
68-
//
69-
// StringBuilder yql = new StringBuilder();
70-
// Map<String, Value<?>> values = params.values();
71-
// for (QueryStatement st: statements) {
72-
// for (ParamDescription prm: st.getParams()) {
73-
// if (!values.containsKey(prm.name())) {
74-
// throw new SQLDataException(YdbConst.MISSING_VALUE_FOR_PARAMETER + prm);
75-
// }
76-
//
77-
// if (isAutoDeclare) {
78-
// String prmType = values.get(prm.name()).getType().toString();
79-
// yql.append("DECLARE ")
80-
// .append(prm.name())
81-
// .append(" AS ")
82-
// .append(prmType)
83-
// .append(";\n");
84-
// }
85-
// }
86-
// }
87-
//
88-
// yql.append(preparedYQL);
89-
// return yql.toString();
90-
// }
91-
9265
public static YdbQuery parseQuery(String query, YdbQueryProperties opts) throws SQLException {
9366
YdbQueryParser parser = new YdbQueryParser(opts.isDetectQueryType(), opts.isDetectJdbcParameters());
9467
String preparedYQL = parser.parseSQL(query);
@@ -97,7 +70,9 @@ public static YdbQuery parseQuery(String query, YdbQueryProperties opts) throws
9770
if (type == null) {
9871
type = parser.detectQueryType();
9972
}
100-
73+
if (parser.getYqlBatcher().isValidBatch()) {
74+
return new YdbQuery(query, preparedYQL, parser.getStatements(), parser.getYqlBatcher(), type);
75+
}
10176
return new YdbQuery(query, preparedYQL, parser.getStatements(), type);
10277
}
10378
}

jdbc/src/main/java/tech/ydb/jdbc/query/params/BatchedQuery.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import tech.ydb.jdbc.query.ParamDescription;
1919
import tech.ydb.jdbc.query.YdbPreparedQuery;
2020
import tech.ydb.jdbc.query.YdbQuery;
21+
import tech.ydb.jdbc.query.YqlBatcher;
2122
import tech.ydb.table.query.Params;
2223
import tech.ydb.table.values.ListType;
2324
import tech.ydb.table.values.ListValue;
@@ -211,4 +212,47 @@ public static BatchedQuery tryCreateBatched(YdbQuery query, Map<String, Type> ty
211212
StructType itemType = (StructType) innerType;
212213
return new BatchedQuery(query.getPreparedYql(), listName, itemType);
213214
}
215+
216+
public static BatchedQuery createAutoBatched(YqlBatcher batcher, Map<String, Type> tableColumns) {
217+
StringBuilder sb = new StringBuilder();
218+
Map<String, Type> structTypes = new HashMap<>();
219+
220+
sb.append("DECLARE $batch AS List<Struct<");
221+
int idx = 1;
222+
for (String column: batcher.getColumns()) {
223+
Type type = tableColumns.get(column);
224+
if (type == null) {
225+
return null;
226+
}
227+
if (idx > 1) {
228+
sb.append(", ");
229+
}
230+
sb.append("p").append(idx).append(":").append(type.toString());
231+
structTypes.put("p" + idx, type);
232+
idx++;
233+
}
234+
sb.append(">>;\n");
235+
236+
if (batcher.isInsert()) {
237+
sb.append("INSERT ");
238+
}
239+
if (batcher.isUpsert()) {
240+
sb.append("UPSERT ");
241+
}
242+
243+
sb.append("INTO `").append(batcher.getTableName()).append("` SELECT ");
244+
245+
idx = 1;
246+
for (String column: batcher.getColumns()) {
247+
if (idx > 1) {
248+
sb.append(", ");
249+
}
250+
sb.append("p").append(idx).append(" AS `").append(column).append("`");
251+
idx++;
252+
}
253+
254+
sb.append(" FROM AS_TABLE($batch);");
255+
256+
return new BatchedQuery(sb.toString(), "$batch", StructType.of(structTypes));
257+
}
214258
}

jdbc/src/test/java/tech/ydb/jdbc/impl/YdbPreparedStatementTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ public void executeUpdateTest(SqlQueries.JdbcQuery query) throws SQLException {
112112
@ParameterizedTest(name = "with {0}")
113113
@EnumSource(SqlQueries.JdbcQuery.class)
114114
public void executeWithMissingParameter(SqlQueries.JdbcQuery query) throws SQLException {
115+
if (query == SqlQueries.JdbcQuery.STANDART) {
116+
// TODO: auto batching don't check missing parameter
117+
return;
118+
}
115119
String sql = TEST_TABLE.upsertOne(query, "c_Text", "Text");
116120

117121
try (PreparedStatement statement = jdbc.connection().prepareStatement(sql)) {

0 commit comments

Comments
 (0)