This is an automated email from the ASF dual-hosted git repository.
rongr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pinot.git
The following commit(s) were added to refs/heads/master by this push:
new c124c6c2b7 [bugfix] fix placeholder resolution for scalar function
(#10050)
c124c6c2b7 is described below
commit c124c6c2b748d33c88549a5a5815534f6f3e28f4
Author: Rong Rong <[email protected]>
AuthorDate: Tue Jan 3 13:09:01 2023 -0800
[bugfix] fix placeholder resolution for scalar function (#10050)
* make a placeholder annotation for calcite function catalog
* adding dateTimeConvert placeholder
Co-authored-by: Rong Rong <[email protected]>
---
.../pinot/common/function/FunctionRegistry.java | 38 +++++++++++++++-------
.../function/InbuiltFunctionEvaluatorTest.java | 18 +++++++++-
.../pinot/query/runtime/QueryRunnerTest.java | 7 ++--
.../pinot/spi/annotations/ScalarFunction.java | 2 ++
4 files changed, 50 insertions(+), 15 deletions(-)
diff --git
a/pinot-common/src/main/java/org/apache/pinot/common/function/FunctionRegistry.java
b/pinot-common/src/main/java/org/apache/pinot/common/function/FunctionRegistry.java
index 86f7434204..4a5f2bb60d 100644
---
a/pinot-common/src/main/java/org/apache/pinot/common/function/FunctionRegistry.java
+++
b/pinot-common/src/main/java/org/apache/pinot/common/function/FunctionRegistry.java
@@ -72,10 +72,10 @@ public class FunctionRegistry {
boolean nullableParameters = scalarFunction.nullableParameters();
if (scalarFunctionNames.length > 0) {
for (String name : scalarFunctionNames) {
- FunctionRegistry.registerFunction(name, method,
nullableParameters);
+ FunctionRegistry.registerFunction(name, method,
nullableParameters, scalarFunction.isPlaceholder());
}
} else {
- FunctionRegistry.registerFunction(method, nullableParameters);
+ FunctionRegistry.registerFunction(method, nullableParameters,
scalarFunction.isPlaceholder());
}
}
}
@@ -94,15 +94,18 @@ public class FunctionRegistry {
/**
* Registers a method with the name of the method.
*/
- public static void registerFunction(Method method, boolean
nullableParameters) {
- registerFunction(method.getName(), method, nullableParameters);
+ public static void registerFunction(Method method, boolean
nullableParameters, boolean isPlaceholder) {
+ registerFunction(method.getName(), method, nullableParameters,
isPlaceholder);
}
/**
* Registers a method with the given function name.
*/
- public static void registerFunction(String functionName, Method method,
boolean nullableParameters) {
- registerFunctionInfoMap(functionName, method, nullableParameters);
+ public static void registerFunction(String functionName, Method method,
boolean nullableParameters,
+ boolean isPlaceholder) {
+ if (!isPlaceholder) {
+ registerFunctionInfoMap(functionName, method, nullableParameters);
+ }
registerCalciteNamedFunctionMap(functionName, method, nullableParameters);
}
@@ -161,33 +164,44 @@ public class FunctionRegistry {
*/
private static class PlaceholderScalarFunctions {
- @ScalarFunction(names = {"jsonExtractScalar", "json_extract_scalar"})
+ /**
+ * Noted that {@code dateTimeConvert} with String as first input is
actually supported.
+ *
+ * @see
org.apache.pinot.common.function.scalar.DateTimeConvert#dateTimeConvert(String,
String, String, String)
+ */
+ @ScalarFunction(names = {"dateTimeConvert", "date_time_convert"},
isPlaceholder = true)
+ public static String dateTimeConvert(long timeValueNumeric, String
inputFormatStr, String outputFormatStr,
+ String outputGranularityStr) {
+ throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
+ }
+
+ @ScalarFunction(names = {"jsonExtractScalar", "json_extract_scalar"},
isPlaceholder = true)
public static Object jsonExtractScalar(String jsonFieldName, String
jsonPath, String resultsType) {
throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
}
- @ScalarFunction(names = {"jsonExtractScalar", "json_extract_scalar"})
+ @ScalarFunction(names = {"jsonExtractScalar", "json_extract_scalar"},
isPlaceholder = true)
public static Object jsonExtractScalar(String jsonFieldName, String
jsonPath, String resultsType,
Object defaultValue) {
throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
}
- @ScalarFunction(names = {"jsonExtractKey", "json_extract_key"})
+ @ScalarFunction(names = {"jsonExtractKey", "json_extract_key"},
isPlaceholder = true)
public static String jsonExtractKey(String jsonFieldName, String jsonPath)
{
throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
}
- @ScalarFunction(names = {"textContains", "text_contains"})
+ @ScalarFunction(names = {"textContains", "text_contains"}, isPlaceholder =
true)
public static boolean textContains(String text, String pattern) {
throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
}
- @ScalarFunction(names = {"textMatch", "text_match"})
+ @ScalarFunction(names = {"textMatch", "text_match"}, isPlaceholder = true)
public static boolean textMatch(String text, String pattern) {
throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
}
- @ScalarFunction(names = {"jsonMatch", "json_match"})
+ @ScalarFunction(names = {"jsonMatch", "json_match"}, isPlaceholder = true)
public static boolean jsonMatch(String text, String pattern) {
throw new UnsupportedOperationException("Placeholder scalar function,
should not reach here");
}
diff --git
a/pinot-core/src/test/java/org/apache/pinot/core/data/function/InbuiltFunctionEvaluatorTest.java
b/pinot-core/src/test/java/org/apache/pinot/core/data/function/InbuiltFunctionEvaluatorTest.java
index 5c6835e293..82be9bcf52 100644
---
a/pinot-core/src/test/java/org/apache/pinot/core/data/function/InbuiltFunctionEvaluatorTest.java
+++
b/pinot-core/src/test/java/org/apache/pinot/core/data/function/InbuiltFunctionEvaluatorTest.java
@@ -30,6 +30,7 @@ import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
public class InbuiltFunctionEvaluatorTest {
@@ -130,7 +131,7 @@ public class InbuiltFunctionEvaluatorTest {
throws Exception {
MyFunc myFunc = new MyFunc();
Method method =
myFunc.getClass().getDeclaredMethod("appendToStringAndReturn", String.class);
- FunctionRegistry.registerFunction(method, false);
+ FunctionRegistry.registerFunction(method, false, false);
String expression = "appendToStringAndReturn('test ')";
InbuiltFunctionEvaluator evaluator = new
InbuiltFunctionEvaluator(expression);
assertTrue(evaluator.getArguments().isEmpty());
@@ -157,6 +158,21 @@ public class InbuiltFunctionEvaluatorTest {
}
}
+ @Test
+ public void testPlaceholderFunctionShouldNotBeRegistered()
+ throws Exception {
+ GenericRow row = new GenericRow();
+ row.putValue("testColumn", "testValue");
+ String expression = "text_match(testColumn, 'pattern')";
+ try {
+ InbuiltFunctionEvaluator evaluator = new
InbuiltFunctionEvaluator(expression);
+ evaluator.evaluate(row);
+ fail();
+ } catch (Throwable t) {
+ assertTrue(t.getMessage().contains("text_match"));
+ }
+ }
+
public static class MyFunc {
String _baseString = "";
diff --git
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
index 37c0ed05bb..abb7d65e4d 100644
---
a/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
+++
b/pinot-query-runtime/src/test/java/org/apache/pinot/query/runtime/QueryRunnerTest.java
@@ -266,9 +266,12 @@ public class QueryRunnerTest extends QueryRunnerTestBase {
new Object[]{"SELECT json_extract_key(col1, 'path') FROM a", "was
expecting (JSON String"},
// - PlaceholderScalarFunction registered will throw on intermediate
stage, but works on leaf stage.
+ // - checked "Illegal Json Path" as col1 is not actually a json
string, but the call is correctly triggered.
new Object[]{"SELECT CAST(jsonExtractScalar(col1, 'path', 'INT') AS
INT) FROM a", "Illegal Json Path"},
- new Object[]{"SELECT CAST(json_extract_scalar(a.col1, b.col2, 'INT')
AS INT) FROM a JOIN b ON a.col1 = b.col1",
- "PlaceholderScalarFunctions.jsonExtractScalar"},
+ // - checked function cannot be found b/c there's no intermediate
stage impl for json_extract_scalar
+ // TODO: re-enable this test once we have implemented constructor time
error pipe back.
+ // new Object[]{"SELECT CAST(json_extract_scalar(a.col1, b.col2,
'INT') AS INT)"
+ // + "FROM a JOIN b ON a.col1 = b.col1", "Cannot find function
with Name: json_extract_scalar"},
};
}
}
diff --git
a/pinot-spi/src/main/java/org/apache/pinot/spi/annotations/ScalarFunction.java
b/pinot-spi/src/main/java/org/apache/pinot/spi/annotations/ScalarFunction.java
index 6963c21b40..f0d14f7dd9 100644
---
a/pinot-spi/src/main/java/org/apache/pinot/spi/annotations/ScalarFunction.java
+++
b/pinot-spi/src/main/java/org/apache/pinot/spi/annotations/ScalarFunction.java
@@ -52,4 +52,6 @@ public @interface ScalarFunction {
// Whether the scalar function expects and can handle null arguments.
boolean nullableParameters() default false;
+
+ boolean isPlaceholder() default false;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]