Code review comment: third param can be non-literal?

Code under review:
public static void verifyAnalyticExpression(AnalyticExpr analyticExpr) {
        for (Expr e : analyticExpr.getPartitionExprs()) {
            if (e.isConstant()) {
                throw new SemanticException("Expressions in the PARTITION BY clause must not be constant: "
                        + e.toSql() + " (in " + analyticExpr.toSql() + ")", e.getPos());
            }
            if (!e.getType().canPartitionBy()) {
                throw new SemanticException("HLL, BITMAP and PERCENTILE type can't as partition by column", e.getPos());
            }
        }

        for (OrderByElement e : analyticExpr.getOrderByElements()) {
            if (e.getExpr().isConstant()) {
                throw new SemanticException("Expressions in the ORDER BY clause must not be constant: "
                        + e.getExpr().toSql() + " (in " + analyticExpr.toSql() + ")", e.getPos());
            }
            if (!e.getExpr().getType().canOrderBy()) {
                throw new SemanticException("HLL, BITMAP and PERCENTILE type can't as order by column", e.getPos());
            }
        }

        FunctionCallExpr analyticFunction = analyticExpr.getFnCall();
        if (analyticFunction.getParams().isDistinct()) {
            throw new SemanticException("DISTINCT not allowed in analytic function: " + analyticFunction.toSql(),
                    analyticExpr.getPos());
        }

        if (!isAnalyticFn(analyticFunction.getFn())) {
            throw new SemanticException("Function '%s' not supported with OVER clause.",
                    analyticExpr.getFnCall().toSql(), analyticFunction.getPos());
        }

        for (Expr e : analyticExpr.getFnCall().getChildren()) {
            if (e.getType().isBitmapType() &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.BITMAP_UNION_COUNT) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LEAD) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LAG)) {
                throw new SemanticException("bitmap type could only used for bitmap_union_count/lead/lag window function",
                        e.getPos());
            } else if (e.getType().isHllType() &&
                    !analyticFunction.getFn().functionName().equals(AnalyticExpr.HLL_UNION_AGG) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LEAD) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LAG)) {
                throw new SemanticException("hll type could only used for hll_union_agg/lead/lag window function",
                        e.getPos());
            } else if (e.getType().isPercentile()) {
                throw new SemanticException("window functions don't support percentile type", e.getPos());
            }
        }

        if (isOffsetFn(analyticFunction.getFn()) && analyticFunction.getChildren().size() > 1) {
            Expr offset = analyticFunction.getChild(1);
            if (!isPositiveConstantInteger(offset)) {
                throw new SemanticException(
                        "The offset parameter of LEAD/LAG must be a constant positive integer: " +
                                analyticFunction.toSql(), analyticFunction.getPos());
            }

            
            if (analyticFunction.getChildren().size() == 2) {
                
            } else if (analyticFunction.getChildren().size() == 3) {
                Type firstType = analyticFunction.getChild(0).getType();

                if (analyticFunction.getChild(0) instanceof NullLiteral) {
                    firstType = analyticFunction.getFn().getArgs()[0];
                }

                try {
                    analyticFunction.uncheckedCastChild(firstType, 2);
                } catch (AnalysisException e) {
                    throw new SemanticException("The third parameter of LEAD/LAG can't convert to " + firstType,
                            analyticFunction.getChild(2).getPos());
                }

                
                
                
                
                if (!analyticFunction.getChild(2).isLiteral() && analyticFunction.getChild(2).isNullable()) {
                    throw new SemanticException("The type of the third parameter of LEAD/LAG not match the type " + firstType,
                            analyticFunction.getChild(2).getPos());
                }
            } else {
                throw new SemanticException("The number of parameter in LEAD/LAG is uncorrected", analyticFunction.getPos());
            }
        }

        if (isNtileFn(analyticFunction.getFn())) {
            Expr numBuckets = analyticFunction.getChild(0);
            if (!isPositiveConstantInteger(numBuckets)) {
                throw new SemanticException(
                        "The num_buckets parameter of NTILE must be a constant positive integer: " +
                                analyticFunction.toSql(), numBuckets.getPos());
            }
        }

        if (analyticExpr.getWindow() != null) {
            if ((isRankingFn(analyticFunction.getFn()) || isOffsetFn(analyticFunction.getFn()) ||
                    isHllAggFn(analyticFunction.getFn()))) {
                throw new SemanticException("Windowing clause not allowed with '" + analyticFunction.toSql() + "'",
                        analyticExpr.getPos());
            }

            verifyWindowFrame(analyticExpr);
        }
    }

Line commented on: if (!analyticFunction.getChild(2).isLiteral() && analyticFunction.getChild(2).isNullable()) {

Revised code:
public static void verifyAnalyticExpression(AnalyticExpr analyticExpr) {
        for (Expr e : analyticExpr.getPartitionExprs()) {
            if (e.isConstant()) {
                throw new SemanticException("Expressions in the PARTITION BY clause must not be constant: "
                        + e.toSql() + " (in " + analyticExpr.toSql() + ")", e.getPos());
            }
            if (!e.getType().canPartitionBy()) {
                throw new SemanticException("HLL, BITMAP and PERCENTILE type can't as partition by column", e.getPos());
            }
        }

        for (OrderByElement e : analyticExpr.getOrderByElements()) {
            if (e.getExpr().isConstant()) {
                throw new SemanticException("Expressions in the ORDER BY clause must not be constant: "
                        + e.getExpr().toSql() + " (in " + analyticExpr.toSql() + ")", e.getPos());
            }
            if (!e.getExpr().getType().canOrderBy()) {
                throw new SemanticException("HLL, BITMAP and PERCENTILE type can't as order by column", e.getPos());
            }
        }

        FunctionCallExpr analyticFunction = analyticExpr.getFnCall();
        if (analyticFunction.getParams().isDistinct()) {
            throw new SemanticException("DISTINCT not allowed in analytic function: " + analyticFunction.toSql(),
                    analyticExpr.getPos());
        }

        if (!isAnalyticFn(analyticFunction.getFn())) {
            throw new SemanticException("Function '%s' not supported with OVER clause.",
                    analyticExpr.getFnCall().toSql(), analyticFunction.getPos());
        }

        for (Expr e : analyticExpr.getFnCall().getChildren()) {
            if (e.getType().isBitmapType() &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.BITMAP_UNION_COUNT) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LEAD) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LAG)) {
                throw new SemanticException("bitmap type could only used for bitmap_union_count/lead/lag window function",
                        e.getPos());
            } else if (e.getType().isHllType() &&
                    !analyticFunction.getFn().functionName().equals(AnalyticExpr.HLL_UNION_AGG) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LEAD) &&
                    !analyticFunction.getFn().functionName().equals(FunctionSet.LAG)) {
                throw new SemanticException("hll type could only used for hll_union_agg/lead/lag window function",
                        e.getPos());
            } else if (e.getType().isPercentile()) {
                throw new SemanticException("window functions don't support percentile type", e.getPos());
            }
        }

        if (isOffsetFn(analyticFunction.getFn()) && analyticFunction.getChildren().size() > 1) {
            Expr offset = analyticFunction.getChild(1);
            if (!isPositiveConstantInteger(offset)) {
                throw new SemanticException(
                        "The offset parameter of LEAD/LAG must be a constant positive integer: " +
                                analyticFunction.toSql(), analyticFunction.getPos());
            }

            
            if (analyticFunction.getChildren().size() == 2) {
                
            } else if (analyticFunction.getChildren().size() == 3) {
                Type firstType = analyticFunction.getChild(0).getType();

                if (analyticFunction.getChild(0) instanceof NullLiteral) {
                    firstType = analyticFunction.getFn().getArgs()[0];
                }

                try {
                    analyticFunction.uncheckedCastChild(firstType, 2);
                } catch (AnalysisException e) {
                    throw new SemanticException("The third parameter of LEAD/LAG can't convert to " + firstType,
                            analyticFunction.getChild(2).getPos());
                }

                
                
                
                
                if (!analyticFunction.getChild(2).isLiteral() && analyticFunction.getChild(2).isNullable()) {
                    throw new SemanticException("The type of the third parameter of LEAD/LAG not match the type " + firstType,
                            analyticFunction.getChild(2).getPos());
                }
            } else {
                throw new SemanticException("The number of parameter in LEAD/LAG is uncorrected", analyticFunction.getPos());
            }
        }

        if (isNtileFn(analyticFunction.getFn())) {
            Expr numBuckets = analyticFunction.getChild(0);
            if (!isPositiveConstantInteger(numBuckets)) {
                throw new SemanticException(
                        "The num_buckets parameter of NTILE must be a constant positive integer: " +
                                analyticFunction.toSql(), numBuckets.getPos());
            }
        }

        if (analyticExpr.getWindow() != null) {
            if ((isRankingFn(analyticFunction.getFn()) || isOffsetFn(analyticFunction.getFn()) ||
                    isHllAggFn(analyticFunction.getFn()))) {
                throw new SemanticException("Windowing clause not allowed with '" + analyticFunction.toSql() + "'",
                        analyticExpr.getPos());
            }

            verifyWindowFrame(analyticExpr);
        }
    }