Skip to content

Commit 1284c12

Browse files
authored
Support for OpenSearch alias type (#3246)
Signed-off-by: Heng Qian <qianheng@amazon.com>
1 parent b738faf commit 1284c12

17 files changed

Lines changed: 312 additions & 11 deletions

File tree

core/src/main/java/org/opensearch/sql/data/type/ExprType.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import java.util.Arrays;
1111
import java.util.List;
12+
import java.util.Optional;
1213
import org.opensearch.sql.data.model.ExprValue;
1314
import org.opensearch.sql.expression.Expression;
1415

@@ -54,4 +55,17 @@ default List<ExprType> getParent() {
5455
default String legacyTypeName() {
5556
return typeName();
5657
}
58+
59+
/** Get the original path. Types like alias type will set the actual path in field property. */
60+
default Optional<String> getOriginalPath() {
61+
return Optional.empty();
62+
}
63+
64+
/**
65+
* Get the original path. Types like alias type should be derived from the type of the original
66+
* field.
67+
*/
68+
default ExprType getOriginalExprType() {
69+
return this;
70+
}
5771
}

core/src/main/java/org/opensearch/sql/expression/ReferenceExpression.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
public class ReferenceExpression implements Expression {
2424
@Getter private final String attr;
2525

26+
@Getter private final String rawPath;
27+
2628
@Getter private final List<String> paths;
2729

2830
private final ExprType type;
@@ -36,8 +38,11 @@ public class ReferenceExpression implements Expression {
3638
public ReferenceExpression(String ref, ExprType type) {
3739
this.attr = ref;
3840
// Todo. the define of paths need to be redefined after adding multiple index/variable support.
39-
this.paths = Arrays.asList(ref.split("\\."));
40-
this.type = type;
41+
// For AliasType, the actual path is set in the property of `path` and the type is derived
42+
// from the type of field on that path; Otherwise, use ref itself as the path
43+
this.rawPath = type.getOriginalPath().orElse(ref);
44+
this.paths = Arrays.asList(rawPath.split("\\."));
45+
this.type = type.getOriginalExprType();
4146
}
4247

4348
@Override

core/src/test/java/org/opensearch/sql/data/type/ExprTypeTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static org.opensearch.sql.data.type.ExprCoreType.UNDEFINED;
2525
import static org.opensearch.sql.data.type.ExprCoreType.UNKNOWN;
2626

27+
import java.util.Optional;
2728
import org.hamcrest.Matchers;
2829
import org.junit.jupiter.api.Test;
2930

@@ -85,4 +86,16 @@ void defaultLegacyTypeName() {
8586
final ExprType exprType = () -> "dummy";
8687
assertEquals("dummy", exprType.legacyTypeName());
8788
}
89+
90+
@Test
91+
void getOriginalPath() {
92+
final ExprType exprType = () -> "dummy";
93+
assertEquals(Optional.empty(), exprType.getOriginalPath());
94+
}
95+
96+
@Test
97+
void getOriginalExprType() {
98+
final ExprType exprType = () -> "dummy";
99+
assertEquals(exprType, exprType.getOriginalExprType());
100+
}
88101
}

integ-test/src/test/java/org/opensearch/sql/legacy/SQLIntegTestCase.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static com.google.common.base.Strings.isNullOrEmpty;
99
import static org.opensearch.sql.legacy.TestUtils.createIndexByRestClient;
1010
import static org.opensearch.sql.legacy.TestUtils.getAccountIndexMapping;
11+
import static org.opensearch.sql.legacy.TestUtils.getAliasIndexMapping;
1112
import static org.opensearch.sql.legacy.TestUtils.getBankIndexMapping;
1213
import static org.opensearch.sql.legacy.TestUtils.getBankWithNullValuesIndexMapping;
1314
import static org.opensearch.sql.legacy.TestUtils.getDataTypeNonnumericIndexMapping;
@@ -751,7 +752,12 @@ public enum Index {
751752
TestsConstants.TEST_INDEX_JSON_TEST,
752753
"json",
753754
getJsonTestIndexMapping(),
754-
"src/test/resources/json_test.json");
755+
"src/test/resources/json_test.json"),
756+
DATA_TYPE_ALIAS(
757+
TestsConstants.TEST_INDEX_ALIAS,
758+
"alias",
759+
getAliasIndexMapping(),
760+
"src/test/resources/alias.json");
755761

756762
private final String name;
757763
private final String type;

integ-test/src/test/java/org/opensearch/sql/legacy/TestUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,11 @@ public static String getJsonTestIndexMapping() {
255255
return getMappingFile(mappingFile);
256256
}
257257

258+
public static String getAliasIndexMapping() {
259+
String mappingFile = "alias_index_mapping.json";
260+
return getMappingFile(mappingFile);
261+
}
262+
258263
public static void loadBulk(Client client, String jsonPath, String defaultIndex)
259264
throws Exception {
260265
System.out.println(String.format("Loading file %s into opensearch cluster", jsonPath));

integ-test/src/test/java/org/opensearch/sql/legacy/TestsConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public class TestsConstants {
5959
public static final String TEST_INDEX_NESTED_WITH_NULLS = TEST_INDEX + "_nested_with_nulls";
6060
public static final String TEST_INDEX_GEOPOINT = TEST_INDEX + "_geopoint";
6161
public static final String TEST_INDEX_JSON_TEST = TEST_INDEX + "_json_test";
62+
public static final String TEST_INDEX_ALIAS = TEST_INDEX + "_alias";
6263
public static final String DATASOURCES = ".ql-datasources";
6364

6465
public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

integ-test/src/test/java/org/opensearch/sql/ppl/DataTypeIT.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55

66
package org.opensearch.sql.ppl;
77

8+
import static org.opensearch.sql.legacy.SQLIntegTestCase.Index.DATA_TYPE_ALIAS;
89
import static org.opensearch.sql.legacy.SQLIntegTestCase.Index.DATA_TYPE_NONNUMERIC;
910
import static org.opensearch.sql.legacy.SQLIntegTestCase.Index.DATA_TYPE_NUMERIC;
11+
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_ALIAS;
1012
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NONNUMERIC;
1113
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_DATATYPE_NUMERIC;
1214
import static org.opensearch.sql.util.MatcherUtils.schema;
@@ -22,6 +24,7 @@ public class DataTypeIT extends PPLIntegTestCase {
2224
public void init() throws IOException {
2325
loadIndex(DATA_TYPE_NUMERIC);
2426
loadIndex(DATA_TYPE_NONNUMERIC);
27+
loadIndex(DATA_TYPE_ALIAS);
2528
}
2629

2730
@Test
@@ -75,4 +78,14 @@ public void test_long_integer_data_type() throws IOException {
7578
schema("long1", "long"),
7679
schema("long2", "long"));
7780
}
81+
82+
@Test
83+
public void test_alias_data_type() throws IOException {
84+
JSONObject result =
85+
executeQuery(
86+
String.format(
87+
"source=%s | where alias_col > 1 " + "| fields original_col, alias_col ",
88+
TEST_INDEX_ALIAS));
89+
verifySchema(result, schema("original_col", "integer"), schema("alias_col", "integer"));
90+
}
7891
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{"index":{"_id":"1"}}
2+
{"original_col" : 1}
3+
{"index":{"_id":"2"}}
4+
{"original_col" : 2}
5+
{"index":{"_id":"3"}}
6+
{"original_col" : 3}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"mappings": {
3+
"properties": {
4+
"original_col": {
5+
"type": "integer"
6+
},
7+
"alias_col": {
8+
"type": "alias",
9+
"path": "original_col"
10+
}
11+
}
12+
}
13+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.opensearch.data.type;
7+
8+
import java.util.List;
9+
import java.util.Optional;
10+
import java.util.Set;
11+
import org.opensearch.sql.data.type.ExprType;
12+
13+
/**
14+
* The type of alias. See <a
15+
* href="https://opensearch.org/docs/latest/opensearch/supported-field-types/alias/">doc</a>
16+
*/
17+
public class OpenSearchAliasType extends OpenSearchDataType {
18+
19+
public static final String typeName = "alias";
20+
public static final String pathPropertyName = "path";
21+
public static final Set<MappingType> objectFieldTypes =
22+
Set.of(MappingType.Object, MappingType.Nested);
23+
private final String path;
24+
private final OpenSearchDataType originalType;
25+
26+
public OpenSearchAliasType(String path, OpenSearchDataType type) {
27+
super(type.getExprCoreType());
28+
if (type instanceof OpenSearchAliasType) {
29+
throw new IllegalStateException(
30+
String.format("Alias field cannot refer to the path [%s] of alias type", path));
31+
} else if (objectFieldTypes.contains(type.getMappingType())) {
32+
throw new IllegalStateException(
33+
String.format("Alias field cannot refer to the path [%s] of object type", path));
34+
}
35+
this.path = path;
36+
this.originalType = type;
37+
}
38+
39+
@Override
40+
public Optional<String> getOriginalPath() {
41+
return Optional.of(this.path);
42+
}
43+
44+
@Override
45+
public ExprType getOriginalExprType() {
46+
return originalType.getExprType();
47+
}
48+
49+
@Override
50+
public ExprType getExprType() {
51+
return this;
52+
}
53+
54+
@Override
55+
public OpenSearchDataType cloneEmpty() {
56+
return new OpenSearchAliasType(this.path, originalType.cloneEmpty());
57+
}
58+
59+
@Override
60+
public boolean isCompatible(ExprType other) {
61+
return originalType.isCompatible(other);
62+
}
63+
64+
@Override
65+
public List<ExprType> getParent() {
66+
return originalType.getParent();
67+
}
68+
69+
@Override
70+
public String typeName() {
71+
return originalType.typeName();
72+
}
73+
74+
@Override
75+
public String legacyTypeName() {
76+
return originalType.legacyTypeName();
77+
}
78+
79+
@Override
80+
public boolean shouldCast(ExprType other) {
81+
return originalType.shouldCast(other);
82+
}
83+
}

0 commit comments

Comments
 (0)