Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PPL command expression implementation for geoip #3228

Merged
merged 78 commits into from
Jan 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
de5f3a5
Update grammar structure
andy-k-improving Dec 24, 2024
b0ff56e
Inteception points
andy-k-improving Dec 24, 2024
6533e21
Update dummy map values
andy-k-improving Dec 25, 2024
90ef4eb
Test
andy-k-improving Dec 25, 2024
e46a3c9
Geo integration
andy-k-improving Dec 25, 2024
0677050
Read ipString from user
andy-k-improving Dec 30, 2024
1f7f507
Read option from user input
andy-k-improving Dec 30, 2024
f7b6fed
Update changes
andy-k-improving Dec 31, 2024
bb6b672
Support multiple method signature
andy-k-improving Dec 31, 2024
9f3051d
Update result map format
andy-k-improving Dec 31, 2024
039c8c2
Code cleanup
andy-k-improving Dec 31, 2024
7341606
Spotless
andy-k-improving Dec 31, 2024
f1294b1
JavaDoc
andy-k-improving Dec 31, 2024
d68bdd0
Spotless
andy-k-improving Dec 31, 2024
151afd6
Update unit test
andy-k-improving Dec 31, 2024
8647055
Update unit-test wording
andy-k-improving Dec 31, 2024
6338b87
Update unit test for eval
andy-k-improving Jan 1, 2025
a59b6a7
Update doc
andy-k-improving Jan 1, 2025
5e72d0a
Unit test
andy-k-improving Jan 3, 2025
fe0c363
Unit-test 1
andy-k-improving Jan 3, 2025
a166f13
Update ipenrichment test-case
andy-k-improving Jan 4, 2025
7fa70fa
Update test-cases
andy-k-improving Jan 4, 2025
4826e69
Update gradle
andy-k-improving Jan 6, 2025
4bf98a3
Geo plugin test case
andy-k-improving Jan 7, 2025
ab80496
Comment out security plugin
andy-k-improving Jan 8, 2025
9e6f2b9
Geo ip index load
andy-k-improving Jan 9, 2025
53896cf
Update integ with data content assert
andy-k-improving Jan 9, 2025
e4ec572
Integ test for geoip
andy-k-improving Jan 9, 2025
675ebc9
Remove debug
andy-k-improving Jan 9, 2025
4cdd458
Gradle task refactor
andy-k-improving Jan 9, 2025
307c000
Remove duplicated urlDownload
andy-k-improving Jan 9, 2025
204b8b1
Refactor gradle script
andy-k-improving Jan 9, 2025
ab46a91
Refactor integ test
andy-k-improving Jan 9, 2025
8503176
Separate sscurity plugin test
andy-k-improving Jan 9, 2025
2ecd20c
Refactor gradle file
andy-k-improving Jan 9, 2025
03c5df6
Infer type
andy-k-improving Jan 10, 2025
1488034
Update java doc
andy-k-improving Jan 10, 2025
185ab9a
Simplifier provider
andy-k-improving Jan 10, 2025
ad9764c
Update test cases
andy-k-improving Jan 10, 2025
aa8abe5
Spotless check
andy-k-improving Jan 10, 2025
6c193de
Github action for GeoSpatial build
andy-k-improving Jan 10, 2025
3276f1f
Execlude geoip doc test
andy-k-improving Jan 10, 2025
02da983
Fix test
andy-k-improving Jan 10, 2025
15a196b
Test coverage
andy-k-improving Jan 11, 2025
ba8c1fc
Style fix
andy-k-improving Jan 11, 2025
f31b8c8
Update test caess
andy-k-improving Jan 13, 2025
b2bd6b0
Minimise diff
andy-k-improving Jan 13, 2025
cd4c5ea
Fix spot
andy-k-improving Jan 13, 2025
8bd98e8
Rebase
andy-k-improving Jan 21, 2025
eeefc50
Update test-cases
andy-k-improving Jan 22, 2025
058eaab
Update diff
andy-k-improving Jan 22, 2025
68396d9
Typo
andy-k-improving Jan 22, 2025
e5407bd
Update spotless
andy-k-improving Jan 22, 2025
738602e
Minimise diff
andy-k-improving Jan 22, 2025
cfd9970
Minimise diff
andy-k-improving Jan 22, 2025
e92ba96
Remove duplicated method
andy-k-improving Jan 22, 2025
43b3c93
Separate logic
andy-k-improving Jan 22, 2025
180822c
Spotless
andy-k-improving Jan 22, 2025
ccac16e
Update Java doc
andy-k-improving Jan 22, 2025
7019452
Doc fix
andy-k-improving Jan 22, 2025
41e99c6
Simplify Integtest
andy-k-improving Jan 22, 2025
a826375
Update doc
andy-k-improving Jan 22, 2025
11f8bad
Spotless
andy-k-improving Jan 22, 2025
9b735aa
Update comment
andy-k-improving Jan 22, 2025
c74f3fd
Update unitTest
andy-k-improving Jan 23, 2025
d981332
Update existing integTest
andy-k-improving Jan 23, 2025
241ea63
Spotless
andy-k-improving Jan 23, 2025
66e17ce
Doc fix
andy-k-improving Jan 28, 2025
3d79741
Address code reivews
andy-k-improving Jan 28, 2025
c3a9348
Update diff
andy-k-improving Jan 28, 2025
89f33e5
Minimise diff
andy-k-improving Jan 28, 2025
11abfd6
Update test-cases
andy-k-improving Jan 28, 2025
b77d557
Update docs/user/ppl/functions/ip.rst
andy-k-improving Jan 28, 2025
1b41d5f
Update opensearch/src/main/java/org/opensearch/sql/opensearch/planner…
andy-k-improving Jan 28, 2025
694b08c
Update spotless
andy-k-improving Jan 28, 2025
ebc451a
Update coverage
andy-k-improving Jan 29, 2025
fbcaf0d
Spotless
andy-k-improving Jan 29, 2025
96cc6f6
Update log
andy-k-improving Jan 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions core/src/main/java/org/opensearch/sql/expression/DSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,10 @@ public static FunctionExpression utc_timestamp(
return compile(functionProperties, BuiltinFunctionName.UTC_TIMESTAMP, args);
}

public static FunctionExpression geoip(Expression... args) {
return compile(FunctionProperties.None, BuiltinFunctionName.GEOIP, args);
}

@SuppressWarnings("unchecked")
private static <T extends FunctionImplementation> T compile(
FunctionProperties functionProperties, BuiltinFunctionName bfn, Expression... args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ public enum BuiltinFunctionName {
/** Json Functions. */
JSON_VALID(FunctionName.of("json_valid")),

/** GEOSPATIAL Functions. */
GEOIP(FunctionName.of("geoip")),

/** NULL Test. */
IS_NULL(FunctionName.of("is null")),
IS_NOT_NULL(FunctionName.of("is not null")),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,4 +173,54 @@ public String toString() {
return String.format("%s(%s)", functionName, String.join(", ", args));
}
}

/**
* Static class to identify functional Expression which specifically designed for OpenSearch
* storage runtime
*/
public static class OpenSearchExecutableFunction extends FunctionExpression {
private final FunctionName functionName;
private final List<Expression> arguments;
private final ExprType returnType;

public OpenSearchExecutableFunction(
FunctionName functionName, List<Expression> arguments, ExprType returnType) {
super(functionName, arguments);
this.functionName = functionName;
this.arguments = arguments;
this.returnType = returnType;
}

@Override
public ExprValue valueOf(Environment<Expression, ExprValue> valueEnv) {
throw new UnsupportedOperationException(
String.format(
"OpenSearch defined function [%s] is only supported in Eval operation.",
functionName));
}

@Override
public ExprType type() {
return returnType;
}

/**
* Util method to generate probe implementation with given list of argument types, with marker
* class `OpenSearchFunction` to annotate this is an OpenSearch specific expression.
*
* @param returnType return type.
* @return Binary Function Implementation.
*/
public static SerializableFunction<FunctionName, Pair<FunctionSignature, FunctionBuilder>>
openSearchImpl(ExprType returnType, List<ExprType> args) {
return functionName -> {
FunctionSignature functionSignature = new FunctionSignature(functionName, args);
FunctionBuilder functionBuilder =
(functionProperties, arguments) ->
new OpenSearchFunctions.OpenSearchExecutableFunction(
functionName, arguments, returnType);
return Pair.of(functionSignature, functionBuilder);
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import static org.opensearch.sql.expression.function.FunctionDSL.define;
import static org.opensearch.sql.expression.function.FunctionDSL.impl;
import static org.opensearch.sql.expression.function.FunctionDSL.nullMissingHandling;
import static org.opensearch.sql.expression.function.OpenSearchFunctions.OpenSearchExecutableFunction.openSearchImpl;

import inet.ipaddr.IPAddress;
import java.util.Arrays;
import lombok.experimental.UtilityClass;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.data.model.ExprValueUtils;
Expand All @@ -28,6 +30,7 @@ public class IPFunctions {

public void register(BuiltinFunctionRepository repository) {
repository.register(cidrmatch());
repository.register(geoIp());
}

private DefaultFunctionResolver cidrmatch() {
Expand Down Expand Up @@ -57,4 +60,16 @@ private ExprValue exprCidrMatch(ExprValue addressExprValue, ExprValue rangeExprV
? ExprValueUtils.LITERAL_FALSE
: ExprValueUtils.LITERAL_TRUE;
}

/**
* To register all method signatures related to geoip( ) expression under eval.
*
* @return Resolver for geoip( ) expression.
*/
private DefaultFunctionResolver geoIp() {
return define(
BuiltinFunctionName.GEOIP.getName(),
openSearchImpl(BOOLEAN, Arrays.asList(STRING, STRING)),
openSearchImpl(BOOLEAN, Arrays.asList(STRING, STRING, STRING)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public ExprValue next() {
* @param env {@link Environment}
* @return The mapping of reference and {@link ExprValue} for each expression.
*/
private Map<String, ExprValue> eval(Environment<Expression, ExprValue> env) {
protected Map<String, ExprValue> eval(Environment<Expression, ExprValue> env) {
Map<String, ExprValue> evalResultMap = new LinkedHashMap<>();
for (Pair<ReferenceExpression, Expression> pair : expressionList) {
ReferenceExpression var = pair.getKey();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.opensearch.sql.expression.ExpressionTestBase;
import org.opensearch.sql.expression.FunctionExpression;
import org.opensearch.sql.expression.NamedArgumentExpression;
import org.opensearch.sql.expression.ReferenceExpression;
import org.opensearch.sql.expression.env.Environment;

public class OpenSearchFunctionsTest extends ExpressionTestBase {
Expand Down Expand Up @@ -309,4 +310,17 @@ void nested_query() {
assertEquals(expr.valueOf(nestedTuple), ExprValueUtils.stringValue("result"));
assertEquals(expr.type(), STRING);
}

@Test
void opensearchExecutableFunction_valueOf() {
var ipInStr =
new OpenSearchFunctions.OpenSearchExecutableFunction(
BuiltinFunctionName.GEOIP.getName(),
List.of(DSL.literal("my-datasource"), new ReferenceExpression("ipInStr", STRING)),
BOOLEAN);
assertThrows(
UnsupportedOperationException.class,
() -> ipInStr.valueOf(valueEnv()),
"OpenSearch defined function [geoip] is only supported in Eval operation.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.expression.ip;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.opensearch.sql.data.type.ExprCoreType.BOOLEAN;
import static org.opensearch.sql.data.type.ExprCoreType.STRING;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.expression.DSL;
import org.opensearch.sql.expression.Expression;
import org.opensearch.sql.expression.env.Environment;

@ExtendWith(MockitoExtension.class)
public class GeoIPFunctionTest {

// Mock value environment for testing.
@Mock private Environment<Expression, ExprValue> env;

@Test
public void testGeoipFunctionSignature() {
var geoip = DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING));
assertEquals(BOOLEAN, geoip.type());
}

/** To make sure no logic being evaluated when no environment being passed. */
@Test
public void testDefaultValueOf() {
UnsupportedOperationException exception =
assertThrows(
UnsupportedOperationException.class,
() ->
DSL.geoip(DSL.literal("HARDCODED_DATASOURCE_NAME"), DSL.ref("ip_address", STRING))
.valueOf(env));
assertTrue(
exception
.getMessage()
.contains("OpenSearch defined function [geoip] is only supported in Eval operation."));
}
}
31 changes: 31 additions & 0 deletions docs/user/ppl/functions/ip.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,34 @@ Note:
- `cidr` can be an IPv4 or IPv6 block
- `ip` and `cidr` must both be valid and non-missing/non-null


GEOIP
---------

Description
>>>>>>>>>>>

Usage: `geoip(dataSourceName, ipAddress[, options])` to lookup location information from given IP addresses via OpenSearch GeoSpatial plugin API.

Argument type: STRING, STRING, STRING

Return type: OBJECT

.. The execution of below example is being excluded, as this requires a standalone Geo-Spatial dataSource setup, which is not yet supported by docTest.

Example:

> source=weblogs | eval LookupResult = geoip("dataSourceName", "50.68.18.229", "country_iso_code,city_name")
fetched rows / total rows = 1/1
+-------------------------------------------------------------+
| LookupResult |
|-------------------------------------------------------------|
| {'city_name': 'Vancouver', 'country_iso_code': 'CA'} |
+-------------------------------------------------------------+


Note:
- `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/
- `ip` can be an IPv4 or an IPv6 address
- `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"

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static org.opensearch.sql.legacy.TestUtils.getDogs3IndexMapping;
import static org.opensearch.sql.legacy.TestUtils.getEmployeeNestedTypeIndexMapping;
import static org.opensearch.sql.legacy.TestUtils.getGameOfThronesIndexMapping;
import static org.opensearch.sql.legacy.TestUtils.getGeoIpIndexMapping;
import static org.opensearch.sql.legacy.TestUtils.getGeopointIndexMapping;
import static org.opensearch.sql.legacy.TestUtils.getJoinTypeIndexMapping;
import static org.opensearch.sql.legacy.TestUtils.getJsonTestIndexMapping;
Expand Down Expand Up @@ -627,6 +628,11 @@ public enum Index {
"unexpandedObject",
getUnexpandedObjectIndexMapping(),
"src/test/resources/unexpanded_objects.json"),
GEOIP(
TestsConstants.TEST_INDEX_GEOIP,
"geoip",
getGeoIpIndexMapping(),
"src/test/resources/geoip.json"),
BANK(
TestsConstants.TEST_INDEX_BANK,
"account",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ public static String getBankIndexMapping() {
return getMappingFile(mappingFile);
}

public static String getGeoIpIndexMapping() {
String mappingFile = "geoip_index_mapping.json";
return getMappingFile(mappingFile);
}

public static String getBankWithNullValuesIndexMapping() {
String mappingFile = "bank_with_null_values_index_mapping.json";
return getMappingFile(mappingFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class TestsConstants {
public static final String TEST_INDEX_GEOPOINT = TEST_INDEX + "_geopoint";
public static final String TEST_INDEX_JSON_TEST = TEST_INDEX + "_json_test";
public static final String TEST_INDEX_ALIAS = TEST_INDEX + "_alias";
public static final String TEST_INDEX_GEOIP = TEST_INDEX + "_geoip";
public static final String DATASOURCES = ".ql-datasources";

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