Skip to content

Commit db8788e

Browse files
authored
QL: wildcard field type support (#58062) (#61205)
(cherry picked from commit c874e6c)
1 parent 90e1167 commit db8788e

File tree

13 files changed

+382
-5
lines changed

13 files changed

+382
-5
lines changed

x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/whitelist/InternalQlScriptUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
package org.elasticsearch.xpack.ql.expression.function.scalar.whitelist;
88

99
import org.elasticsearch.index.fielddata.ScriptDocValues;
10-
import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation;
1110
import org.elasticsearch.xpack.ql.expression.function.scalar.string.StartsWithFunctionProcessor;
11+
import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation;
1212
import org.elasticsearch.xpack.ql.expression.predicate.logical.NotProcessor;
1313
import org.elasticsearch.xpack.ql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation;
1414
import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.DefaultBinaryArithmeticOperation;

x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Types.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,12 @@ private static Map<String, EsField> startWalking(DataTypeRegistry typeRegistry,
4848

4949
private static DataType getType(DataTypeRegistry typeRegistry, Map<String, Object> content) {
5050
if (content.containsKey("type")) {
51+
String typeName = content.get("type").toString();
52+
if ("wildcard".equals(typeName)) {
53+
return KEYWORD;
54+
}
5155
try {
52-
return typeRegistry.fromEs(content.get("type").toString());
56+
return typeRegistry.fromEs(typeName);
5357
} catch (IllegalArgumentException ex) {
5458
return UNSUPPORTED;
5559
}

x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/TypesTests.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,11 @@ public void testMultiField() {
136136
assertThat(DataTypes.isPrimitive(field.getDataType()), is(true));
137137
assertThat(field.getDataType(), is(TEXT));
138138
Map<String, EsField> fields = field.getProperties();
139-
assertThat(fields.size(), is(3));
139+
assertThat(fields.size(), is(4));
140140
assertThat(fields.get("raw").getDataType(), is(KEYWORD));
141141
assertThat(fields.get("english").getDataType(), is(TEXT));
142142
assertThat(fields.get("constant").getDataType(), is(CONSTANT_KEYWORD));
143+
assertThat(fields.get("wildcard").getDataType(), is(KEYWORD));
143144
}
144145

145146
public void testMultiFieldTooManyOptions() {
@@ -150,10 +151,11 @@ public void testMultiFieldTooManyOptions() {
150151
assertThat(DataTypes.isPrimitive(field.getDataType()), is(true));
151152
assertThat(field, instanceOf(TextEsField.class));
152153
Map<String, EsField> fields = field.getProperties();
153-
assertThat(fields.size(), is(3));
154+
assertThat(fields.size(), is(4));
154155
assertThat(fields.get("raw").getDataType(), is(KEYWORD));
155156
assertThat(fields.get("english").getDataType(), is(TEXT));
156157
assertThat(fields.get("constant").getDataType(), is(CONSTANT_KEYWORD));
158+
assertThat(fields.get("wildcard").getDataType(), is(KEYWORD));
157159
}
158160

159161
public void testNestedDoc() {
@@ -183,6 +185,13 @@ public void testConstantKeywordField() {
183185
assertThat(dt.getDataType().typeName(), is("constant_keyword"));
184186
}
185187

188+
public void testWildcardField() {
189+
Map<String, EsField> mapping = loadMapping("mapping-wildcard.json");
190+
assertThat(mapping.size(), is(1));
191+
EsField dt = mapping.get("full_name");
192+
assertThat(dt.getDataType().typeName(), is("keyword"));
193+
}
194+
186195
public void testUnsupportedTypes() {
187196
Map<String, EsField> mapping = loadMapping("mapping-unsupported.json");
188197
EsField dt = mapping.get("range");

x-pack/plugin/ql/src/test/resources/mapping-multi-field.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
"constant" : {
1414
"type" : "constant_keyword",
1515
"value" : "some constant value"
16+
},
17+
"wildcard" : {
18+
"type" : "wildcard"
1619
}
1720
}
1821
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"properties" : {
3+
"full_name" : {
4+
"type" : "wildcard",
5+
"ignore_above" : 256
6+
}
7+
}
8+
}

x-pack/plugin/sql/qa/jdbc/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/PreparedStatementTestCase.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,65 @@ public void testOutOfRangeBigDecimal() throws SQLException {
189189
}
190190
}
191191

192+
public void testWildcardField() throws IOException, SQLException {
193+
String mapping = "\"properties\":{\"id\":{\"type\":\"integer\"},\"text\":{\"type\":\"wildcard\"}}";
194+
createIndex("test", Settings.EMPTY, mapping);
195+
String text = randomAlphaOfLengthBetween(1, 10);
196+
197+
for (int i = 1; i <= 3; i++) {
198+
int id = 1000 + i;
199+
String valueToIndex = text + i;
200+
index("test", "" + i, builder -> {
201+
builder.field("id", id);
202+
builder.field("text", valueToIndex);
203+
});
204+
}
205+
206+
try (Connection connection = esJdbc()) {
207+
try (PreparedStatement statement = connection.prepareStatement("SELECT id, text FROM test WHERE text = ?")) {
208+
int randomDocumentIndex = randomIntBetween(1, 3);
209+
String randomDocumentText = text + randomDocumentIndex;
210+
211+
statement.setString(1, randomDocumentText);
212+
try (ResultSet results = statement.executeQuery()) {
213+
assertTrue(results.next());
214+
assertEquals(1000 + randomDocumentIndex, results.getInt(1));
215+
assertEquals(randomDocumentText, results.getString(2));
216+
assertFalse(results.next());
217+
}
218+
}
219+
}
220+
}
221+
222+
public void testConstantKeywordField() throws IOException, SQLException {
223+
String mapping = "\"properties\":{\"id\":{\"type\":\"integer\"},\"text\":{\"type\":\"constant_keyword\"}}";
224+
createIndex("test", Settings.EMPTY, mapping);
225+
String text = randomAlphaOfLengthBetween(1, 10);
226+
227+
for (int i = 1; i <= 3; i++) {
228+
int id = 1000 + i;
229+
index("test", "" + i, builder -> {
230+
builder.field("id", id);
231+
builder.field("text", text);
232+
});
233+
}
234+
235+
try (Connection connection = esJdbc()) {
236+
try (PreparedStatement statement = connection.prepareStatement("SELECT id, text FROM test WHERE text = ?")) {
237+
statement.setString(1, text);
238+
239+
try (ResultSet results = statement.executeQuery()) {
240+
for (int i = 1; i <= 3; i++) {
241+
assertTrue(results.next());
242+
assertEquals(1000 + i, results.getInt(1));
243+
assertEquals(text, results.getString(2));
244+
}
245+
assertFalse(results.next());
246+
}
247+
}
248+
}
249+
}
250+
192251
public void testUnsupportedParameterUse() throws IOException, SQLException {
193252
index("library", builder -> {
194253
builder.field("name", "Don Quixote");

x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/FieldExtractorTestCase.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,39 @@ public void testConstantKeywordField() throws IOException {
134134
assertResponse(expected, runSql("SELECT constant_keyword_field FROM test"));
135135
}
136136

137+
/*
138+
* "wildcard_field": {
139+
* "type": "wildcard",
140+
* "ignore_above": 10
141+
* }
142+
*/
143+
public void testWildcardField() throws IOException {
144+
String wildcard = randomAlphaOfLength(20);
145+
// _source for `wildcard` fields doesn't matter, as they should be taken from docvalue_fields
146+
boolean explicitSourceSetting = randomBoolean(); // default (no _source setting) or explicit setting
147+
boolean enableSource = randomBoolean(); // enable _source at index level
148+
boolean ignoreAbove = randomBoolean();
149+
150+
Map<String, Object> indexProps = new HashMap<>(1);
151+
indexProps.put("_source", enableSource);
152+
153+
Map<String, Map<String, Object>> fieldProps = null;
154+
if (ignoreAbove) {
155+
fieldProps = new HashMap<>(1);
156+
Map<String, Object> fieldProp = new HashMap<>(1);
157+
fieldProp.put("ignore_above", 10);
158+
fieldProps.put("wildcard_field", fieldProp);
159+
}
160+
161+
createIndexWithFieldTypeAndProperties("wildcard", fieldProps, explicitSourceSetting ? indexProps : null);
162+
index("{\"wildcard_field\":\"" + wildcard + "\"}");
163+
164+
Map<String, Object> expected = new HashMap<>();
165+
expected.put("columns", Arrays.asList(columnInfo("plain", "wildcard_field", "keyword", JDBCType.VARCHAR, Integer.MAX_VALUE)));
166+
expected.put("rows", singletonList(singletonList(ignoreAbove ? null : wildcard)));
167+
assertResponse(expected, runSql("SELECT wildcard_field FROM test"));
168+
}
169+
137170
/*
138171
* "long/integer/short/byte_field": {
139172
* "type": "long/integer/short/byte"

x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/CsvSpecTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public abstract class CsvSpecTestCase extends SpecBaseIntegrationTestCase {
3030
@ParametersFactory(argumentFormatting = PARAM_FORMATTING)
3131
public static List<Object[]> readScriptSpec() throws Exception {
3232
List<URL> urls = JdbcTestUtils.classpathResources("/*.csv-spec");
33-
assertTrue("Not enough specs found " + urls.toString(), urls.size() > 15);
33+
assertTrue("Not enough specs found (" + urls.size() + ") " + urls.toString(), urls.size() >= 23);
3434
return readScriptSpec(urls, specParser());
3535
}
3636

x-pack/plugin/sql/qa/server/src/main/java/org/elasticsearch/xpack/sql/qa/jdbc/DataLoader.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ private static void loadEmpDatasetIntoEs(RestClient client, String index, String
129129
if (extraFields) {
130130
createIndex.startObject("extra_gender").field("type", "constant_keyword").endObject();
131131
createIndex.startObject("null_constant").field("type", "constant_keyword").endObject();
132+
createIndex.startObject("wildcard_name").field("type", "wildcard").endObject();
132133
createIndex.startObject("extra.info.gender").field("type", "alias").field("path", "gender").endObject();
133134
}
134135

@@ -186,6 +187,8 @@ private static void loadEmpDatasetIntoEs(RestClient client, String index, String
186187

187188
boolean hadLastItem = false;
188189

190+
String wildcard_name = null;
191+
boolean setWildcardName = true;
189192
for (int f = 0; f < fields.size(); f++) {
190193
// an empty value in the csv file is treated as 'null', thus skipping it in the bulk request
191194
if (fields.get(f).trim().length() > 0) {
@@ -198,7 +201,19 @@ private static void loadEmpDatasetIntoEs(RestClient client, String index, String
198201
bulk.append(",\"extra_gender\":\"Female\"");
199202
}
200203
}
204+
if ((titles.get(f).equals("first_name") || titles.get(f).equals("last_name")) && extraFields && setWildcardName) {
205+
if (fields.get(f).trim().length() == 0) {
206+
setWildcardName = false;
207+
} else {
208+
wildcard_name = wildcard_name == null ? fields.get(f) : wildcard_name + " " + fields.get(f);
209+
}
210+
}
201211
}
212+
// append the wildcard field
213+
if (extraFields && setWildcardName) {
214+
bulk.append(",\"wildcard_name\":\"" + wildcard_name + "\"");
215+
}
216+
202217
// append department
203218
List<List<String>> list = dep_emp.get(emp_no);
204219
if (!list.isEmpty()) {

x-pack/plugin/sql/qa/server/src/main/resources/alias.csv-spec

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ last_name |VARCHAR |text
5252
last_name.keyword |VARCHAR |keyword
5353
null_constant |VARCHAR |keyword
5454
salary |INTEGER |integer
55+
wildcard_name |VARCHAR |keyword
5556
;
5657

5758
describePattern
@@ -81,6 +82,7 @@ last_name |VARCHAR |text
8182
last_name.keyword |VARCHAR |keyword
8283
null_constant |VARCHAR |keyword
8384
salary |INTEGER |integer
85+
wildcard_name |VARCHAR |keyword
8486
;
8587

8688
showAlias

0 commit comments

Comments
 (0)