Skip to content

Commit 90c5b4e

Browse files
committed
Support for SQL.
Signed-off-by: Youssef Aouichaoui <[email protected]>
1 parent 3fc19bb commit 90c5b4e

File tree

10 files changed

+1029
-20
lines changed

10 files changed

+1029
-20
lines changed

src/main/java/org/springframework/data/elasticsearch/client/elc/ElasticsearchTemplate.java

+34
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
package org.springframework.data.elasticsearch.client.elc;
1717

1818
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
19+
import static org.springframework.data.elasticsearch.core.sql.types.ResponseFormat.json;
1920

2021
import co.elastic.clients.elasticsearch.ElasticsearchClient;
2122
import co.elastic.clients.elasticsearch._types.Time;
2223
import co.elastic.clients.elasticsearch.core.*;
2324
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
2425
import co.elastic.clients.elasticsearch.core.msearch.MultiSearchResponseItem;
2526
import co.elastic.clients.elasticsearch.core.search.ResponseBody;
27+
import co.elastic.clients.elasticsearch.sql.ElasticsearchSqlClient;
28+
import co.elastic.clients.elasticsearch.sql.QueryResponse;
2629
import co.elastic.clients.json.JsonpMapper;
2730
import co.elastic.clients.transport.Version;
2831

@@ -34,6 +37,7 @@
3437
import java.util.Iterator;
3538
import java.util.List;
3639
import java.util.Map;
40+
import java.util.Objects;
3741
import java.util.stream.Collectors;
3842

3943
import org.apache.commons.logging.Log;
@@ -56,6 +60,7 @@
5660
import org.springframework.data.elasticsearch.core.reindex.ReindexRequest;
5761
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
5862
import org.springframework.data.elasticsearch.core.script.Script;
63+
import org.springframework.data.elasticsearch.core.sql.SqlResponse;
5964
import org.springframework.lang.Nullable;
6065
import org.springframework.util.Assert;
6166

@@ -74,6 +79,7 @@ public class ElasticsearchTemplate extends AbstractElasticsearchTemplate {
7479
private static final Log LOGGER = LogFactory.getLog(ElasticsearchTemplate.class);
7580

7681
private final ElasticsearchClient client;
82+
private final ElasticsearchSqlClient sqlClient;
7783
private final RequestConverter requestConverter;
7884
private final ResponseConverter responseConverter;
7985
private final JsonpMapper jsonpMapper;
@@ -85,6 +91,7 @@ public ElasticsearchTemplate(ElasticsearchClient client) {
8591
Assert.notNull(client, "client must not be null");
8692

8793
this.client = client;
94+
this.sqlClient = client.sql();
8895
this.jsonpMapper = client._transport().jsonpMapper();
8996
requestConverter = new RequestConverter(elasticsearchConverter, jsonpMapper);
9097
responseConverter = new ResponseConverter(jsonpMapper);
@@ -97,6 +104,7 @@ public ElasticsearchTemplate(ElasticsearchClient client, ElasticsearchConverter
97104
Assert.notNull(client, "client must not be null");
98105

99106
this.client = client;
107+
this.sqlClient = client.sql();
100108
this.jsonpMapper = client._transport().jsonpMapper();
101109
requestConverter = new RequestConverter(elasticsearchConverter, jsonpMapper);
102110
responseConverter = new ResponseConverter(jsonpMapper);
@@ -656,6 +664,32 @@ public boolean deleteScript(String name) {
656664
DeleteScriptRequest request = requestConverter.scriptDelete(name);
657665
return execute(client -> client.deleteScript(request)).acknowledged();
658666
}
667+
668+
@Override
669+
public SqlResponse search(SqlQuery query) {
670+
Assert.notNull(query, "Query must not be null.");
671+
Assert.isTrue(query.getFormat() == null || json.equals(query.getFormat()),
672+
"The Elasticsearch Java Client only supports JSON format.");
673+
674+
try {
675+
QueryResponse response = sqlClient.query(sqb -> {
676+
sqb.query(query.getQuery()).catalog(query.getCatalog()).columnar(query.getColumnar()).cursor(query.getCursor())
677+
.fetchSize(query.getFetchSize()).fieldMultiValueLeniency(query.getFieldMultiValueLeniency())
678+
.indexUsingFrozen(query.getIndexIncludeFrozen()).keepAlive(time(query.getKeepAlive()))
679+
.keepOnCompletion(query.getKeepOnCompletion()).pageTimeout(time(query.getPageTimeout()))
680+
.requestTimeout(time(query.getRequestTimeout()))
681+
.waitForCompletionTimeout(time(query.getWaitForCompletionTimeout()))
682+
.filter(requestConverter.getQuery(query.getFilter(), null))
683+
.timeZone(Objects.toString(query.getTimeZone(), null)).format(Objects.toString(query.getFormat(), null));
684+
685+
return sqb;
686+
});
687+
688+
return responseConverter.sqlResponse(response);
689+
} catch (IOException e) {
690+
throw exceptionTranslator.translateException(e);
691+
}
692+
}
659693
// endregion
660694

661695
// region client callback

src/main/java/org/springframework/data/elasticsearch/client/elc/ResponseConverter.java

+57-19
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,9 @@
1515
*/
1616
package org.springframework.data.elasticsearch.client.elc;
1717

18-
import static org.springframework.data.elasticsearch.client.elc.JsonUtils.*;
19-
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.*;
20-
21-
import co.elastic.clients.elasticsearch._types.BulkIndexByScrollFailure;
22-
import co.elastic.clients.elasticsearch._types.ErrorCause;
23-
import co.elastic.clients.elasticsearch._types.Time;
24-
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
25-
import co.elastic.clients.elasticsearch.cluster.ComponentTemplateSummary;
26-
import co.elastic.clients.elasticsearch.cluster.GetComponentTemplateResponse;
27-
import co.elastic.clients.elasticsearch.cluster.HealthResponse;
28-
import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse;
29-
import co.elastic.clients.elasticsearch.core.GetScriptResponse;
30-
import co.elastic.clients.elasticsearch.core.UpdateByQueryResponse;
31-
import co.elastic.clients.elasticsearch.core.mget.MultiGetError;
32-
import co.elastic.clients.elasticsearch.core.mget.MultiGetResponseItem;
33-
import co.elastic.clients.elasticsearch.indices.*;
34-
import co.elastic.clients.elasticsearch.indices.get_index_template.IndexTemplateItem;
35-
import co.elastic.clients.elasticsearch.indices.get_mapping.IndexMappingRecord;
36-
import co.elastic.clients.json.JsonpMapper;
18+
import static org.springframework.data.elasticsearch.client.elc.JsonUtils.toJson;
19+
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.removePrefixFromJson;
20+
import static org.springframework.data.elasticsearch.client.elc.TypeUtils.typeMapping;
3721

3822
import java.util.ArrayList;
3923
import java.util.HashMap;
@@ -61,10 +45,41 @@
6145
import org.springframework.data.elasticsearch.core.query.StringQuery;
6246
import org.springframework.data.elasticsearch.core.reindex.ReindexResponse;
6347
import org.springframework.data.elasticsearch.core.script.Script;
48+
import org.springframework.data.elasticsearch.core.sql.SqlResponse;
6449
import org.springframework.data.elasticsearch.support.DefaultStringObjectMap;
6550
import org.springframework.lang.Nullable;
6651
import org.springframework.util.Assert;
6752

53+
import co.elastic.clients.elasticsearch._types.BulkIndexByScrollFailure;
54+
import co.elastic.clients.elasticsearch._types.ErrorCause;
55+
import co.elastic.clients.elasticsearch._types.Time;
56+
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
57+
import co.elastic.clients.elasticsearch.cluster.ComponentTemplateSummary;
58+
import co.elastic.clients.elasticsearch.cluster.GetComponentTemplateResponse;
59+
import co.elastic.clients.elasticsearch.cluster.HealthResponse;
60+
import co.elastic.clients.elasticsearch.core.DeleteByQueryResponse;
61+
import co.elastic.clients.elasticsearch.core.GetScriptResponse;
62+
import co.elastic.clients.elasticsearch.core.UpdateByQueryResponse;
63+
import co.elastic.clients.elasticsearch.core.mget.MultiGetError;
64+
import co.elastic.clients.elasticsearch.core.mget.MultiGetResponseItem;
65+
import co.elastic.clients.elasticsearch.indices.Alias;
66+
import co.elastic.clients.elasticsearch.indices.AliasDefinition;
67+
import co.elastic.clients.elasticsearch.indices.GetAliasResponse;
68+
import co.elastic.clients.elasticsearch.indices.GetIndexResponse;
69+
import co.elastic.clients.elasticsearch.indices.GetIndexTemplateResponse;
70+
import co.elastic.clients.elasticsearch.indices.GetIndicesSettingsResponse;
71+
import co.elastic.clients.elasticsearch.indices.GetMappingResponse;
72+
import co.elastic.clients.elasticsearch.indices.GetTemplateResponse;
73+
import co.elastic.clients.elasticsearch.indices.IndexSettings;
74+
import co.elastic.clients.elasticsearch.indices.IndexState;
75+
import co.elastic.clients.elasticsearch.indices.IndexTemplateSummary;
76+
import co.elastic.clients.elasticsearch.indices.TemplateMapping;
77+
import co.elastic.clients.elasticsearch.indices.get_index_template.IndexTemplateItem;
78+
import co.elastic.clients.elasticsearch.indices.get_mapping.IndexMappingRecord;
79+
import co.elastic.clients.elasticsearch.sql.QueryResponse;
80+
import co.elastic.clients.json.JsonData;
81+
import co.elastic.clients.json.JsonpMapper;
82+
6883
/**
6984
* Class to convert Elasticsearch responses into Spring Data Elasticsearch classes.
7085
*
@@ -536,6 +551,29 @@ public Script scriptResponse(GetScriptResponse response) {
536551
}
537552
// endregion
538553

554+
// region sql
555+
public SqlResponse sqlResponse(QueryResponse response) {
556+
SqlResponse.Builder builder = SqlResponse.builder();
557+
builder.withRunning(Boolean.TRUE.equals(response.isRunning()))
558+
.withPartial(Boolean.TRUE.equals(response.isPartial())).withCursor(response.cursor());
559+
560+
final List<SqlResponse.Column> columns = response.columns().stream()
561+
.map(column -> new SqlResponse.Column(column.name(), column.type())).toList();
562+
builder.withColumns(columns);
563+
564+
for (List<JsonData> rowValues : response.rows()) {
565+
SqlResponse.Row.Builder rowBuilder = SqlResponse.Row.builder();
566+
for (int idx = 0; idx < rowValues.size(); idx++) {
567+
rowBuilder.withValue(columns.get(idx), rowValues.get(idx).toJson());
568+
}
569+
570+
builder.withRow(rowBuilder.build());
571+
}
572+
573+
return builder.build();
574+
}
575+
// end region
576+
539577
// region helper functions
540578

541579
private long timeToLong(Time time) {

src/main/java/org/springframework/data/elasticsearch/core/ElasticsearchOperations.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
2121
import org.springframework.data.elasticsearch.core.routing.RoutingResolver;
2222
import org.springframework.data.elasticsearch.core.script.ScriptOperations;
23+
import org.springframework.data.elasticsearch.core.sql.SqlOperations;
2324
import org.springframework.lang.Nullable;
2425

2526
/**
@@ -35,7 +36,7 @@
3536
* @author Dmitriy Yakovlev
3637
* @author Peter-Josef Meisch
3738
*/
38-
public interface ElasticsearchOperations extends DocumentOperations, SearchOperations, ScriptOperations {
39+
public interface ElasticsearchOperations extends DocumentOperations, SearchOperations, ScriptOperations, SqlOperations {
3940

4041
/**
4142
* get an {@link IndexOperations} that is bound to the given class

0 commit comments

Comments
 (0)