Skip to content

Commit b66f91b

Browse files
authored
Merge branch 'main' into feature/acarbo_json_cast_ppl
Signed-off-by: Andrew Carbonetto <[email protected]>
2 parents 25b0f90 + a2cb2a3 commit b66f91b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1062
-71
lines changed

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/DSL.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,10 @@ public static FunctionExpression utc_timestamp(
981981
return compile(functionProperties, BuiltinFunctionName.UTC_TIMESTAMP, args);
982982
}
983983

984+
public static FunctionExpression geoip(Expression... args) {
985+
return compile(FunctionProperties.None, BuiltinFunctionName.GEOIP, args);
986+
}
987+
984988
@SuppressWarnings("unchecked")
985989
private static <T extends FunctionImplementation> T compile(
986990
FunctionProperties functionProperties, BuiltinFunctionName bfn, Expression... args) {

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/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ public enum BuiltinFunctionName {
208208
JSON_VALID(FunctionName.of("json_valid")),
209209
JSON(FunctionName.of("json")),
210210

211+
/** GEOSPATIAL Functions. */
212+
GEOIP(FunctionName.of("geoip")),
213+
211214
/** NULL Test. */
212215
IS_NULL(FunctionName.of("is null")),
213216
IS_NOT_NULL(FunctionName.of("is not null")),

core/src/main/java/org/opensearch/sql/expression/function/OpenSearchFunctions.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,4 +173,54 @@ public String toString() {
173173
return String.format("%s(%s)", functionName, String.join(", ", args));
174174
}
175175
}
176+
177+
/**
178+
* Static class to identify functional Expression which specifically designed for OpenSearch
179+
* storage runtime
180+
*/
181+
public static class OpenSearchExecutableFunction extends FunctionExpression {
182+
private final FunctionName functionName;
183+
private final List<Expression> arguments;
184+
private final ExprType returnType;
185+
186+
public OpenSearchExecutableFunction(
187+
FunctionName functionName, List<Expression> arguments, ExprType returnType) {
188+
super(functionName, arguments);
189+
this.functionName = functionName;
190+
this.arguments = arguments;
191+
this.returnType = returnType;
192+
}
193+
194+
@Override
195+
public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) {
196+
throw new UnsupportedOperationException(
197+
String.format(
198+
"OpenSearch defined function [%s] is only supported in Eval operation.",
199+
functionName));
200+
}
201+
202+
@Override
203+
public ExprType type() {
204+
return returnType;
205+
}
206+
207+
/**
208+
* Util method to generate probe implementation with given list of argument types, with marker
209+
* class `OpenSearchFunction` to annotate this is an OpenSearch specific expression.
210+
*
211+
* @param returnType return type.
212+
* @return Binary Function Implementation.
213+
*/
214+
public static SerializableFunction<FunctionName, Pair<FunctionSignature, FunctionBuilder>>
215+
openSearchImpl(ExprType returnType, List<ExprType> args) {
216+
return functionName -> {
217+
FunctionSignature functionSignature = new FunctionSignature(functionName, args);
218+
FunctionBuilder functionBuilder =
219+
(functionProperties, arguments) ->
220+
new OpenSearchFunctions.OpenSearchExecutableFunction(
221+
functionName, arguments, returnType);
222+
return Pair.of(functionSignature, functionBuilder);
223+
};
224+
}
225+
}
176226
}

core/src/main/java/org/opensearch/sql/expression/ip/IPFunctions.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
import static org.opensearch.sql.expression.function.FunctionDSL.define;
1212
import static org.opensearch.sql.expression.function.FunctionDSL.impl;
1313
import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling;
14+
import static org.opensearch.sql.expression.function.OpenSearchFunctions.OpenSearchExecutableFunction.openSearchImpl;
1415

1516
import inet.ipaddr.IPAddress;
17+
import java.util.Arrays;
1618
import lombok.experimental.UtilityClass;
1719
import org.opensearch.sql.data.model.ExprValue;
1820
import org.opensearch.sql.data.model.ExprValueUtils;
@@ -28,6 +30,7 @@ public class IPFunctions {
2830

2931
public void register(BuiltinFunctionRepository repository) {
3032
repository.register(cidrmatch());
33+
repository.register(geoIp());
3134
}
3235

3336
private DefaultFunctionResolver cidrmatch() {
@@ -57,4 +60,16 @@ private ExprValue exprCidrMatch(ExprValue addressExprValue, ExprValue rangeExprV
5760
? ExprValueUtils.LITERAL_FALSE
5861
: ExprValueUtils.LITERAL_TRUE;
5962
}
63+
64+
/**
65+
* To register all method signatures related to geoip( ) expression under eval.
66+
*
67+
* @return Resolver for geoip( ) expression.
68+
*/
69+
private DefaultFunctionResolver geoIp() {
70+
return define(
71+
BuiltinFunctionName.GEOIP.getName(),
72+
openSearchImpl(BOOLEAN, Arrays.asList(STRING, STRING)),
73+
openSearchImpl(BOOLEAN, Arrays.asList(STRING, STRING, STRING)));
74+
}
6075
}

core/src/main/java/org/opensearch/sql/planner/physical/EvalOperator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public ExprValue next() {
8787
* @param env {@link Environment}
8888
* @return The mapping of reference and {@link ExprValue} for each expression.
8989
*/
90-
private Map<String, ExprValue> eval(Environment<Expression, ExprValue> env) {
90+
protected Map<String, ExprValue> eval(Environment<Expression, ExprValue> env) {
9191
Map<String, ExprValue> evalResultMap = new LinkedHashMap<>();
9292
for (Pair<ReferenceExpression, Expression> pair : expressionList) {
9393
ReferenceExpression var = pair.getKey();

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
}

core/src/test/java/org/opensearch/sql/expression/function/OpenSearchFunctionsTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.opensearch.sql.expression.ExpressionTestBase;
2323
import org.opensearch.sql.expression.FunctionExpression;
2424
import org.opensearch.sql.expression.NamedArgumentExpression;
25+
import org.opensearch.sql.expression.ReferenceExpression;
2526
import org.opensearch.sql.expression.env.Environment;
2627

2728
public class OpenSearchFunctionsTest extends ExpressionTestBase {
@@ -309,4 +310,17 @@ void nested_query() {
309310
assertEquals(expr.valueOf(nestedTuple), ExprValueUtils.stringValue("result"));
310311
assertEquals(expr.type(), STRING);
311312
}
313+
314+
@Test
315+
void opensearchExecutableFunction_valueOf() {
316+
var ipInStr =
317+
new OpenSearchFunctions.OpenSearchExecutableFunction(
318+
BuiltinFunctionName.GEOIP.getName(),
319+
List.of(DSL.literal("my-datasource"), new ReferenceExpression("ipInStr", STRING)),
320+
BOOLEAN);
321+
assertThrows(
322+
UnsupportedOperationException.class,
323+
() -> ipInStr.valueOf(valueEnv()),
324+
"OpenSearch defined function [geoip] is only supported in Eval operation.");
325+
}
312326
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.expression.ip;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertThrows;
10+
import static org.junit.jupiter.api.Assertions.assertTrue;
11+
import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN;
12+
import static org.opensearch.sql.data.type.ExprCoreType.STRING;
13+
14+
import org.junit.jupiter.api.Test;
15+
import org.junit.jupiter.api.extension.ExtendWith;
16+
import org.mockito.Mock;
17+
import org.mockito.junit.jupiter.MockitoExtension;
18+
import org.opensearch.sql.data.model.ExprValue;
19+
import org.opensearch.sql.expression.DSL;
20+
import org.opensearch.sql.expression.Expression;
21+
import org.opensearch.sql.expression.env.Environment;
22+
23+
@ExtendWith(MockitoExtension.class)
24+
public class GeoIPFunctionTest {
25+
26+
// Mock value environment for testing.
27+
@Mock private Environment<Expression, ExprValue> env;
28+
29+
@Test
30+
public void testGeoipFunctionSignature() {
31+
var geoip = DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING));
32+
assertEquals(BOOLEAN, geoip.type());
33+
}
34+
35+
/** To make sure no logic being evaluated when no environment being passed. */
36+
@Test
37+
public void testDefaultValueOf() {
38+
UnsupportedOperationException exception =
39+
assertThrows(
40+
UnsupportedOperationException.class,
41+
() ->
42+
DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING))
43+
.valueOf(env));
44+
assertTrue(
45+
exception
46+
.getMessage()
47+
.contains("OpenSearch defined function [geoip] is only supported in Eval operation."));
48+
}
49+
}

docs/dev/datasource-prometheus.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ Since we don't have column names similar to relational databases, `@timestamp` a
175175

176176
### Passthrough PromQL Support.
177177
* PromQL is easy to use powerful language over metrics and we want to support promQL queries from catalogs with prometheus connectors.
178-
* Function signature: source = ``promcatalog.nativeQuery(`promQLCommand`, startTime = "{{startTime}}", endTime="{{endTime}", step="{{resolution}}")``
178+
* Function signature: source = ``promcatalog.nativeQuery(`promQLCommand`, startTime = "{{startTime}}", endTime="{{endTime}}", step="{{resolution}}")``
179179

180180

181181

docs/user/ppl/functions/ip.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,34 @@ Note:
3636
- `cidr` can be an IPv4 or IPv6 block
3737
- `ip` and `cidr` must both be valid and non-missing/non-null
3838

39+
40+
GEOIP
41+
---------
42+
43+
Description
44+
>>>>>>>>>>>
45+
46+
Usage: `geoip(dataSourceName, ipAddress[, options])` to lookup location information from given IP addresses via OpenSearch GeoSpatial plugin API.
47+
48+
Argument type: STRING, STRING, STRING
49+
50+
Return type: OBJECT
51+
52+
.. The execution of below example is being excluded, as this requires a standalone Geo-Spatial dataSource setup, which is not yet supported by docTest.
53+
54+
Example:
55+
56+
> source=weblogs | eval LookupResult = geoip("dataSourceName", "50.68.18.229", "country_iso_code,city_name")
57+
fetched rows / total rows = 1/1
58+
+-------------------------------------------------------------+
59+
| LookupResult |
60+
|-------------------------------------------------------------|
61+
| {'city_name': 'Vancouver', 'country_iso_code': 'CA'} |
62+
+-------------------------------------------------------------+
63+
64+
65+
Note:
66+
- `dataSourceName` must be an established dataSource on OpenSearch GeoSpatial plugin, detail of configuration can be found: https://opensearch.org/docs/latest/ingest-pipelines/processors/ip2geo/
67+
- `ip` can be an IPv4 or an IPv6 address
68+
- `options` is an optional String of comma separated fields to output: the selection of fields is subject to dataSourceProvider's schema. For example, the list of fields in the provided `geolite2-city` dataset includes: "country_iso_code", "country_name", "continent_name", "region_iso_code", "region_name", "city_name", "time_zone", "location"
69+

0 commit comments

Comments
 (0)