github-actions[bot] commented on code in PR #68579:
URL: https://github.com/apache/doris/pull/68579#discussion_r4220686217


##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SplitByRegexp.java:
##########
@@ -79,9 +80,13 @@ public SplitByRegexp withChildren(List<Expression> children) 
{
     public void checkLegalityBeforeTypeCoercion() {
         List<Expression> arguments = getArguments();
         if (arguments.size() == 3) {
-            Expression thirdArgument = getArgument(2);
-            if (!thirdArgument.isConstant() || !(thirdArgument instanceof 
IntegerLikeLiteral)
-                    || (((IntegerLikeLiteral) thirdArgument).getIntValue() < 
0)) {
+            // validate the value FE can evaluate here, because constant 
folding may remove this function before
+            // any later check; the type is checked before the type coercion 
casts the argument to the INT
+            // signature, and the value of a constant FE cannot fold is 
validated by BE when it is evaluated
+            Expression thirdArgument = 
ExpressionUtils.foldConstantArgument(getArgument(2));
+            if (!thirdArgument.isConstant() || 
!thirdArgument.getDataType().isIntegralType()
+                    || (thirdArgument instanceof IntegerLikeLiteral

Review Comment:
   [P2] Reject a typed NULL split limit before treating it as a valid constant. 
`split_by_regexp('a,b', ',', CAST(NULL AS INT))` folds to 
`NullLiteral(IntegerType)`, so it passes the new constant and integral checks 
but skips the `IntegerLikeLiteral` range check. `PropagateNullable` then 
returns NULL, whereas this call was rejected before this PR and a bare NULL 
limit is still rejected. Handle `NullLiteral` explicitly here, as the SHA2 
length check does, and cover the typed-NULL case.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DateTrunc.java:
##########
@@ -62,13 +63,57 @@ private DateTrunc(ScalarFunctionParams functionParams) {
         super(functionParams);
     }
 
+    @Override
+    public Expression prepareBeforeTypeCoercion() {
+        // When an argument is a date, the other one is the time unit, and the 
signature does not need its value.
+        if (getArgument(0).getDataType().isDateLikeType() || 
getArgument(1).getDataType().isDateLikeType()) {
+            return this;
+        }
+        // Otherwise customSignature tells the time unit from the date value 
by the literal time unit, so fold a
+        // constant string that evaluates to a time unit, unless the other 
argument already is one. A string date
+        // value is kept unfolded, because folding it would change the derived 
return type.
+        return withChildren((argument, index) -> {
+            if (!argument.getDataType().isStringLikeType() || 
isTimeUnit(getArgument(1 - index))) {
+                return argument;
+            }
+            Expression folded = ExpressionUtils.foldConstantArgument(argument);
+            return isTimeUnit(folded) ? folded : argument;
+        });
+    }
+
+    private static boolean isTimeUnit(Expression expression) {
+        return expression instanceof StringLikeLiteral
+                && LEGAL_TIME_UNIT.contains(((StringLikeLiteral) 
expression).getStringValue().toLowerCase());
+    }
+
+    private static boolean isConstantString(Expression expression) {
+        return expression.isConstant() && 
expression.getDataType().isStringLikeType();
+    }
+
     @Override
     public void checkLegalityBeforeTypeCoercion() {
         boolean firstArgIsStringLiteral =
                 getArgument(0).isConstant() && getArgument(0) instanceof 
StringLikeLiteral;
         boolean secondArgIsStringLiteral =
                 getArgument(1).isConstant() && getArgument(1) instanceof 
StringLikeLiteral;
         if (!firstArgIsStringLiteral && !secondArgIsStringLiteral) {
+            for (int i = 0; i < 2; i++) {
+                // The other argument is the time unit when this one is a 
date-typed value, or when this one
+                // is simply nonconstant (e.g. a VARCHAR date column) and the 
other side can only be the unit.
+                boolean thisArgIsDateRole = 
getArgument(i).getDataType().isDateLikeType()
+                        || !getArgument(i).isConstant();

Review Comment:
   [P2] Accept a BE-only unit beside a constant string date. 
`date_trunc('2024-03-15', lpad('nth', 5, 'mo'))` has an evaluated unit of 
`month`, but the sole FE literal is the date string. This role inference covers 
nonconstant string dates only, so the later branch treats the date as the unit 
and rejects it; the literal `'month'` succeeds. An FE-foldable date expression 
such as `concat('2024-03-15', '')` also fails because preparation keeps it 
nonliteral and the new loop sees two constants. Handle this date role in both 
argument orders and in `customSignature`, preserving timezone type selection.



##########
be/src/exprs/function/function_regexp.cpp:
##########
@@ -404,69 +398,108 @@ class FunctionRegexpReplace : public IFunction {
         for (int i = 0; i < 3; ++i) {
             col_const[i] = 
is_column_const(*block.get_by_position(arguments[i]).column);
         }
-        argument_columns[0] = col_const[0] ? static_cast<const ColumnConst&>(
-                                                     
*block.get_by_position(arguments[0]).column)
-                                                     .convert_to_full_column()
-                                           : 
block.get_by_position(arguments[0]).column;
+        const auto& [source_column, source_const] =
+                unpack_if_const(block.get_by_position(arguments[0]).column);
+        argument_columns[0] = source_column;
 
         default_preprocess_parameter_columns(argument_columns, col_const, {1, 
2}, block, arguments);
 
+        if constexpr (std::is_same_v<FourParamTypes, ParamTypes>) {
+            // The regex of a constant pattern was not compiled in open 
because the options were
+            // not evaluated there. Compile it once with the options of the 
first row.
+            // Gate this on the query-level constant-ness of the pattern (as 
open() does), not on
+            // col_const[1]: a lazy join can broadcast a non-constant probe 
pattern as a physical
+            // ColumnConst for one block, which would otherwise cache that 
block's pattern and
+            // wrongly reuse it for later blocks with a different pattern 
value.
+            if (context->is_col_constant(1) && !context->is_col_constant(3) &&
+                input_rows_count > 0 &&
+                context->get_function_state(FunctionContext::THREAD_LOCAL) == 
nullptr) {
+                RETURN_IF_ERROR(compile_constant_pattern(
+                        context, argument_columns[1]->get_data_at(0),
+                        
block.get_by_position(arguments[3]).column->get_data_at(0)));
+            }
+        }
+
         StringRef options_value;
         if (col_const[1] && col_const[2]) {
-            Impl::execute_impl_const_args(context, argument_columns, 
options_value,
+            Impl::execute_impl_const_args(context, argument_columns, 
source_const, options_value,

Review Comment:
   [P1] Pass the evaluated fourth argument to the physical-constant pattern 
path. For `regexp_replace('a', '', '\\x', if(uniform(1, 2, crc32('x')) > 0, 
'ignore_invalid_escape', ''))` over a multirow `numbers` source, `uniform` 
produces a full options column and bypasses the all-constant wrapper. The empty 
pattern leaves no cached regex state, and this branch passes empty 
`options_value` to per-row compilation, ignoring the requested invalid-escape 
behavior. The equivalent literal option takes the all-constant wrapper and 
reads its option. Both replacement variants share this path. Read options 
before branching and cover this mixed-column case.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to