Skip to content

Commit bdd42bc

Browse files
authored
Update GEOIP function to support IP types as input (#4613)
Signed-off-by: Yuanchun Shen <yuanchu@amazon.com>
1 parent 60b7d98 commit bdd42bc

File tree

4 files changed

+61
-19
lines changed

4 files changed

+61
-19
lines changed

docs/user/ppl/functions/ip.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Description
4545

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

48-
Argument type: STRING, STRING, STRING
48+
Argument type: STRING, STRING/IP, STRING
4949

5050
Return type: OBJECT
5151

integ-test/src/test/java/org/opensearch/sql/calcite/remote/CalciteGeoIpFunctionsIT.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,52 @@
55

66
package org.opensearch.sql.calcite.remote;
77

8+
import static org.opensearch.sql.legacy.TestsConstants.TEST_INDEX_WEBLOGS;
9+
import static org.opensearch.sql.util.MatcherUtils.rows;
10+
import static org.opensearch.sql.util.MatcherUtils.schema;
11+
import static org.opensearch.sql.util.MatcherUtils.verifyDataRows;
12+
import static org.opensearch.sql.util.MatcherUtils.verifySchema;
13+
14+
import java.io.IOException;
15+
import java.util.Map;
16+
import org.json.JSONObject;
17+
import org.junit.jupiter.api.Test;
18+
import org.opensearch.client.Request;
819
import org.opensearch.sql.ppl.GeoIpFunctionsIT;
920

1021
public class CalciteGeoIpFunctionsIT extends GeoIpFunctionsIT {
1122
@Override
1223
public void init() throws Exception {
1324
super.init();
25+
loadIndex(Index.WEBLOG);
1426
enableCalcite();
27+
28+
// Only limited IPs are loaded into geospatial data sources. Therefore, we insert IPs that match
29+
// those known ones for test purpose
30+
Request bulkRequest = new Request("POST", "/_bulk?refresh=true");
31+
bulkRequest.setJsonEntity(
32+
String.format(
33+
"{\"index\":{\"_index\":\"%s\",\"_id\":6}}\n"
34+
+ "{\"host\":\"10.0.0.1\",\"method\":\"POST\"}\n"
35+
+ "{\"index\":{\"_index\":\"%s\",\"_id\":7}}\n"
36+
+ "{\"host\":\"fd12:2345:6789:1:a1b2:c3d4:e5f6:789a\",\"method\":\"POST\"}\n",
37+
TEST_INDEX_WEBLOGS, TEST_INDEX_WEBLOGS));
38+
client().performRequest(bulkRequest);
39+
}
40+
41+
// In v2 it supports only string as IP inputs
42+
@Test
43+
public void testGeoIpEnrichmentWithIpFieldAsInput() throws IOException {
44+
JSONObject result =
45+
executeQuery(
46+
String.format(
47+
"source=%s | where method='POST' | eval ip_to_country = geoip('%s', host,"
48+
+ " 'country') | fields host, ip_to_country",
49+
TEST_INDEX_WEBLOGS, DATASOURCE_NAME));
50+
verifySchema(result, schema("host", "ip"), schema("ip_to_country", "struct"));
51+
verifyDataRows(
52+
result,
53+
rows("10.0.0.1", Map.of("country", "USA")),
54+
rows("fd12:2345:6789:1:a1b2:c3d4:e5f6:789a", Map.of("country", "India")));
1555
}
1656
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class GeoIpFunctionsIT extends PPLIntegTestCase {
4040
"endpoint",
4141
"https://raw.githubusercontent.com/opensearch-project/geospatial/main/src/test/resources/ip2geo/server/city/manifest.json");
4242

43-
private static String DATASOURCE_NAME = "dummycityindex";
43+
protected static String DATASOURCE_NAME = "dummycityindex";
4444

4545
private static String PLUGIN_NAME = "opensearch-geospatial";
4646

@@ -83,7 +83,7 @@ public void testGeoIpEnrichment() {
8383
String.format(
8484
"search source=%s | eval enrichmentResult = geoip(\\\"%s\\\",%s) | fields name, ip,"
8585
+ " enrichmentResult",
86-
TEST_INDEX_GEOIP, "dummycityindex", "ip"));
86+
TEST_INDEX_GEOIP, DATASOURCE_NAME, "ip"));
8787

8888
verifyColumn(resultGeoIp, columnName("name"), columnName("ip"), columnName("enrichmentResult"));
8989
verifyDataRows(
@@ -101,7 +101,7 @@ public void testGeoIpEnrichmentWithSingleOption() {
101101
String.format(
102102
"search source=%s | eval enrichmentResult = geoip(\\\"%s\\\",%s,\\\"%s\\\") |"
103103
+ " fields name, ip, enrichmentResult",
104-
TEST_INDEX_GEOIP, "dummycityindex", "ip", "city"));
104+
TEST_INDEX_GEOIP, DATASOURCE_NAME, "ip", "city"));
105105

106106
verifyColumn(resultGeoIp, columnName("name"), columnName("ip"), columnName("enrichmentResult"));
107107
verifyDataRows(
@@ -119,7 +119,7 @@ public void testGeoIpEnrichmentWithSpaceSeparatedMultipleOptions() {
119119
String.format(
120120
"search source=%s | eval enrichmentResult = geoip(\\\"%s\\\",%s,\\\"%s\\\") |"
121121
+ " fields name, ip, enrichmentResult",
122-
TEST_INDEX_GEOIP, "dummycityindex", "ip", "city , country"));
122+
TEST_INDEX_GEOIP, DATASOURCE_NAME, "ip", "city , country"));
123123

124124
verifyColumn(resultGeoIp, columnName("name"), columnName("ip"), columnName("enrichmentResult"));
125125
verifyDataRows(

opensearch/src/main/java/org/opensearch/sql/opensearch/functions/GeoIpFunction.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,15 @@
1616
import org.apache.calcite.rel.type.RelDataType;
1717
import org.apache.calcite.rel.type.RelDataTypeFactory;
1818
import org.apache.calcite.rex.RexCall;
19-
import org.apache.calcite.sql.type.CompositeOperandTypeChecker;
20-
import org.apache.calcite.sql.type.OperandTypes;
2119
import org.apache.calcite.sql.type.SqlReturnTypeInference;
22-
import org.apache.calcite.sql.type.SqlTypeFamily;
2320
import org.apache.calcite.sql.type.SqlTypeName;
2421
import org.opensearch.geospatial.action.IpEnrichmentActionClient;
2522
import org.opensearch.sql.common.utils.StringUtils;
23+
import org.opensearch.sql.data.model.ExprIpValue;
2624
import org.opensearch.sql.data.model.ExprStringValue;
2725
import org.opensearch.sql.data.model.ExprTupleValue;
2826
import org.opensearch.sql.data.model.ExprValue;
27+
import org.opensearch.sql.data.type.ExprCoreType;
2928
import org.opensearch.sql.expression.function.ImplementorUDF;
3029
import org.opensearch.sql.expression.function.UDFOperandMetadata;
3130
import org.opensearch.transport.client.node.NodeClient;
@@ -38,8 +37,8 @@
3837
* <p>Signatures:
3938
*
4039
* <ul>
41-
* <li>(STRING, STRING) -> MAP
42-
* <li>(STRING, STRING, STRING) -> MAP
40+
* <li>(STRING, IP) -> MAP
41+
* <li>(STRING, IP, STRING) -> MAP
4342
* </ul>
4443
*/
4544
public class GeoIpFunction extends ImplementorUDF {
@@ -59,11 +58,10 @@ public SqlReturnTypeInference getReturnTypeInference() {
5958

6059
@Override
6160
public UDFOperandMetadata getOperandMetadata() {
62-
return UDFOperandMetadata.wrap(
63-
(CompositeOperandTypeChecker)
64-
OperandTypes.CHARACTER_CHARACTER.or(
65-
OperandTypes.family(
66-
SqlTypeFamily.CHARACTER, SqlTypeFamily.CHARACTER, SqlTypeFamily.CHARACTER)));
61+
return UDFOperandMetadata.wrapUDT(
62+
List.of(
63+
List.of(ExprCoreType.STRING, ExprCoreType.IP),
64+
List.of(ExprCoreType.STRING, ExprCoreType.IP, ExprCoreType.STRING)));
6765
}
6866

6967
public static class GeoIPImplementor implements NotNullImplementor {
@@ -87,16 +85,20 @@ public Expression implement(
8785
}
8886

8987
public static Map<String, ?> fetchIpEnrichment(
90-
String dataSource, String ipAddress, NodeClient nodeClient) {
91-
return fetchIpEnrichment(dataSource, ipAddress, Collections.emptySet(), nodeClient);
88+
String dataSource, ExprIpValue ipAddress, NodeClient nodeClient) {
89+
return fetchIpEnrichment(
90+
dataSource, ipAddress.toString(), Collections.emptySet(), nodeClient);
9291
}
9392

9493
public static Map<String, ?> fetchIpEnrichment(
95-
String dataSource, String ipAddress, String commaSeparatedOptions, NodeClient nodeClient) {
94+
String dataSource,
95+
ExprIpValue ipAddress,
96+
String commaSeparatedOptions,
97+
NodeClient nodeClient) {
9698
String unquotedOptions = StringUtils.unquoteText(commaSeparatedOptions);
9799
final Set<String> options =
98100
Arrays.stream(unquotedOptions.split(",")).map(String::trim).collect(Collectors.toSet());
99-
return fetchIpEnrichment(dataSource, ipAddress, options, nodeClient);
101+
return fetchIpEnrichment(dataSource, ipAddress.toString(), options, nodeClient);
100102
}
101103

102104
private static Map<String, ?> fetchIpEnrichment(

0 commit comments

Comments
 (0)