Skip to content

Commit

Permalink
Merge branch 'main' into feature/json-extract
Browse files Browse the repository at this point in the history
Signed-off-by: Kenrick Yap <[email protected]>

# Conflicts:
#	core/src/main/java/org/opensearch/sql/expression/DSL.java
#	core/src/main/java/org/opensearch/sql/expression/function/BuiltinFunctionName.java
#	core/src/main/java/org/opensearch/sql/expression/json/JsonFunctions.java
#	core/src/main/java/org/opensearch/sql/utils/JsonUtils.java
#	core/src/test/java/org/opensearch/sql/expression/json/JsonFunctionsTest.java
#	docs/user/ppl/functions/json.rst
#	integ-test/src/test/java/org/opensearch/sql/ppl/JsonFunctionsIT.java
#	integ-test/src/test/resources/json_test.json
#	ppl/src/main/antlr/OpenSearchPPLLexer.g4
#	ppl/src/main/antlr/OpenSearchPPLParser.g4
  • Loading branch information
kenrickyap committed Feb 12, 2025
2 parents b6ae5ba + 5aa86d7 commit adde88d
Show file tree
Hide file tree
Showing 79 changed files with 600 additions and 2,548 deletions.
2 changes: 0 additions & 2 deletions DEVELOPER_GUIDE.rst
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ The plugin codebase is in standard layout of Gradle project::
├── plugin
├── protocol
├── ppl
├── spark
├── sql
├── sql-cli
├── sql-jdbc
Expand All @@ -161,7 +160,6 @@ Here are sub-folders (Gradle modules) for plugin source code:
- ``core``: core query engine.
- ``opensearch``: OpenSearch storage engine.
- ``prometheus``: Prometheus storage engine.
- ``spark`` : Spark storage engine
- ``protocol``: request/response protocol formatter.
- ``common``: common util code.
- ``integ-test``: integration and comparison test.
Expand Down
2 changes: 1 addition & 1 deletion async-query-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ dependencies {
antlr "org.antlr:antlr4:4.7.1"

implementation project(':core')
implementation project(':spark') // TODO: dependency to spark should be eliminated
implementation project(':datasources') // TODO: dependency to datasources should be eliminated
implementation 'org.json:json:20231013'
implementation 'com.google.code.gson:gson:2.8.9'
api group: 'com.amazonaws', name: 'aws-java-sdk-emrserverless', version: "${aws_java_sdk_version}"

testImplementation(platform("org.junit:junit-bom:5.9.3"))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public enum FunctionType {
CSV("CSV"),
MISC("Misc"),
GENERATOR("Generator"),
OTHER("Other"),
UDF("User Defined Function");

private final String name;
Expand Down Expand Up @@ -422,6 +423,51 @@ public enum FunctionType {
"posexplode",
"posexplode_outer",
"stack"))
.put(
OTHER,
Set.of(
"aggregate",
"array_size",
"array_sort",
"cardinality",
"crc32",
"exists",
"filter",
"forall",
"hash",
"ilike",
"in",
"like",
"map_filter",
"map_zip_with",
"md5",
"mod",
"named_struct",
"parse_url",
"raise_error",
"reduce",
"reverse",
"sha",
"sha1",
"sha2",
"size",
"struct",
"transform",
"transform_keys",
"transform_values",
"url_decode",
"url_encode",
"xpath",
"xpath_boolean",
"xpath_double",
"xpath_float",
"xpath_int",
"xpath_long",
"xpath_number",
"xpath_short",
"xpath_string",
"xxhash64",
"zip_with"))
.build();

private static final Map<String, FunctionType> FUNCTION_NAME_TO_FUNCTION_TYPE_MAP =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public enum SQLGrammarElement implements GrammarElement {
CSV_FUNCTIONS("CSV functions"),
GENERATOR_FUNCTIONS("Generator functions"),
MISC_FUNCTIONS("Misc functions"),
OTHER_FUNCTIONS("Other functions"),

// UDF
UDF("User Defined functions");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,26 +560,30 @@ public Void visitFunctionName(FunctionNameContext ctx) {
return super.visitFunctionName(ctx);
}

private void validateFunctionAllowed(String function) {
FunctionType type = FunctionType.fromFunctionName(function.toLowerCase());
private void validateFunctionAllowed(String functionName) {
String lowerCaseFunctionName = functionName.toLowerCase();
FunctionType type = FunctionType.fromFunctionName(lowerCaseFunctionName);
switch (type) {
case MAP:
validateAllowed(SQLGrammarElement.MAP_FUNCTIONS);
validateAllowed(SQLGrammarElement.MAP_FUNCTIONS, lowerCaseFunctionName);
break;
case BITWISE:
validateAllowed(SQLGrammarElement.BITWISE_FUNCTIONS);
validateAllowed(SQLGrammarElement.BITWISE_FUNCTIONS, lowerCaseFunctionName);
break;
case CSV:
validateAllowed(SQLGrammarElement.CSV_FUNCTIONS);
validateAllowed(SQLGrammarElement.CSV_FUNCTIONS, lowerCaseFunctionName);
break;
case MISC:
validateAllowed(SQLGrammarElement.MISC_FUNCTIONS);
validateAllowed(SQLGrammarElement.MISC_FUNCTIONS, lowerCaseFunctionName);
break;
case GENERATOR:
validateAllowed(SQLGrammarElement.GENERATOR_FUNCTIONS);
validateAllowed(SQLGrammarElement.GENERATOR_FUNCTIONS, lowerCaseFunctionName);
break;
case OTHER:
validateAllowed(SQLGrammarElement.OTHER_FUNCTIONS, lowerCaseFunctionName);
break;
case UDF:
validateAllowed(SQLGrammarElement.UDF);
validateAllowed(SQLGrammarElement.UDF, lowerCaseFunctionName);
break;
}
}
Expand All @@ -590,6 +594,12 @@ private void validateAllowed(SQLGrammarElement element) {
}
}

private void validateAllowed(SQLGrammarElement element, String detail) {
if (!grammarElementValidator.isValid(element)) {
throw new IllegalArgumentException(String.format("%s (%s) is not allowed.", element, detail));
}
}

@Override
public Void visitErrorCapturingIdentifier(ErrorCapturingIdentifierContext ctx) {
ErrorCapturingIdentifierExtraContext extra = ctx.errorCapturingIdentifierExtra();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.spark.data.type;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;

class SparkDataTypeTest {

@Test
void testTypeName() {
String expectedTypeName = "spark_string";
SparkDataType sparkDataType = new SparkDataType(expectedTypeName);

assertEquals(
expectedTypeName, sparkDataType.typeName(), "Type name should match the expected value");
}

@Test
void testEqualsAndHashCode() {
SparkDataType type1 = new SparkDataType("spark_integer");
SparkDataType type2 = new SparkDataType("spark_integer");
SparkDataType type3 = new SparkDataType("spark_double");

assertEquals(type1, type2);
assertNotEquals(type1, type3);
assertEquals(type1.hashCode(), type2.hashCode());
assertNotEquals(type1.hashCode(), type3.hashCode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.spark.data.value;

import static org.junit.jupiter.api.Assertions.*;

import org.junit.jupiter.api.Test;
import org.opensearch.sql.spark.data.type.SparkDataType;

class SparkExprValueTest {
private final SparkDataType sparkDataType = new SparkDataType("char");

@Test
public void getters() {
SparkExprValue sparkExprValue = new SparkExprValue(sparkDataType, "str");

assertEquals(sparkDataType, sparkExprValue.type());
assertEquals("str", sparkExprValue.value());
}

@Test
public void unsupportedCompare() {
SparkExprValue sparkExprValue = new SparkExprValue(sparkDataType, "str");

assertThrows(UnsupportedOperationException.class, () -> sparkExprValue.compare(sparkExprValue));
}

@Test
public void testEquals() {
SparkExprValue sparkExprValue1 = new SparkExprValue(sparkDataType, "str");
SparkExprValue sparkExprValue2 = new SparkExprValue(sparkDataType, "str");
SparkExprValue sparkExprValue3 = new SparkExprValue(sparkDataType, "other");

assertTrue(sparkExprValue1.equal(sparkExprValue2));
assertFalse(sparkExprValue1.equal(sparkExprValue3));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

package org.opensearch.sql.spark.functions.response;

import static org.junit.jupiter.api.Assertions.*;

import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.opensearch.sql.data.model.ExprBooleanValue;
import org.opensearch.sql.data.model.ExprByteValue;
import org.opensearch.sql.data.model.ExprDateValue;
import org.opensearch.sql.data.model.ExprDoubleValue;
import org.opensearch.sql.data.model.ExprFloatValue;
import org.opensearch.sql.data.model.ExprIntegerValue;
import org.opensearch.sql.data.model.ExprLongValue;
import org.opensearch.sql.data.model.ExprShortValue;
import org.opensearch.sql.data.model.ExprStringValue;
import org.opensearch.sql.data.model.ExprTimestampValue;
import org.opensearch.sql.data.model.ExprValue;
import org.opensearch.sql.executor.ExecutionEngine;
import org.opensearch.sql.executor.ExecutionEngine.Schema.Column;

class DefaultSparkSqlFunctionResponseHandleTest {

@Test
public void testConstruct() throws Exception {
DefaultSparkSqlFunctionResponseHandle handle =
new DefaultSparkSqlFunctionResponseHandle(readJson());

assertTrue(handle.hasNext());
ExprValue value = handle.next();
Map<String, ExprValue> row = value.tupleValue();
assertEquals(ExprBooleanValue.of(true), row.get("col1"));
assertEquals(new ExprLongValue(2), row.get("col2"));
assertEquals(new ExprIntegerValue(3), row.get("col3"));
assertEquals(new ExprShortValue(4), row.get("col4"));
assertEquals(new ExprByteValue(5), row.get("col5"));
assertEquals(new ExprDoubleValue(6.1), row.get("col6"));
assertEquals(new ExprFloatValue(7.1), row.get("col7"));
assertEquals(new ExprTimestampValue("2024-01-02 03:04:05.1234"), row.get("col8"));
assertEquals(new ExprDateValue("2024-01-03 04:05:06.1234"), row.get("col9"));
assertEquals(new ExprStringValue("some string"), row.get("col10"));

ExecutionEngine.Schema schema = handle.schema();
List<Column> columns = schema.getColumns();
assertEquals("col1", columns.get(0).getName());
}

private JSONObject readJson() throws Exception {
final URL url =
DefaultSparkSqlFunctionResponseHandle.class.getResource(
"/spark_execution_result_test.json");
return new JSONObject(Files.readString(Paths.get(url.toURI())));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ void testExtractionFromFlintSkippingIndexQueries() {
+ " WHERE elb_status_code = 500 "
+ " WITH (auto_refresh = true)",
"DROP SKIPPING INDEX ON myS3.default.alb_logs",
"ALTER SKIPPING INDEX ON myS3.default.alb_logs WITH (auto_refresh = false)",
"ALTER SKIPPING INDEX ON myS3.default.alb_logs WITH (auto_refresh = false)"
};

for (String query : createSkippingIndexQueries) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public void test() {
assertEquals(FunctionType.MISC, FunctionType.fromFunctionName("version"));
assertEquals(FunctionType.GENERATOR, FunctionType.fromFunctionName("explode"));
assertEquals(FunctionType.GENERATOR, FunctionType.fromFunctionName("stack"));
assertEquals(FunctionType.OTHER, FunctionType.fromFunctionName("aggregate"));
assertEquals(FunctionType.OTHER, FunctionType.fromFunctionName("forall"));
assertEquals(FunctionType.UDF, FunctionType.fromFunctionName("unknown"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private String[] addPrefix(String... queries) {
void testAllowAllByDefault() {
when(mockedProvider.getValidatorForDatasource(any()))
.thenReturn(new DefaultGrammarElementValidator());
VerifyValidator v = new VerifyValidator(pplQueryValidator, DataSourceType.SPARK);
VerifyValidator v = new VerifyValidator(pplQueryValidator, DataSourceType.S3GLUE);
Arrays.stream(PPLQueryValidatorTest.TestElement.values()).forEach(v::ok);
}

Expand Down Expand Up @@ -127,7 +127,7 @@ public TestPPLGrammarElementValidator() {
void testCwlValidator() {
when(mockedProvider.getValidatorForDatasource(any()))
.thenReturn(new TestPPLGrammarElementValidator());
VerifyValidator v = new VerifyValidator(pplQueryValidator, DataSourceType.SPARK);
VerifyValidator v = new VerifyValidator(pplQueryValidator, DataSourceType.S3GLUE);

v.ok(TestElement.FIELDS);
v.ok(TestElement.WHERE);
Expand Down
Loading

0 comments on commit adde88d

Please sign in to comment.