Skip to content

Commit f340f22

Browse files
authored
Updated yql query parser with support of RETURNING, OFFSET/LIMIT and auto batching (#56)
2 parents fc82d87 + c9c1798 commit f340f22

34 files changed

+1787
-875
lines changed

jdbc/src/main/java/tech/ydb/jdbc/YdbConnection.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import tech.ydb.jdbc.context.YdbContext;
1010
import tech.ydb.jdbc.context.YdbValidator;
1111
import tech.ydb.jdbc.query.ExplainedQuery;
12-
import tech.ydb.jdbc.query.YdbQuery;
1312
import tech.ydb.table.query.Params;
1413
import tech.ydb.table.result.ResultSetReader;
1514

@@ -36,47 +35,47 @@ public interface YdbConnection extends Connection {
3635
/**
3736
* Explicitly execute query as a schema query
3837
*
39-
* @param query query (DDL) to execute
38+
* @param yql query (DDL) to execute
4039
* @param validator handler for logging and warnings
4140
* @throws SQLException if query cannot be executed
4241
*/
43-
void executeSchemeQuery(YdbQuery query, YdbValidator validator) throws SQLException;
42+
void executeSchemeQuery(String yql, YdbValidator validator) throws SQLException;
4443

4544
/**
4645
* Explicitly execute query as a data query
4746
*
48-
* @param query query to execute
47+
* @param yql query to execute
4948
* @param params parameters for query
5049
* @param timeout timeout of operation
5150
* @param keepInCache flag to store query in server-side cache
5251
* @param validator handler for logging and warnings
5352
* @return list of result set
5453
* @throws SQLException if query cannot be executed
5554
*/
56-
List<ResultSetReader> executeDataQuery(YdbQuery query, YdbValidator validator,
55+
List<ResultSetReader> executeDataQuery(String yql, YdbValidator validator,
5756
int timeout, boolean keepInCache, Params params) throws SQLException;
5857

5958
/**
6059
* Explicitly execute query as a scan query
6160
*
62-
* @param query query to execute
61+
* @param yql query to execute
6362
* @param params parameters for query
6463
* @param validator handler for logging and warnings
6564
* @return single result set with rows
6665
* @throws SQLException if query cannot be executed
6766
*/
68-
ResultSetReader executeScanQuery(YdbQuery query, YdbValidator validator, Params params) throws SQLException;
67+
ResultSetReader executeScanQuery(String yql, YdbValidator validator, Params params) throws SQLException;
6968

7069
/**
7170
* Explicitly explain this query
7271
*
73-
* @param query query to explain
72+
* @param yql query to explain
7473
* @param validator handler for logging and warnings
7574
* @return list of result set of two string columns: {@link YdbConst#EXPLAIN_COLUMN_AST}
7675
* and {@link YdbConst#EXPLAIN_COLUMN_PLAN}
7776
* @throws SQLException if query cannot be explained
7877
*/
79-
ExplainedQuery executeExplainQuery(YdbQuery query, YdbValidator validator) throws SQLException;
78+
ExplainedQuery executeExplainQuery(String yql, YdbValidator validator) throws SQLException;
8079

8180
@Override
8281
YdbDatabaseMetaData getMetaData() throws SQLException;

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import tech.ydb.core.UnexpectedResultException;
1010
import tech.ydb.jdbc.exception.ExceptionFactory;
1111
import tech.ydb.jdbc.query.QueryType;
12-
import tech.ydb.jdbc.query.YdbQuery;
1312
import tech.ydb.table.Session;
1413
import tech.ydb.table.TableClient;
1514
import tech.ydb.table.query.Params;
@@ -42,22 +41,19 @@ protected Session createNewTableSession(YdbValidator validator) throws SQLExcept
4241
}
4342

4443
@Override
45-
public void executeSchemeQuery(YdbContext ctx, YdbValidator validator, YdbQuery query) throws SQLException {
44+
public void executeSchemeQuery(YdbContext ctx, YdbValidator validator, String yql) throws SQLException {
4645
// Scheme query does not affect transactions or result sets
4746
ExecuteSchemeQuerySettings settings = ctx.withDefaultTimeout(new ExecuteSchemeQuerySettings());
48-
final String yql = query.getYqlQuery(null);
49-
5047
try (Session session = createNewTableSession(validator)) {
5148
validator.execute(QueryType.SCHEME_QUERY + " >>\n" + yql, () -> session.executeSchemeQuery(yql, settings));
5249
}
5350
}
5451

5552
@Override
56-
public ResultSetReader executeScanQuery(YdbContext ctx, YdbValidator validator, YdbQuery query, Params params)
53+
public ResultSetReader executeScanQuery(YdbContext ctx, YdbValidator validator, String yql, Params params)
5754
throws SQLException {
5855
ensureOpened();
5956

60-
String yql = query.getYqlQuery(params);
6157
Collection<ResultSetReader> resultSets = new LinkedBlockingQueue<>();
6258
Duration scanQueryTimeout = ctx.getOperationProperties().getScanQueryTimeout();
6359
ExecuteScanQuerySettings settings = ExecuteScanQuerySettings.newBuilder()

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

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import tech.ydb.jdbc.exception.ExceptionFactory;
1818
import tech.ydb.jdbc.query.ExplainedQuery;
1919
import tech.ydb.jdbc.query.QueryType;
20-
import tech.ydb.jdbc.query.YdbQuery;
2120
import tech.ydb.query.QueryClient;
2221
import tech.ydb.query.QuerySession;
2322
import tech.ydb.query.QueryStream;
@@ -197,11 +196,10 @@ public void rollback(YdbContext ctx, YdbValidator validator) throws SQLException
197196

198197
@Override
199198
public List<ResultSetReader> executeDataQuery(
200-
YdbContext ctx, YdbValidator validator, YdbQuery query, long timeout, boolean keepInCache, Params params
199+
YdbContext ctx, YdbValidator validator, String yql, long timeout, boolean keepInCache, Params params
201200
) throws SQLException {
202201
ensureOpened();
203202

204-
final String yql = query.getYqlQuery(params);
205203
ExecuteQuerySettings.Builder builder = ExecuteQuerySettings.newBuilder();
206204
if (timeout > 0) {
207205
builder = builder.withRequestTimeout(timeout, TimeUnit.SECONDS);
@@ -229,13 +227,11 @@ public List<ResultSetReader> executeDataQuery(
229227
}
230228

231229
@Override
232-
public void executeSchemeQuery(YdbContext ctx, YdbValidator validator, YdbQuery query) throws SQLException {
230+
public void executeSchemeQuery(YdbContext ctx, YdbValidator validator, String yql) throws SQLException {
233231
ensureOpened();
234232

235233
// Scheme query does not affect transactions or result sets
236234
ExecuteQuerySettings settings = ctx.withRequestTimeout(ExecuteQuerySettings.newBuilder()).build();
237-
final String yql = query.getYqlQuery(null);
238-
239235
try (QuerySession session = createNewQuerySession(validator)) {
240236
validator.call(QueryType.SCHEME_QUERY + " >>\n" + yql, () -> session
241237
.createQuery(yql, TxMode.NONE, Params.empty(), settings)
@@ -245,15 +241,14 @@ public void executeSchemeQuery(YdbContext ctx, YdbValidator validator, YdbQuery
245241
}
246242

247243
@Override
248-
public ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator, YdbQuery query)
244+
public ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator, String yql)
249245
throws SQLException {
250246
ensureOpened();
251247

252248
// Scheme query does not affect transactions or result sets
253249
ExecuteQuerySettings settings = ctx.withRequestTimeout(ExecuteQuerySettings.newBuilder())
254250
.withExecMode(QueryExecMode.EXPLAIN)
255251
.build();
256-
final String yql = query.getYqlQuery(null);
257252

258253
try (QuerySession session = createNewQuerySession(validator)) {
259254
QueryInfo res = validator.call(QueryType.EXPLAIN_QUERY + " >>\n" + yql, () -> session

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import tech.ydb.jdbc.YdbConst;
1111
import tech.ydb.jdbc.query.ExplainedQuery;
1212
import tech.ydb.jdbc.query.QueryType;
13-
import tech.ydb.jdbc.query.YdbQuery;
1413
import tech.ydb.table.Session;
1514
import tech.ydb.table.query.DataQueryResult;
1615
import tech.ydb.table.query.ExplainDataQueryResult;
@@ -155,11 +154,10 @@ private ExecuteDataQuerySettings dataQuerySettings(long timeout, boolean keepInC
155154
}
156155

157156
@Override
158-
public ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator, YdbQuery query)
157+
public ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator, String yql)
159158
throws SQLException {
160159
ensureOpened();
161160

162-
String yql = query.getYqlQuery(null);
163161
ExplainDataQuerySettings settings = ctx.withDefaultTimeout(new ExplainDataQuerySettings());
164162
try (Session session = createNewTableSession(validator)) {
165163
String msg = QueryType.EXPLAIN_QUERY + " >>\n" + yql;
@@ -170,11 +168,10 @@ public ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator
170168

171169
@Override
172170
public List<ResultSetReader> executeDataQuery(
173-
YdbContext ctx, YdbValidator validator, YdbQuery query, long timeout, boolean keepInCache, Params params
171+
YdbContext ctx, YdbValidator validator, String yql, long timeout, boolean keepInCache, Params params
174172
) throws SQLException {
175173
ensureOpened();
176174

177-
final String yql = query.getYqlQuery(params);
178175
final Session session = tx.getSession(validator);
179176
try {
180177
DataQueryResult result = validator.call(

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

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,24 @@
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;
1820
import tech.ydb.core.settings.BaseRequestSettings;
1921
import tech.ydb.jdbc.YdbConst;
2022
import tech.ydb.jdbc.YdbPrepareMode;
2123
import tech.ydb.jdbc.exception.ExceptionFactory;
22-
import tech.ydb.jdbc.query.JdbcParams;
23-
import tech.ydb.jdbc.query.JdbcQueryLexer;
24+
import tech.ydb.jdbc.query.YdbPreparedQuery;
2425
import tech.ydb.jdbc.query.YdbQuery;
25-
import tech.ydb.jdbc.query.YdbQueryBuilder;
26-
import tech.ydb.jdbc.query.params.BatchedParams;
27-
import tech.ydb.jdbc.query.params.InMemoryParams;
28-
import tech.ydb.jdbc.query.params.PreparedParams;
26+
import tech.ydb.jdbc.query.params.BatchedQuery;
27+
import tech.ydb.jdbc.query.params.InMemoryQuery;
28+
import tech.ydb.jdbc.query.params.PreparedQuery;
2929
import tech.ydb.jdbc.settings.YdbClientProperties;
3030
import tech.ydb.jdbc.settings.YdbConfig;
3131
import tech.ydb.jdbc.settings.YdbConnectionProperties;
@@ -36,8 +36,11 @@
3636
import tech.ydb.scheme.SchemeClient;
3737
import tech.ydb.table.SessionRetryContext;
3838
import tech.ydb.table.TableClient;
39+
import tech.ydb.table.description.TableColumn;
40+
import tech.ydb.table.description.TableDescription;
3941
import tech.ydb.table.impl.PooledTableClient;
4042
import tech.ydb.table.rpc.grpc.GrpcTableRpc;
43+
import tech.ydb.table.settings.DescribeTableSettings;
4144
import tech.ydb.table.settings.PrepareDataQuerySettings;
4245
import tech.ydb.table.settings.RequestSettings;
4346
import tech.ydb.table.values.Type;
@@ -255,9 +258,7 @@ public <T extends BaseRequestSettings.BaseBuilder<T>> T withRequestTimeout(T bui
255258
}
256259

257260
public YdbQuery parseYdbQuery(String sql) throws SQLException {
258-
YdbQueryBuilder builder = new YdbQueryBuilder(sql, queryOptions.getForcedQueryType());
259-
JdbcQueryLexer.buildQuery(builder, queryOptions);
260-
return builder.build(queryOptions);
261+
return YdbQuery.parseQuery(sql, queryOptions);
261262
}
262263

263264
public YdbQuery findOrParseYdbQuery(String sql) throws SQLException {
@@ -274,37 +275,64 @@ public YdbQuery findOrParseYdbQuery(String sql) throws SQLException {
274275
return cached;
275276
}
276277

277-
public JdbcParams findOrCreateJdbcParams(YdbQuery query, YdbPrepareMode mode) throws SQLException {
278-
if (query.hasIndexesParameters()
278+
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+
305+
if (!query.isPlainYQL()
279306
|| mode == YdbPrepareMode.IN_MEMORY
280-
|| !queryOptions.iPrepareDataQueries()) {
281-
return new InMemoryParams(query.getIndexesParameters());
307+
|| !queryOptions.isPrepareDataQueries()) {
308+
return new InMemoryQuery(query, queryOptions.isDeclareJdbcParameters());
282309
}
283310

284-
String yql = query.getYqlQuery(null);
285-
PrepareDataQuerySettings settings = withDefaultTimeout(new PrepareDataQuerySettings());
311+
// try to prepare data query
286312
try {
287-
Map<String, Type> types = queryParamsCache.getIfPresent(query.originSQL());
313+
Map<String, Type> types = queryParamsCache.getIfPresent(query.getOriginQuery());
288314
if (types == null) {
315+
String yql = query.getPreparedYql();
316+
PrepareDataQuerySettings settings = withDefaultTimeout(new PrepareDataQuerySettings());
289317
types = retryCtx.supplyResult(session -> session.prepareDataQuery(yql, settings))
290318
.join()
291319
.getValue()
292320
.types();
293-
queryParamsCache.put(query.originSQL(), types);
321+
queryParamsCache.put(query.getOriginQuery(), types);
294322
}
295323

296324
boolean requireBatch = mode == YdbPrepareMode.DATA_QUERY_BATCH;
297325
if (requireBatch || (mode == YdbPrepareMode.AUTO && queryOptions.isDetectBatchQueries())) {
298-
BatchedParams params = BatchedParams.tryCreateBatched(types);
326+
BatchedQuery params = BatchedQuery.tryCreateBatched(query, types);
299327
if (params != null) {
300328
return params;
301329
}
302330

303331
if (requireBatch) {
304-
throw new SQLDataException(YdbConst.STATEMENT_IS_NOT_A_BATCH + query.originSQL());
332+
throw new SQLDataException(YdbConst.STATEMENT_IS_NOT_A_BATCH + query.getOriginQuery());
305333
}
306334
}
307-
return new PreparedParams(types);
335+
return new PreparedQuery(query, types);
308336
} catch (UnexpectedResultException ex) {
309337
throw ExceptionFactory.createException("Cannot prepare data query: " + ex.getMessage(), ex);
310338
}

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import tech.ydb.jdbc.YdbConst;
77
import tech.ydb.jdbc.query.ExplainedQuery;
8-
import tech.ydb.jdbc.query.YdbQuery;
98
import tech.ydb.table.query.Params;
109
import tech.ydb.table.result.ResultSetReader;
1110

@@ -33,15 +32,15 @@ default void ensureOpened() throws SQLException {
3332
void setReadOnly(boolean readOnly) throws SQLException;
3433
void setAutoCommit(boolean autoCommit) throws SQLException;
3534

36-
void executeSchemeQuery(YdbContext ctx, YdbValidator validator, YdbQuery query) throws SQLException;
35+
void executeSchemeQuery(YdbContext ctx, YdbValidator validator, String yql) throws SQLException;
3736

38-
List<ResultSetReader> executeDataQuery(YdbContext ctx, YdbValidator validator, YdbQuery query,
37+
List<ResultSetReader> executeDataQuery(YdbContext ctx, YdbValidator validator, String yql,
3938
long timeout, boolean poolable, Params params) throws SQLException;
4039

41-
ResultSetReader executeScanQuery(YdbContext ctx, YdbValidator validator, YdbQuery query, Params params)
40+
ResultSetReader executeScanQuery(YdbContext ctx, YdbValidator validator, String yql, Params params)
4241
throws SQLException;
4342

44-
ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator, YdbQuery query)
43+
ExplainedQuery executeExplainQuery(YdbContext ctx, YdbValidator validator, String yql)
4544
throws SQLException;
4645

4746
void commit(YdbContext ctx, YdbValidator validator) throws SQLException;

0 commit comments

Comments
 (0)