diff --git a/fe/fe-core/src/main/java/com/starrocks/connector/parser/BaseComplexFunctionCallTransformer.java b/fe/fe-core/src/main/java/com/starrocks/connector/parser/BaseComplexFunctionCallTransformer.java new file mode 100644 index 00000000000000..714cfd0011998a --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/connector/parser/BaseComplexFunctionCallTransformer.java @@ -0,0 +1,22 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.starrocks.connector.parser; + +import com.starrocks.analysis.Expr; + + +public abstract class BaseComplexFunctionCallTransformer { + + protected abstract Expr transform(String functionName, Expr... args); +} diff --git a/fe/fe-core/src/main/java/com/starrocks/connector/parser/BaseFunctionCallTransformer.java b/fe/fe-core/src/main/java/com/starrocks/connector/parser/BaseFunctionCallTransformer.java new file mode 100644 index 00000000000000..ca0fa56f202b05 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/connector/parser/BaseFunctionCallTransformer.java @@ -0,0 +1,100 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.starrocks.connector.parser; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.starrocks.analysis.Expr; +import com.starrocks.analysis.FunctionCallExpr; + +import java.util.List; +import java.util.Map; + +public abstract class BaseFunctionCallTransformer { + public static Map> TRANSFORMER_MAP = Maps.newHashMap(); + + public BaseFunctionCallTransformer() { + registerAllFunctionTransformer(); + } + + protected abstract void registerAllFunctionTransformer(); + + protected abstract Expr convert(String fnName, List children); + + public static Expr convertRegisterFn(String fnName, List children) { + List transformers = TRANSFORMER_MAP.get(fnName); + if (transformers == null) { + return null; + } + + FunctionCallTransformer matcher = null; + for (FunctionCallTransformer transformer : transformers) { + if (transformer.match(children)) { + matcher = transformer; + } + } + if (matcher == null) { + return null; + } + return matcher.transform(children); + } + + protected static FunctionCallExpr buildStarRocksFunctionCall(String starRocksFnName, + List> starRocksArgumentsClass) { + List arguments = Lists.newArrayList(); + for (int index = 0; index < starRocksArgumentsClass.size(); ++index) { + // For a FunctionCallExpr, do not know the actual arguments here, so we use a PlaceholderExpr to replace it. + arguments.add(new PlaceholderExpr(index + 1, starRocksArgumentsClass.get(index))); + } + return new FunctionCallExpr(starRocksFnName, arguments); + } + + + protected static void registerFunctionTransformer(String originFnName, int originFnArgNums, String starRocksFnName, + List> starRocksArgumentsClass) { + FunctionCallExpr starRocksFunctionCall = buildStarRocksFunctionCall(starRocksFnName, starRocksArgumentsClass); + registerFunctionTransformer(originFnName, originFnArgNums, starRocksFunctionCall); + } + + protected static void registerFunctionTransformer(String originFnName, String starRocksFnName) { + FunctionCallExpr starRocksFunctionCall = buildStarRocksFunctionCall(starRocksFnName, Lists.newArrayList()); + registerFunctionTransformer(originFnName, 0, starRocksFunctionCall); + } + + protected static void registerFunctionTransformerWithVarArgs(String originFnName, String starRocksFnName, + List> starRocksArgumentsClass) { + Preconditions.checkState(starRocksArgumentsClass.size() == 1); + FunctionCallExpr starRocksFunctionCall = buildStarRocksFunctionCall(starRocksFnName, starRocksArgumentsClass); + registerFunctionTransformerWithVarArgs(originFnName, starRocksFunctionCall); + } + + protected static void registerFunctionTransformer(String originFnName, int originFnArgNums, + FunctionCallExpr starRocksFunctionCall) { + FunctionCallTransformer transformer = new FunctionCallTransformer(starRocksFunctionCall, originFnArgNums); + + List transformerList = TRANSFORMER_MAP.computeIfAbsent(originFnName, + k -> Lists.newArrayList()); + transformerList.add(transformer); + } + + protected static void registerFunctionTransformerWithVarArgs(String originFnName, FunctionCallExpr starRocksFunctionCall) { + FunctionCallTransformer transformer = new FunctionCallTransformer(starRocksFunctionCall, true); + + List transformerList = TRANSFORMER_MAP.computeIfAbsent(originFnName, + k -> Lists.newArrayList()); + transformerList.add(transformer); + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/FunctionCallTransformer.java b/fe/fe-core/src/main/java/com/starrocks/connector/parser/FunctionCallTransformer.java similarity index 99% rename from fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/FunctionCallTransformer.java rename to fe/fe-core/src/main/java/com/starrocks/connector/parser/FunctionCallTransformer.java index f6ce80b30c11b2..c5fe16cd2dd75f 100644 --- a/fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/FunctionCallTransformer.java +++ b/fe/fe-core/src/main/java/com/starrocks/connector/parser/FunctionCallTransformer.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.starrocks.connector.parser.trino; +package com.starrocks.connector.parser; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; diff --git a/fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/PlaceholderExpr.java b/fe/fe-core/src/main/java/com/starrocks/connector/parser/PlaceholderExpr.java similarity index 96% rename from fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/PlaceholderExpr.java rename to fe/fe-core/src/main/java/com/starrocks/connector/parser/PlaceholderExpr.java index a9205345126340..d31b8339b31b32 100644 --- a/fe/fe-core/src/main/java/com/starrocks/connector/parser/trino/PlaceholderExpr.java +++ b/fe/fe-core/src/main/java/com/starrocks/connector/parser/PlaceholderExpr.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.starrocks.connector.parser.trino; +package com.starrocks.connector.parser; import com.starrocks.analysis.Expr; import com.starrocks.sql.ast.AstVisitor; diff --git a/fe/fe-core/src/main/java/com/starrocks/connector/parser/pinot/AstBuilder.java b/fe/fe-core/src/main/java/com/starrocks/connector/parser/pinot/AstBuilder.java new file mode 100644 index 00000000000000..eaacbe808b6511 --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/connector/parser/pinot/AstBuilder.java @@ -0,0 +1,74 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.starrocks.connector.parser.pinot; + +import com.starrocks.analysis.ArithmeticExpr; +import com.starrocks.analysis.Expr; +import com.starrocks.analysis.FunctionCallExpr; +import com.starrocks.analysis.FunctionName; +import com.starrocks.analysis.FunctionParams; +import com.starrocks.analysis.HintNode; +import com.starrocks.analysis.IntLiteral; +import com.starrocks.analysis.ParseNode; +import com.starrocks.sql.parser.NodePosition; +import com.starrocks.sql.parser.StarRocksParser; +import com.starrocks.sql.parser.SyntaxSugars; +import org.antlr.v4.runtime.ParserRuleContext; + +import java.util.IdentityHashMap; +import java.util.List; + +public class AstBuilder extends com.starrocks.sql.parser.AstBuilder { + + protected AstBuilder(long sqlMode) { + super(sqlMode); + } + + public AstBuilder(long sqlMode, IdentityHashMap> hintMap) { + super(sqlMode, hintMap); + } + + @Override + public ParseNode visitFunctionCallExpression(StarRocksParser.FunctionCallExpressionContext ctx) { + return visitChildren(ctx); + } + + public ParseNode visitSimpleFunctionCall(StarRocksParser.SimpleFunctionCallContext context) { + String fullFunctionName = getQualifiedName(context.qualifiedName()).toString(); + NodePosition pos = createPos(context); + + List arguments = visit(context.expression(), Expr.class); + FunctionName fnName = FunctionName.createFnName(fullFunctionName); + String functionName = fnName.getFunction(); + + Pinot2SRFunctionCallTransformer transformer = new Pinot2SRFunctionCallTransformer(); + Expr convertedFunctionCall = transformer.convert(functionName, arguments); + + if (convertedFunctionCall != null) { + if (functionName.equalsIgnoreCase("fromdatetime")) { + ArithmeticExpr toMillis = new ArithmeticExpr(ArithmeticExpr.Operator.MULTIPLY, + convertedFunctionCall, new IntLiteral(1000)); + return toMillis; + } + return convertedFunctionCall; + } else { + FunctionCallExpr functionCallExpr = new FunctionCallExpr(fnName, + new FunctionParams(false, arguments), pos); + if (context.over() != null) { + return buildOverClause(functionCallExpr, context.over(), pos); + } + return SyntaxSugars.parse(functionCallExpr); + } + } +} diff --git a/fe/fe-core/src/main/java/com/starrocks/connector/parser/pinot/ComplexFunctionCallTransformer.java b/fe/fe-core/src/main/java/com/starrocks/connector/parser/pinot/ComplexFunctionCallTransformer.java new file mode 100644 index 00000000000000..f788321de9842c --- /dev/null +++ b/fe/fe-core/src/main/java/com/starrocks/connector/parser/pinot/ComplexFunctionCallTransformer.java @@ -0,0 +1,287 @@ +// Copyright 2021-present StarRocks, Inc. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package com.starrocks.connector.parser.pinot; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.starrocks.analysis.ArithmeticExpr; +import com.starrocks.analysis.CompoundPredicate; +import com.starrocks.analysis.DecimalLiteral; +import com.starrocks.analysis.Expr; +import com.starrocks.analysis.FunctionCallExpr; +import com.starrocks.analysis.FunctionParams; +import com.starrocks.analysis.IntLiteral; +import com.starrocks.analysis.StringLiteral; +import com.starrocks.catalog.FunctionSet; +import com.starrocks.catalog.Type; +import com.starrocks.connector.parser.BaseComplexFunctionCallTransformer; +import com.starrocks.sql.analyzer.SemanticException; +import com.starrocks.sql.ast.IntervalLiteral; +import com.starrocks.sql.ast.UnitIdentifier; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ComplexFunctionCallTransformer extends BaseComplexFunctionCallTransformer { + + @Override + public Expr transform(String functionName, Expr... args) { + List argumentsList = Arrays.asList(args); + + if (functionName.equalsIgnoreCase("datetimeconvert")) { + return transformDateTimeConvert(argumentsList); + } else if (functionName.equalsIgnoreCase("datetrunc")) { + return transformDateTrunc(argumentsList); + } else if (functionName.equalsIgnoreCase("text_match")) { + return transformTextMatch(argumentsList); + } + + return null; + } + + private static Expr transformDateTimeConvert(List args) { + if (args.size() < 4 || args.size() > 5) { + throw new SemanticException("The datetimeconvert function must include between 4 and 5 parameters, inclusive."); + } + // DATETIMECONVERT(columnName, inputFormat, outputFormat, outputGranularity) + // DATETIMECONVERT(columnName, inputFormat, outputFormat, outputGranularity, timeZone) + // format is