From 3a93bfa8285eff7a15344456f31daa184c60e4aa Mon Sep 17 00:00:00 2001 From: morrySnow Date: Sat, 28 Feb 2026 10:27:47 +0800 Subject: [PATCH] [refactor](analysis) replace Expr.toSql() with visitor pattern Remove toSql(), toSqlImpl(), toSqlWithoutTbl(), toExternalSql(), and toColumnLabel() from legacy Expr and all 39 subclasses. Introduce three visitor classes (ExprToSqlVisitor, ExprToExternalSqlVisitor, ExprToColumnLabelVisitor) plus ExprVisitor base and ToSqlParams context. Update all call sites across FE. Build and checkstyle pass clean. fix(analysis): remove visitor usage from toString() and TableIf from FunctionCallExpr - Remove toString() overrides that called ExprToSqlVisitor in ArithmeticExpr, CompoundPredicate, InPredicate, VariableExpr, MaxLiteral so they fall back to Expr.toString() debug representation - Rename ImportColumnDesc.toString() to toSql() to avoid calling visitor in toString - Change FunctionCallExpr.paramsToSql() signature from (boolean, boolean, TableType, TableIf) to (ToSqlParams) to remove TableIf/TableType dependency - Remove unused TableIf and TableIf.TableType imports from FunctionCallExpr - Update ExprToExternalSqlVisitor.visitFunctionCallExpr() to pass ToSqlParams directly Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> fix(analysis): restore toString via toSql facade and move paramsToSql into visitors Issue 1: toString() should not directly depend on ExprVisitor. - Add toSql() and toSqlWithoutTbl() facade methods to Expr base class that delegate to ExprToSqlVisitor and ExprToExternalSqlVisitor respectively - Restore toString() overrides in ArithmeticExpr, CompoundPredicate, InPredicate, VariableExpr, MaxLiteral to call toSql() (same as before the visitor refactoring) - Fix ImportColumnDesc.toString() to call expr.toSqlWithoutTbl() instead of directly invoking ExprToExternalSqlVisitor Issue 2: paramsToSql should not live in FunctionCallExpr. - Remove paramsToSql() and paramsToSql(ToSqlParams) from FunctionCallExpr - Inline the params-building logic directly into ExprToSqlVisitor.visitFunctionCallExpr() and ExprToExternalSqlVisitor.visitFunctionCallExpr() Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> fix(analysis): inline SQL logic in toString without visitor or toSql method - Remove toSql() and toSqlWithoutTbl() facade methods from Expr base class - Inline SQL generation directly in toString() for each class: - ArithmeticExpr: inline op + children SQL - CompoundPredicate: inline NOT/AND/OR logic (add Preconditions import) - InPredicate: inline IN list SQL - VariableExpr: inline @@/@ prefix + name construction - MaxLiteral: return literal string "MAXVALUE" - ImportColumnDesc.toString(): call ExprToExternalSqlVisitor directly on the child expr (not dispatching through visitor on 'this') Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> fix(analysis): move toExternalSqlImpl from SlotRef into ExprToExternalSqlVisitor - Remove toExternalSqlImpl(TableType, TableIf) method from SlotRef - Inline its logic into ExprToExternalSqlVisitor.visitSlotRef() where context.needExternalSql is true - Remove JdbcTable, OdbcTable, TableIf, TableType imports from SlotRef - Add JdbcTable, OdbcTable, TableIf imports to ExprToExternalSqlVisitor - Inline getTableIdToColumnNames() table variable to remove last TableIf usage in SlotRef No Expr subclass now imports org.apache.doris.catalog.TableIf. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> let ExprToColumnLabelVisitor extends ExprToSqlVisitor let attr private --- .../org/apache/doris/alter/RollupJobV2.java | 1 - .../apache/doris/analysis/AggregateInfo.java | 3 +- .../apache/doris/analysis/AnalyticWindow.java | 36 +- .../apache/doris/analysis/ArithmeticExpr.java | 31 +- .../apache/doris/analysis/ArrayLiteral.java | 18 +- .../doris/analysis/BetweenPredicate.java | 21 +- .../doris/analysis/BinaryPredicate.java | 14 +- .../apache/doris/analysis/BoolLiteral.java | 12 +- .../org/apache/doris/analysis/CaseExpr.java | 50 +- .../org/apache/doris/analysis/CastExpr.java | 15 +- .../apache/doris/analysis/ColumnRefExpr.java | 12 +- .../doris/analysis/CompoundPredicate.java | 33 +- .../doris/analysis/DataDescription.java | 16 +- .../apache/doris/analysis/DateLiteral.java | 12 +- .../apache/doris/analysis/DecimalLiteral.java | 14 +- .../apache/doris/analysis/EncryptKeyRef.java | 16 +- .../java/org/apache/doris/analysis/Expr.java | 50 +- .../analysis/ExprToColumnLabelVisitor.java | 51 ++ .../analysis/ExprToExternalSqlVisitor.java | 84 +++ .../doris/analysis/ExprToSqlVisitor.java | 561 ++++++++++++++++++ .../apache/doris/analysis/ExprVisitor.java | 215 +++++++ .../apache/doris/analysis/FloatLiteral.java | 12 +- .../doris/analysis/FunctionCallExpr.java | 235 +------- .../apache/doris/analysis/IPv4Literal.java | 12 +- .../apache/doris/analysis/IPv6Literal.java | 12 +- .../doris/analysis/ImportColumnDesc.java | 2 +- .../apache/doris/analysis/InPredicate.java | 34 +- .../doris/analysis/InformationFunction.java | 12 +- .../org/apache/doris/analysis/IntLiteral.java | 12 +- .../doris/analysis/IsNullPredicate.java | 13 +- .../apache/doris/analysis/JsonLiteral.java | 12 +- .../analysis/LambdaFunctionCallExpr.java | 89 +-- .../doris/analysis/LambdaFunctionExpr.java | 47 +- .../doris/analysis/LargeIntLiteral.java | 12 +- .../apache/doris/analysis/LikePredicate.java | 15 +- .../doris/analysis/ListPartitionDesc.java | 2 +- .../apache/doris/analysis/MVColumnItem.java | 2 +- .../org/apache/doris/analysis/MapLiteral.java | 22 +- .../apache/doris/analysis/MatchPredicate.java | 19 +- .../org/apache/doris/analysis/MaxLiteral.java | 14 +- .../apache/doris/analysis/NullLiteral.java | 12 +- .../apache/doris/analysis/OrderByElement.java | 2 +- .../apache/doris/analysis/PartitionDesc.java | 13 +- .../doris/analysis/PlaceHolderExpr.java | 18 +- .../doris/analysis/SearchPredicate.java | 47 +- .../org/apache/doris/analysis/SetVar.java | 3 +- .../apache/doris/analysis/SlotDescriptor.java | 8 +- .../org/apache/doris/analysis/SlotRef.java | 144 +---- .../apache/doris/analysis/StringLiteral.java | 15 +- .../apache/doris/analysis/StructLiteral.java | 16 +- .../apache/doris/analysis/TimeV2Literal.java | 11 +- .../analysis/TimestampArithmeticExpr.java | 98 +-- .../apache/doris/analysis/ToSqlParams.java | 48 ++ .../apache/doris/analysis/TryCastExpr.java | 15 +- .../doris/analysis/VarBinaryLiteral.java | 14 +- .../apache/doris/analysis/VariableExpr.java | 30 +- .../apache/doris/catalog/AliasFunction.java | 4 +- .../java/org/apache/doris/catalog/Column.java | 8 +- .../java/org/apache/doris/catalog/Env.java | 4 +- .../doris/catalog/GeneratedColumnInfo.java | 4 +- .../doris/catalog/MaterializedIndexMeta.java | 4 - .../apache/doris/catalog/PartitionKey.java | 8 +- .../doris/catalog/RangePartitionInfo.java | 4 +- .../doris/source/RemoteDorisScanNode.java | 14 +- .../jdbc/source/JdbcFunctionPushDownRule.java | 7 +- .../datasource/jdbc/source/JdbcScanNode.java | 28 +- .../maxcompute/MaxComputeMetadataOps.java | 5 +- .../datasource/odbc/source/OdbcScanNode.java | 5 +- .../apache/doris/load/BrokerFileGroup.java | 14 +- .../java/org/apache/doris/load/DeleteJob.java | 5 +- .../doris/load/loadv2/MysqlLoadManager.java | 4 +- .../load/routineload/KafkaRoutineLoadJob.java | 16 +- .../load/routineload/RoutineLoadJob.java | 20 +- .../org/apache/doris/mtmv/MTMVPlanUtil.java | 5 +- .../nereids/load/NereidsStreamLoadTask.java | 8 +- .../nereids/rules/analysis/BindSink.java | 16 +- .../expressions/functions/udf/AliasUdf.java | 5 +- .../plans/commands/CreateFunctionCommand.java | 1 - .../CreateMaterializedViewCommand.java | 8 +- .../plans/commands/DeleteFromCommand.java | 5 +- .../trees/plans/commands/DescribeCommand.java | 9 +- .../commands/ShowColumnStatsCommand.java | 14 +- .../plans/commands/ShowFunctionsCommand.java | 6 +- .../nereids/util/FrontendConjunctsUtils.java | 4 +- .../apache/doris/nereids/util/PlanUtils.java | 1 - .../doris/planner/AnalyticEvalNode.java | 6 +- .../apache/doris/planner/DataPartition.java | 4 +- .../apache/doris/planner/DataStreamSink.java | 5 +- .../apache/doris/planner/HashJoinNode.java | 5 +- .../apache/doris/planner/OlapScanNode.java | 14 +- .../apache/doris/planner/OlapTableSink.java | 5 +- .../doris/planner/PartitionSortNode.java | 6 +- .../apache/doris/planner/PlanFragment.java | 6 +- .../org/apache/doris/planner/PlanNode.java | 4 +- .../doris/planner/RecursiveCteNode.java | 5 +- .../doris/planner/RecursiveCteScanNode.java | 5 +- .../apache/doris/planner/RuntimeFilter.java | 6 +- .../apache/doris/planner/SchemaScanNode.java | 8 +- .../doris/planner/SetOperationNode.java | 8 +- .../org/apache/doris/planner/SortNode.java | 4 +- .../doris/planner/TableFunctionNode.java | 4 +- .../apache/doris/qe/PointQueryExecutor.java | 5 +- .../org/apache/doris/qe/StmtExecutor.java | 5 +- .../doris/analysis/DateLiteralTest.java | 10 +- .../apache/doris/analysis/ExprToSqlTest.java | 367 ++++++++---- .../doris/analysis/SearchPredicateTest.java | 6 +- .../VarBinaryLiteralAnalysisTest.java | 2 +- .../iceberg/IcebergPredicateTest.java | 18 +- .../lakesoul/LakeSoulPredicateTest.java | 18 +- .../expressions/VarBinaryLiteralTest.java | 6 +- 110 files changed, 1708 insertions(+), 1397 deletions(-) create mode 100644 fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExternalSqlVisitor.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/analysis/ExprVisitor.java create mode 100644 fe/fe-core/src/main/java/org/apache/doris/analysis/ToSqlParams.java diff --git a/fe/fe-core/src/main/java/org/apache/doris/alter/RollupJobV2.java b/fe/fe-core/src/main/java/org/apache/doris/alter/RollupJobV2.java index 439b0423651151..66bfaedc8a7583 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/alter/RollupJobV2.java +++ b/fe/fe-core/src/main/java/org/apache/doris/alter/RollupJobV2.java @@ -889,7 +889,6 @@ private void setColumnsDefineExpr(List mvColumnItemList) { for (Column column : rollupSchema) { if (column.getName().equals(mvColumnItem.getName())) { Expr defineExpr = mvColumnItem.getDefineExpr(); - defineExpr.disableTableName(); column.setDefineExpr(defineExpr); break; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AggregateInfo.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AggregateInfo.java index f1f0c069903a49..d1c2c75b89c9a1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AggregateInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AggregateInfo.java @@ -101,7 +101,8 @@ public static AggregateInfo create( for (int i = 0; i < aggExprSize; i++) { result.materializedSlots.add(i); String label = (isPartialAgg ? "partial_" : "") - + aggExprs.get(i).toSql() + "[#" + aggExprIds.get(i) + "]"; + + aggExprs.get(i).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE) + + "[#" + aggExprIds.get(i) + "]"; result.materializedSlotLabels.add(label); } return result; diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java index 9143c96be831c5..e1185451f0a737 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/AnalyticWindow.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.thrift.TAnalyticWindow; import org.apache.doris.thrift.TAnalyticWindowBoundary; import org.apache.doris.thrift.TAnalyticWindowBoundaryType; @@ -130,19 +128,7 @@ public String toSql() { StringBuilder sb = new StringBuilder(); if (expr != null) { - sb.append(expr.toSql()).append(" "); - } - - sb.append(type.toString()); - return sb.toString(); - } - - public String toSql(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder sb = new StringBuilder(); - - if (expr != null) { - sb.append(expr.toSql(disableTableName, needExternalSql, tableType, table)).append(" "); + sb.append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append(" "); } sb.append(type.toString()); @@ -235,26 +221,6 @@ public String toSql() { return sb.toString(); } - public String toSql(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - if (toSqlString != null) { - return toSqlString; - } - - StringBuilder sb = new StringBuilder(); - sb.append(type.toString()).append(" "); - - if (rightBoundary == null) { - sb.append(leftBoundary.toSql(disableTableName, needExternalSql, tableType, table)); - } else { - sb.append("BETWEEN ").append(leftBoundary.toSql(disableTableName, needExternalSql, tableType, table)) - .append(" AND "); - sb.append(rightBoundary.toSql(disableTableName, needExternalSql, tableType, table)); - } - - return sb.toString(); - } - public TAnalyticWindow toThrift() { TAnalyticWindow result = new TAnalyticWindow(type.toThrift()); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java index 456e849f399eeb..ac3c35b32595b0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArithmeticExpr.java @@ -22,8 +22,6 @@ import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -74,7 +72,7 @@ public TExprOpcode getOpcode() { } @SerializedName("op") - private final Operator op; + final Operator op; /** * constructor only used for Nereids. @@ -107,7 +105,13 @@ protected ArithmeticExpr(ArithmeticExpr other) { @Override public String toString() { - return toSql(); + if (children.size() == 1) { + return op.toString() + " " + getChild(0).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); + } else { + return "(" + getChild(0).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE) + + " " + op.toString() + + " " + getChild(1).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE) + ")"; + } } @Override @@ -116,23 +120,8 @@ public Expr clone() { } @Override - public String toSqlImpl() { - if (children.size() == 1) { - return op.toString() + " " + getChild(0).toSql(); - } else { - return "(" + getChild(0).toSql() + " " + op.toString() + " " + getChild(1).toSql() + ")"; - } - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - if (children.size() == 1) { - return op.toString() + " " + getChild(0).toSql(disableTableName, needExternalSql, tableType, table); - } else { - return "(" + getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + " " + op.toString() - + " " + getChild(1).toSql(disableTableName, needExternalSql, tableType, table) + ")"; - } + public R accept(ExprVisitor visitor, C context) { + return visitor.visitArithmeticExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java index 43e4a4f1826777..731a3639f1916d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ArrayLiteral.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.ArrayType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -69,20 +67,8 @@ public int compareLiteral(LiteralExpr expr) { } @Override - protected String toSqlImpl() { - List list = new ArrayList<>(children.size()); - children.forEach(v -> list.add(v.toSqlImpl())); - - return "[" + StringUtils.join(list, ", ") + "]"; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - List list = new ArrayList<>(children.size()); - children.forEach(v -> list.add(v.toSqlImpl(disableTableName, needExternalSql, tableType, table))); - - return "[" + StringUtils.join(list, ", ") + "]"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitArrayLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/BetweenPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/BetweenPredicate.java index b8a47464c1fccf..943b56b4169c06 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/BetweenPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/BetweenPredicate.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.thrift.TExprNode; import com.google.gson.annotations.SerializedName; @@ -45,6 +43,10 @@ protected BetweenPredicate(BetweenPredicate other) { isNotBetween = other.isNotBetween; } + public boolean isNotBetween() { + return isNotBetween; + } + @Override public Expr clone() { return new BetweenPredicate(this); @@ -57,19 +59,8 @@ protected void toThrift(TExprNode msg) { } @Override - public String toSqlImpl() { - String notStr = (isNotBetween) ? "NOT " : ""; - return children.get(0).toSql() + " " + notStr + "BETWEEN " - + children.get(1).toSql() + " AND " + children.get(2).toSql(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - String notStr = (isNotBetween) ? "NOT " : ""; - return children.get(0).toSql(disableTableName, needExternalSql, tableType, table) + " " + notStr + "BETWEEN " - + children.get(1).toSql(disableTableName, needExternalSql, tableType, table) + " AND " + children.get(2) - .toSql(disableTableName, needExternalSql, tableType, table); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitBetweenPredicate(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java index d1e3833b38b137..bba2e3c436e49f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/BinaryPredicate.java @@ -22,8 +22,6 @@ import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -171,16 +169,8 @@ public boolean equals(Object obj) { } @Override - public String toSqlImpl() { - return "(" + getChild(0).toSql() + " " + op.toString() + " " + getChild(1).toSql() + ")"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "(" + getChild(0).toSql(disableTableName, needExternalSql, tableType, table) - + " " + op.toString() + " " - + getChild(1).toSql(disableTableName, needExternalSql, tableType, table) + ")"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitBinaryPredicate(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/BoolLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/BoolLiteral.java index ea59b03582a72f..7a3355e1620c8e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/BoolLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/BoolLiteral.java @@ -21,8 +21,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -104,14 +102,8 @@ public int compareLiteral(LiteralExpr expr) { } @Override - public String toSqlImpl() { - return value ? "TRUE" : "FALSE"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return value ? "TRUE" : "FALSE"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitBoolLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CaseExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CaseExpr.java index a046ae249cc863..481925baa561a9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CaseExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CaseExpr.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.qe.ConnectContext; import org.apache.doris.thrift.TCaseExpr; import org.apache.doris.thrift.TExprNode; @@ -99,6 +97,14 @@ protected CaseExpr(CaseExpr other) { hasElseExpr = other.hasElseExpr; } + public boolean isHasCaseExpr() { + return hasCaseExpr; + } + + public boolean isHasElseExpr() { + return hasElseExpr; + } + @Override public Expr clone() { return new CaseExpr(this); @@ -119,44 +125,8 @@ public boolean equals(Object obj) { } @Override - public String toSqlImpl() { - StringBuilder output = new StringBuilder("CASE"); - int childIdx = 0; - if (hasCaseExpr) { - output.append(' ').append(children.get(childIdx++).toSql()); - } - while (childIdx + 2 <= children.size()) { - output.append(" WHEN " + children.get(childIdx++).toSql()); - output.append(" THEN " + children.get(childIdx++).toSql()); - } - if (hasElseExpr) { - output.append(" ELSE " + children.get(children.size() - 1).toSql()); - } - output.append(" END"); - return output.toString(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder output = new StringBuilder("CASE"); - int childIdx = 0; - if (hasCaseExpr) { - output.append(' ') - .append(children.get(childIdx++).toSql(disableTableName, needExternalSql, tableType, table)); - } - while (childIdx + 2 <= children.size()) { - output.append( - " WHEN " + children.get(childIdx++).toSql(disableTableName, needExternalSql, tableType, table)); - output.append( - " THEN " + children.get(childIdx++).toSql(disableTableName, needExternalSql, tableType, table)); - } - if (hasElseExpr) { - output.append(" ELSE " + children.get(children.size() - 1) - .toSql(disableTableName, needExternalSql, tableType, table)); - } - output.append(" END"); - return output.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitCaseExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java index bac4535c3242d5..665f219bea83a6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CastExpr.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.FormatOptions; import org.apache.doris.thrift.TExpr; @@ -83,17 +81,8 @@ public Expr clone() { } @Override - public String toSqlImpl() { - return "CAST(" + getChild(0).toSql() + " AS " + type.toSql() + ")"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, TableIf table) { - if (needExternalSql) { - return getChild(0).toSql(disableTableName, needExternalSql, tableType, table); - } - return "CAST(" + getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + " AS " - + type.toSql() + ")"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitCastExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java index bdcf1fde5a99bd..51bacc3dc3f23d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnRefExpr.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.nereids.util.Utils; import org.apache.doris.thrift.TColumnRef; import org.apache.doris.thrift.TExprNode; @@ -62,14 +60,8 @@ public void setColumnId(int id) { } @Override - protected String toSqlImpl() { - return columnName; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return columnName; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitColumnRefExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/CompoundPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/CompoundPredicate.java index c17701b55ddbee..6d9705cb0a46c3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/CompoundPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/CompoundPredicate.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; import org.apache.doris.thrift.TExprOpcode; @@ -85,26 +83,8 @@ public boolean equals(Object obj) { } @Override - public String toSqlImpl() { - if (children.size() == 1) { - Preconditions.checkState(op == Operator.NOT); - return "NOT " + getChild(0).toSql(); - } else { - return "(" + getChild(0).toSql() + " " + op.toString() + " " + getChild(1).toSql() + ")"; - } - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - if (children.size() == 1) { - Preconditions.checkState(op == Operator.NOT); - return "(NOT " + getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + ")"; - } else { - return "(" + getChild(0).toSql(disableTableName, needExternalSql, tableType, table) - + " " + op.toString() + " " - + getChild(1).toSql(disableTableName, needExternalSql, tableType, table) + ")"; - } + public R accept(ExprVisitor visitor, C context) { + return visitor.visitCompoundPredicate(this, context); } @Override @@ -143,6 +123,13 @@ public int hashCode() { @Override public String toString() { - return toSqlImpl(); + if (getChildren().size() == 1) { + Preconditions.checkState(getOp() == Operator.NOT); + return "NOT " + getChild(0).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); + } else { + return "(" + getChild(0).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE) + + " " + getOp().toString() + + " " + getChild(1).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE) + ")"; + } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java index e2970dc9dfc7d5..08b8141e443451 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DataDescription.java @@ -509,7 +509,7 @@ public void analyzeColumns() throws AnalysisException { for (Expr columnExpr : columnMappingList) { if (!(columnExpr instanceof BinaryPredicate)) { throw new AnalysisException("Mapping function expr only support the column or eq binary predicate. " - + "Expr: " + columnExpr.toSql()); + + "Expr: " + columnExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } BinaryPredicate predicate = (BinaryPredicate) columnExpr; if (predicate.getOp() != Operator.EQ) { @@ -522,7 +522,8 @@ public void analyzeColumns() throws AnalysisException { child0 = predicate.getChild(0); } else if (!(child0 instanceof SlotRef)) { throw new AnalysisException("Mapping function expr only support the column or eq binary predicate. " - + "The mapping column error. column: " + child0.toSql()); + + "The mapping column error. column: " + + child0.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } String column = ((SlotRef) child0).getColumnName(); if (!columnMappingNames.add(column)) { @@ -533,7 +534,7 @@ public void analyzeColumns() throws AnalysisException { if (isHadoopLoad && !(child1 instanceof FunctionCallExpr)) { throw new AnalysisException( "Hadoop load only supports the designated function. " + "The error mapping function is:" - + child1.toSql()); + + child1.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // Must clone the expr, because in routine load, the expr will be analyzed for each task. Expr cloned = child1.clone(); @@ -590,7 +591,8 @@ private void analyzeColumnToHadoopFunction(String columnName, Expr child1) throw } else { if (isHadoopLoad) { // hadoop function only support slot, string and null parameters - throw new AnalysisException("Mapping function args error, arg: " + paramExpr.toSql()); + throw new AnalysisException("Mapping function args error, arg: " + + paramExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } } @@ -784,15 +786,15 @@ public String apply(String s) { Joiner.on(", ").appendTo(sb, Lists.transform(columnMappingList, new Function() { @Override public Object apply(Expr expr) { - return expr.toSql(); + return expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); } })).append(")"); } if (whereExpr != null) { - sb.append(" WHERE ").append(whereExpr.toSql()); + sb.append(" WHERE ").append(whereExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } if (deleteCondition != null && mergeType == LoadTask.MergeType.MERGE) { - sb.append(" DELETE ON ").append(deleteCondition.toSql()); + sb.append(" DELETE ON ").append(deleteCondition.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } return sb.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java index 60168de6ea21d1..69a81dd6e78ac0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DateLiteral.java @@ -22,8 +22,6 @@ import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.ScalarType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -622,14 +620,8 @@ public int compareLiteral(LiteralExpr expr) { } @Override - public String toSqlImpl() { - return "'" + getStringValue() + "'"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "'" + getStringValue() + "'"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitDateLiteral(this, context); } private void fillPaddedValue(char[] buffer, int start, long value, int length) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java index 779ca177a28c9f..f5ca88f4ee2e37 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DecimalLiteral.java @@ -19,8 +19,6 @@ import org.apache.doris.catalog.PrimitiveType; import org.apache.doris.catalog.ScalarType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; @@ -239,7 +237,7 @@ public int compareLiteral(LiteralExpr expr) { return this.compareLiteral(decimalLiteral); } catch (AnalysisException e) { throw new ClassCastException("Those two values cannot be compared: " + value - + " and " + expr.toSqlImpl()); + + " and " + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } } @@ -250,14 +248,8 @@ public String getStringValueForQuery(FormatOptions options) { } @Override - public String toSqlImpl() { - return getStringValue(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getStringValue(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitDecimalLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/EncryptKeyRef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/EncryptKeyRef.java index 39030e49d5af15..7626c78252850f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/EncryptKeyRef.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/EncryptKeyRef.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; @@ -45,19 +43,13 @@ protected EncryptKeyRef(EncryptKeyRef other) { this.type = Type.VARCHAR; } - @Override - protected String toSqlImpl() { - StringBuilder sb = new StringBuilder(); - sb.append(encryptKeyName.toSql()); - return sb.toString(); + public EncryptKeyName getEncryptKeyName() { + return encryptKeyName; } @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder sb = new StringBuilder(); - sb.append(encryptKeyName.toSql()); - return sb.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitEncryptKeyRef(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java index 8638110c96cc87..48ec078bf027ba 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java @@ -22,8 +22,6 @@ import org.apache.doris.catalog.AggStateType; import org.apache.doris.catalog.Function; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -59,8 +57,6 @@ public abstract class Expr extends TreeNode implements Cloneable { public static final String DEFAULT_EXPR_NAME = "expr"; - protected boolean disableTableName = false; - protected boolean nullable = false; @SerializedName("type") @@ -216,47 +212,11 @@ public static void extractSlots(Expr root, Set slotIdSet) { } } - public String toSql() { - if (disableTableName) { - return toSqlWithoutTbl(); - } - return toSqlImpl(); - } - - public String toSql(boolean disableTableName, boolean needExternalSql, TableType tableType, TableIf table) { - return toSqlImpl(disableTableName, needExternalSql, tableType, table); - } - - public void disableTableName() { - disableTableName = true; - for (Expr child : children) { - child.disableTableName(); - } - } - - public String toSqlWithoutTbl() { - return toSql(true, false, null, null); - } - /** - * Returns a SQL string representing this expr. Subclasses should override this method - * instead of toSql() to ensure that parenthesis are properly added around the toSql(). + * Accept a visitor and dispatch to the appropriate typed {@code visitXxx} method. + * Each concrete subclass must override this to call the correct visitor method. */ - protected abstract String toSqlImpl(); - - protected abstract String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table); - - public String toExternalSql(TableType tableType, TableIf table) { - return toSql(false, true, tableType, table); - } - - /** - * Return a column label for the expression - */ - public String toColumnLabel() { - return toSql(); - } + public abstract R accept(ExprVisitor visitor, C context); // Convert this expr, including all children, to its Thrift representation. public TExpr treeToThrift() { @@ -270,7 +230,7 @@ protected void treeToThriftHelper(TExpr container) { } // Append a flattened version of this expr, including all children, to 'container'. - protected void treeToThriftHelper(TExpr container, ExprVisitor visitor) { + protected void treeToThriftHelper(TExpr container, ExprThriftVisitor visitor) { TExprNode msg = new TExprNode(); msg.type = type.toThrift(); msg.num_children = children.size(); @@ -290,7 +250,7 @@ protected void treeToThriftHelper(TExpr container, ExprVisitor visitor) { } } - public interface ExprVisitor { + public interface ExprThriftVisitor { void visit(Expr expr, TExprNode exprNode); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java new file mode 100644 index 00000000000000..0534b50031fd1e --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToColumnLabelVisitor.java @@ -0,0 +1,51 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.analysis; + +/** + * Visitor that produces the column-label string for any {@link Expr}. + * + *

For all expression types except {@link SlotRef}, the result is identical + * to {@link ExprToSqlVisitor} (i.e. the standard SQL string). For + * {@link SlotRef} the result is the raw column name without table qualification + * or backtick quoting, matching the legacy {@code SlotRef.toColumnLabel()} + * behaviour. + * + *

Usage: + *

+ *     String label = expr.accept(ExprToColumnLabelVisitor.INSTANCE, null);
+ * 
+ */ +public class ExprToColumnLabelVisitor extends ExprToSqlVisitor { + + /** Singleton — the visitor is stateless. */ + public static final ExprToColumnLabelVisitor INSTANCE = new ExprToColumnLabelVisitor(); + + private ExprToColumnLabelVisitor() { + } + + /** + * For a {@link SlotRef} the column label is the raw column name only + * (no table prefix, no backtick quoting), matching the legacy + * {@code SlotRef.toColumnLabel()} override that simply returned {@code col}. + */ + @Override + public String visitSlotRef(SlotRef expr, ToSqlParams context) { + return expr.getCol(); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExternalSqlVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExternalSqlVisitor.java new file mode 100644 index 00000000000000..97128ef9f656e6 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToExternalSqlVisitor.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.analysis; + +import org.apache.doris.catalog.JdbcTable; +import org.apache.doris.catalog.OdbcTable; +import org.apache.doris.catalog.TableIf; + +/** + * Visitor that produces the external SQL string for any {@link Expr}. + * Extends {@link ExprToSqlVisitor} and overrides only the methods that differ + * for external SQL generation. + * + *

Usage examples: + *

+ *   // equivalent to expr.toSqlWithoutTbl()
+ *   expr.accept(ExprToExternalSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)
+ *
+ *   // equivalent to expr.toExternalSql(tableType, table)
+ *   expr.accept(ExprToExternalSqlVisitor.INSTANCE, new ToSqlParams(false, true, tableType, table))
+ * 
+ */ +public class ExprToExternalSqlVisitor extends ExprToSqlVisitor { + + public static final ExprToExternalSqlVisitor INSTANCE = new ExprToExternalSqlVisitor(); + + private ExprToExternalSqlVisitor() { + // singleton + } + + @Override + public String visit(Expr expr, ToSqlParams context) { + throw new UnsupportedOperationException("ExprToExternalSqlVisitor does not support Expr type: " + + expr.getClass().getSimpleName()); + } + + @Override + public String visitSlotRef(SlotRef expr, ToSqlParams context) { + if (expr.getCol() != null) { + if (context.tableType.equals(TableIf.TableType.JDBC_EXTERNAL_TABLE) + || context.tableType.equals(TableIf.TableType.JDBC) + || context.tableType.equals(TableIf.TableType.ODBC)) { + if (context.table instanceof JdbcTable) { + return ((JdbcTable) context.table).getProperRemoteColumnName( + ((JdbcTable) context.table).getJdbcTableType(), expr.getCol()); + } else if (context.table instanceof OdbcTable) { + return JdbcTable.databaseProperName( + ((OdbcTable) context.table).getOdbcTableType(), expr.getCol()); + } else { + return expr.getCol(); + } + } else { + return expr.getCol(); + } + } else { + return ""; + } + } + + @Override + public String visitCastExpr(CastExpr expr, ToSqlParams context) { + return expr.getChild(0).accept(this, context); + } + + @Override + public String visitTryCastExpr(TryCastExpr expr, ToSqlParams context) { + return expr.getChild(0).accept(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java new file mode 100644 index 00000000000000..8f24389f4cfe35 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToSqlVisitor.java @@ -0,0 +1,561 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.analysis; + +import org.apache.doris.common.util.ToSqlContext; +import org.apache.doris.qe.ConnectContext; + +import com.google.common.base.Preconditions; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * Visitor that produces the standard SQL string for any {@link Expr}. + * Replaces the 0-arg {@code toSqlImpl()} body in every subclass. + * + *

Usage: {@code expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)} + */ +public class ExprToSqlVisitor extends ExprVisitor { + + public static final ExprToSqlVisitor INSTANCE = new ExprToSqlVisitor(); + + protected ExprToSqlVisitor() { + // singleton + } + + @Override + public String visit(Expr expr, ToSqlParams context) { + throw new UnsupportedOperationException("ExprToSqlVisitor does not support Expr type: " + + expr.getClass().getSimpleName()); + } + + // ----------------------------------------------------------------------- + // Literals + // ----------------------------------------------------------------------- + + @Override + public String visitBoolLiteral(BoolLiteral expr, ToSqlParams context) { + return expr.getValue() ? "TRUE" : "FALSE"; + } + + @Override + public String visitStringLiteral(StringLiteral expr, ToSqlParams context) { + return "'" + expr.getValue().replaceAll("'", "''") + "'"; + } + + @Override + public String visitIntLiteral(IntLiteral expr, ToSqlParams context) { + return expr.getStringValue(); + } + + @Override + public String visitLargeIntLiteral(LargeIntLiteral expr, ToSqlParams context) { + return expr.getStringValue(); + } + + @Override + public String visitFloatLiteral(FloatLiteral expr, ToSqlParams context) { + return expr.getStringValue(); + } + + @Override + public String visitDecimalLiteral(DecimalLiteral expr, ToSqlParams context) { + return expr.getStringValue(); + } + + @Override + public String visitDateLiteral(DateLiteral expr, ToSqlParams context) { + return "'" + expr.getStringValue() + "'"; + } + + @Override + public String visitTimeV2Literal(TimeV2Literal expr, ToSqlParams context) { + return "\"" + expr.getStringValue() + "\""; + } + + @Override + public String visitNullLiteral(NullLiteral expr, ToSqlParams context) { + return expr.getStringValue(); + } + + @Override + public String visitMaxLiteral(MaxLiteral expr, ToSqlParams context) { + return "MAXVALUE"; + } + + @Override + public String visitJsonLiteral(JsonLiteral expr, ToSqlParams context) { + return "'" + expr.getValue().replaceAll("'", "''") + "'"; + } + + @Override + public String visitIPv4Literal(IPv4Literal expr, ToSqlParams context) { + return "\"" + expr.getStringValue() + "\""; + } + + @Override + public String visitIPv6Literal(IPv6Literal expr, ToSqlParams context) { + return "\"" + expr.getStringValue() + "\""; + } + + @Override + public String visitVarBinaryLiteral(VarBinaryLiteral expr, ToSqlParams context) { + return expr.toHexLiteral(); + } + + @Override + public String visitArrayLiteral(ArrayLiteral expr, ToSqlParams context) { + List list = new ArrayList<>(expr.getChildren().size()); + expr.getChildren().forEach(v -> list.add(v.accept(this, context))); + return "[" + StringUtils.join(list, ", ") + "]"; + } + + @Override + public String visitMapLiteral(MapLiteral expr, ToSqlParams context) { + List list = new ArrayList<>(expr.getChildren().size()); + for (int i = 0; i < expr.getChildren().size() && i + 1 < expr.getChildren().size(); i += 2) { + list.add(expr.getChild(i).accept(this, context) + ":" + expr.getChild(i + 1).accept(this, context)); + } + return "MAP{" + StringUtils.join(list, ", ") + "}"; + } + + @Override + public String visitStructLiteral(StructLiteral expr, ToSqlParams context) { + List list = new ArrayList<>(expr.getChildren().size()); + expr.getChildren().forEach(v -> list.add(v.accept(this, context))); + return "STRUCT(" + StringUtils.join(list, ", ") + ")"; + } + + @Override + public String visitPlaceHolderExpr(PlaceHolderExpr expr, ToSqlParams context) { + if (expr.getLiteral() == null) { + return "?"; + } + return "_placeholder_(" + expr.getLiteral().accept(this, context) + ")"; + } + + // ----------------------------------------------------------------------- + // Reference / slot expressions + // ----------------------------------------------------------------------- + + @Override + public String visitSlotRef(SlotRef expr, ToSqlParams context) { + if (context.disableTableName && expr.getLabel() != null) { + return expr.getLabel(); + } + + StringBuilder sb = new StringBuilder(); + String subColumnPaths = ""; + if (expr.getSubColPath() != null && !expr.getSubColPath().isEmpty()) { + subColumnPaths = "." + String.join(".", expr.getSubColPath()); + } + if (expr.getTableNameInfo() != null) { + return expr.getTableNameInfo().toSql() + "." + expr.getLabel() + subColumnPaths; + } else if (expr.getLabel() != null) { + if (ConnectContext.get() != null + && ConnectContext.get().getState().isNereids() + && !ConnectContext.get().getState().isQuery() + && ConnectContext.get().getSessionVariable() != null + && expr.desc != null) { + return expr.getLabel() + "[#" + expr.desc.getId().asInt() + "]"; + } else { + return expr.getLabel(); + } + } else if (expr.desc == null) { + return "`" + expr.getCol() + "`"; + } else if (expr.desc.getSourceExprs() != null) { + if (!context.disableTableName && (ToSqlContext.get() == null || ToSqlContext.get().isNeedSlotRefId())) { + if (expr.desc.getId().asInt() != 1) { + sb.append(""); + } + } + for (Expr srcExpr : expr.desc.getSourceExprs()) { + if (!context.disableTableName) { + sb.append(" "); + } + sb.append(context.disableTableName + ? srcExpr.accept(INSTANCE, ToSqlParams.WITHOUT_TABLE) + : srcExpr.accept(this, context)); + } + return sb.toString(); + } else { + return "" + sb; + } + } + + @Override + public String visitColumnRefExpr(ColumnRefExpr expr, ToSqlParams context) { + return expr.getName(); + } + + @Override + public String visitInformationFunction(InformationFunction expr, ToSqlParams context) { + return expr.getFuncType() + "()"; + } + + @Override + public String visitEncryptKeyRef(EncryptKeyRef expr, ToSqlParams context) { + return expr.getEncryptKeyName().toSql(); + } + + @Override + public String visitVariableExpr(VariableExpr expr, ToSqlParams context) { + StringBuilder sb = new StringBuilder(); + if (expr.getSetType() == SetType.USER) { + sb.append("@"); + } else { + sb.append("@@"); + if (expr.getSetType() == SetType.GLOBAL) { + sb.append("GLOBAL."); + } + } + sb.append(expr.getName()); + return sb.toString(); + } + + // ----------------------------------------------------------------------- + // Predicates + // ----------------------------------------------------------------------- + + @Override + public String visitBinaryPredicate(BinaryPredicate expr, ToSqlParams context) { + return "(" + expr.getChild(0).accept(this, context) + + " " + expr.getOp().toString() + + " " + expr.getChild(1).accept(this, context) + ")"; + } + + @Override + public String visitIsNullPredicate(IsNullPredicate expr, ToSqlParams context) { + return expr.getChild(0).accept(this, context) + (expr.isNotNull() ? " IS NOT NULL" : " IS NULL"); + } + + @Override + public String visitCompoundPredicate(CompoundPredicate expr, ToSqlParams context) { + if (expr.getChildren().size() == 1) { + Preconditions.checkState(expr.getOp() == CompoundPredicate.Operator.NOT); + return "(NOT " + expr.getChild(0).accept(this, context) + ")"; + } else { + return "(" + expr.getChild(0).accept(this, context) + + " " + expr.getOp().toString() + + " " + expr.getChild(1).accept(this, context) + ")"; + } + } + + @Override + public String visitInPredicate(InPredicate expr, ToSqlParams context) { + StringBuilder strBuilder = new StringBuilder(); + String notStr = expr.isNotIn() ? "NOT " : ""; + strBuilder.append(expr.getChild(0).accept(this, context) + " " + notStr + "IN ("); + for (int i = 1; i < expr.getChildren().size(); ++i) { + strBuilder.append(expr.getChild(i).accept(this, context)); + strBuilder.append((i + 1 != expr.getChildren().size()) ? ", " : ""); + } + strBuilder.append(")"); + return strBuilder.toString(); + } + + @Override + public String visitLikePredicate(LikePredicate expr, ToSqlParams context) { + return expr.getChild(0).accept(this, context) + + " " + expr.op.toString() + + " " + expr.getChild(1).accept(this, context); + } + + @Override + public String visitMatchPredicate(MatchPredicate expr, ToSqlParams context) { + return expr.getChild(0).accept(this, context) + + " " + expr.op.toString() + + " " + expr.getChild(1).accept(this, context) + + expr.analyzerSqlFragment(); + } + + @Override + public String visitBetweenPredicate(BetweenPredicate expr, ToSqlParams context) { + String notStr = expr.isNotBetween() ? "NOT " : ""; + return expr.getChild(0).accept(this, context) + " " + notStr + "BETWEEN " + + expr.getChild(1).accept(this, context) + " AND " + expr.getChild(2).accept(this, context); + } + + @Override + public String visitSearchPredicate(SearchPredicate expr, ToSqlParams context) { + if (!expr.isExplainVerboseContext()) { + return "search('" + expr.getDslString() + "')"; + } + + StringBuilder sb = new StringBuilder("search('" + expr.getDslString() + "')"); + + List astLines = expr.buildDslAstExplainLines(); + if (!astLines.isEmpty()) { + sb.append("\n| dsl_ast:"); + for (String line : astLines) { + sb.append("\n| ").append(line); + } + } + + List bindings = expr.buildFieldBindingExplainLines(); + if (!bindings.isEmpty()) { + sb.append("\n| field_bindings:"); + for (String binding : bindings) { + sb.append("\n| ").append(binding); + } + } + + return sb.toString(); + } + + // ----------------------------------------------------------------------- + // Arithmetic / cast + // ----------------------------------------------------------------------- + + @Override + public String visitArithmeticExpr(ArithmeticExpr expr, ToSqlParams context) { + if (expr.getChildren().size() == 1) { + return expr.op.toString() + " " + expr.getChild(0).accept(this, context); + } else { + return "(" + expr.getChild(0).accept(this, context) + + " " + expr.op.toString() + + " " + expr.getChild(1).accept(this, context) + ")"; + } + } + + @Override + public String visitCastExpr(CastExpr expr, ToSqlParams context) { + return "CAST(" + expr.getChild(0).accept(this, context) + " AS " + expr.getType().toSql() + ")"; + } + + @Override + public String visitTryCastExpr(TryCastExpr expr, ToSqlParams context) { + return "TRY_CAST(" + expr.getChild(0).accept(this, context) + " AS " + expr.getType().toSql() + ")"; + } + + @Override + public String visitTimestampArithmeticExpr(TimestampArithmeticExpr expr, ToSqlParams context) { + StringBuilder strBuilder = new StringBuilder(); + if (expr.getFuncName() != null) { + if (expr.getFuncName().equalsIgnoreCase("TIMESTAMPDIFF") + || expr.getFuncName().equalsIgnoreCase("TIMESTAMPADD")) { + strBuilder.append(expr.getFuncName()).append("("); + strBuilder.append(expr.getTimeUnitIdent()).append(", "); + strBuilder.append(expr.getChild(1).accept(this, context)).append(", "); + strBuilder.append(expr.getChild(0).accept(this, context)).append(")"); + return strBuilder.toString(); + } + strBuilder.append(expr.getFuncName()).append("("); + strBuilder.append(expr.getChild(0).accept(this, context)).append(", "); + strBuilder.append("INTERVAL "); + strBuilder.append(expr.getChild(1).accept(this, context)); + strBuilder.append(" ").append(expr.getTimeUnitIdent()); + strBuilder.append(")"); + return strBuilder.toString(); + } + if (expr.isIntervalFirst()) { + strBuilder.append("INTERVAL "); + strBuilder.append(expr.getChild(1).accept(this, context) + " "); + strBuilder.append(expr.getTimeUnitIdent()); + strBuilder.append(" ").append(expr.getOp().toString()).append(" "); + strBuilder.append(expr.getChild(0).accept(this, context)); + } else { + strBuilder.append(expr.getChild(0).accept(this, context)); + strBuilder.append(" " + expr.getOp().toString() + " "); + strBuilder.append("INTERVAL "); + strBuilder.append(expr.getChild(1).accept(this, context) + " "); + strBuilder.append(expr.getTimeUnitIdent()); + } + return strBuilder.toString(); + } + + // ----------------------------------------------------------------------- + // Functions / lambda / case + // ----------------------------------------------------------------------- + + @Override + public String visitFunctionCallExpr(FunctionCallExpr expr, ToSqlParams context) { + StringBuilder sb = new StringBuilder(); + + if (expr.getFnName().getFunction().equalsIgnoreCase("like") + || expr.getFnName().getFunction().equalsIgnoreCase("regexp")) { + sb.append(expr.getChild(0).accept(this, context)); + sb.append(" "); + sb.append(expr.getFnName()); + sb.append(" "); + sb.append(expr.getChild(1).accept(this, context)); + } else if (expr.getFnName().getFunction().equalsIgnoreCase("encryptkeyref")) { + sb.append("key "); + for (int i = 0; i < expr.getChildren().size(); i++) { + String str = ((StringLiteral) expr.getChild(i)).getValue(); + if (str.isEmpty()) { + continue; + } + sb.append(str); + sb.append("."); + } + sb.deleteCharAt(sb.length() - 1); + } else { + sb.append(expr.getFnName()); + // inline params + StringBuilder params = new StringBuilder(); + params.append("("); + FunctionParams fnParams = expr.getFnParams(); + if (fnParams.isStar()) { + params.append("*"); + } + if (fnParams.isDistinct()) { + params.append("DISTINCT "); + } + int len = expr.getChildren().size(); + List orderByElements = expr.getOrderByElements(); + if (expr.getFnName().getFunction().equalsIgnoreCase("char")) { + for (int i = 1; i < len; ++i) { + params.append(expr.getChild(i).accept(this, context)); + if (i < len - 1) { + params.append(", "); + } + } + params.append(" using "); + String encodeType = expr.getChild(0).accept(this, context); + if (encodeType.charAt(0) == '\'') { + encodeType = encodeType.substring(1, encodeType.length()); + } + if (encodeType.charAt(encodeType.length() - 1) == '\'') { + encodeType = encodeType.substring(0, encodeType.length() - 1); + } + params.append(encodeType).append(")"); + } else if (expr.getFnName().getFunction().equalsIgnoreCase("years_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("months_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("days_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("hours_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("minutes_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("seconds_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("milliseconds_diff") + || expr.getFnName().getFunction().equalsIgnoreCase("microseconds_diff")) { + // XXX_diff are used by nereids only + params.append(expr.getChild(0).accept(this, context)).append(", "); + params.append(expr.getChild(1).accept(this, context)).append(")"); + } else { + for (int i = 0; i < len; ++i) { + if (i != 0) { + if (expr.getFnName().getFunction().equalsIgnoreCase("group_concat") + && orderByElements.size() > 0 && i == len - orderByElements.size()) { + params.append(" "); + } else { + params.append(", "); + } + } + if (ConnectContext.get() != null && ConnectContext.get().getState().isQuery() && i == 1 + && (expr.getFnName().getFunction().equalsIgnoreCase("aes_decrypt") + || expr.getFnName().getFunction().equalsIgnoreCase("aes_encrypt") + || expr.getFnName().getFunction().equalsIgnoreCase("sm4_decrypt") + || expr.getFnName().getFunction().equalsIgnoreCase("sm4_encrypt"))) { + params.append("\'***\'"); + continue; + } else if (orderByElements.size() > 0 && i == len - orderByElements.size()) { + params.append("ORDER BY "); + } + params.append(expr.getChild(i).accept(this, context)); + if (orderByElements.size() > 0 && i >= len - orderByElements.size()) { + if (orderByElements.get(i - len + orderByElements.size()).getIsAsc()) { + params.append(" ASC"); + } else { + params.append(" DESC"); + } + } + } + params.append(")"); + } + sb.append(params); + if (expr.getFnName().getFunction().equalsIgnoreCase("json_quote") + || expr.getFnName().getFunction().equalsIgnoreCase("json_array") + || expr.getFnName().getFunction().equalsIgnoreCase("json_object") + || expr.getFnName().getFunction().equalsIgnoreCase("json_insert") + || expr.getFnName().getFunction().equalsIgnoreCase("json_replace") + || expr.getFnName().getFunction().equalsIgnoreCase("json_set")) { + return expr.forJSON(sb.toString()); + } + } + return sb.toString(); + } + + @Override + public String visitLambdaFunctionCallExpr(LambdaFunctionCallExpr expr, ToSqlParams context) { + StringBuilder sb = new StringBuilder(); + String fnName = expr.getFnName().getFunction(); + if (expr.fn != null) { + fnName = expr.fn.getFunctionName().getFunction(); + } + sb.append(fnName); + sb.append("("); + int childSize = expr.getChildren().size(); + Expr lastExpr = expr.getChild(childSize - 1); + boolean lastIsLambdaExpr = (lastExpr instanceof LambdaFunctionExpr); + if (lastIsLambdaExpr) { + sb.append(lastExpr.accept(this, context)); + sb.append(", "); + } + for (int i = 0; i < childSize - 1; ++i) { + sb.append(expr.getChild(i).accept(this, context)); + if (i != childSize - 2) { + sb.append(", "); + } + } + if (!lastIsLambdaExpr) { + if (childSize > 1) { + sb.append(", "); + } + sb.append(lastExpr.accept(this, context)); + } + sb.append(")"); + return sb.toString(); + } + + @Override + public String visitLambdaFunctionExpr(LambdaFunctionExpr expr, ToSqlParams context) { + String nameStr = ""; + Expr lambdaExpr = expr.getSlotExprs().get(0); + int exprSize = expr.getNames().size(); + for (int i = 0; i < exprSize; ++i) { + nameStr = nameStr + expr.getNames().get(i); + if (i != exprSize - 1) { + nameStr = nameStr + ","; + } + } + if (exprSize > 1) { + nameStr = "(" + nameStr + ")"; + } + return String.format("%s -> %s", nameStr, lambdaExpr.accept(this, context)); + } + + @Override + public String visitCaseExpr(CaseExpr expr, ToSqlParams context) { + StringBuilder output = new StringBuilder("CASE"); + int childIdx = 0; + if (expr.isHasCaseExpr()) { + output.append(' ').append(expr.getChild(childIdx++).accept(this, context)); + } + while (childIdx + 2 <= expr.getChildren().size()) { + output.append(" WHEN " + expr.getChild(childIdx++).accept(this, context)); + output.append(" THEN " + expr.getChild(childIdx++).accept(this, context)); + } + if (expr.isHasElseExpr()) { + output.append(" ELSE " + expr.getChild(expr.getChildren().size() - 1).accept(this, context)); + } + output.append(" END"); + return output.toString(); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprVisitor.java new file mode 100644 index 00000000000000..fbed2844989f71 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprVisitor.java @@ -0,0 +1,215 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.analysis; + +/** + * Abstract visitor base class for {@link Expr} and all 39 concrete subclasses. + * Follows the same {@code } pattern as + * {@code org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor}. + * + *

Each typed {@code visitXxx} method defaults to delegating upward to + * {@link #visit(Expr, Object)}, so concrete visitors only need to override + * the methods they care about. + * + * @param return type of each visit method + * @param context type passed through each visit call + */ +public abstract class ExprVisitor { + + /** + * Catch-all method. All typed {@code visitXxx} methods ultimately delegate here + * unless overridden by a concrete visitor. + */ + public abstract R visit(Expr expr, C context); + + // ----------------------------------------------------------------------- + // Literals + // ----------------------------------------------------------------------- + + public R visitBoolLiteral(BoolLiteral expr, C context) { + return visit(expr, context); + } + + public R visitStringLiteral(StringLiteral expr, C context) { + return visit(expr, context); + } + + public R visitIntLiteral(IntLiteral expr, C context) { + return visit(expr, context); + } + + public R visitLargeIntLiteral(LargeIntLiteral expr, C context) { + return visit(expr, context); + } + + public R visitFloatLiteral(FloatLiteral expr, C context) { + return visit(expr, context); + } + + public R visitDecimalLiteral(DecimalLiteral expr, C context) { + return visit(expr, context); + } + + public R visitDateLiteral(DateLiteral expr, C context) { + return visit(expr, context); + } + + public R visitTimeV2Literal(TimeV2Literal expr, C context) { + return visit(expr, context); + } + + public R visitNullLiteral(NullLiteral expr, C context) { + return visit(expr, context); + } + + public R visitMaxLiteral(MaxLiteral expr, C context) { + return visit(expr, context); + } + + public R visitJsonLiteral(JsonLiteral expr, C context) { + return visit(expr, context); + } + + public R visitIPv4Literal(IPv4Literal expr, C context) { + return visit(expr, context); + } + + public R visitIPv6Literal(IPv6Literal expr, C context) { + return visit(expr, context); + } + + public R visitVarBinaryLiteral(VarBinaryLiteral expr, C context) { + return visit(expr, context); + } + + public R visitArrayLiteral(ArrayLiteral expr, C context) { + return visit(expr, context); + } + + public R visitMapLiteral(MapLiteral expr, C context) { + return visit(expr, context); + } + + public R visitStructLiteral(StructLiteral expr, C context) { + return visit(expr, context); + } + + public R visitPlaceHolderExpr(PlaceHolderExpr expr, C context) { + return visit(expr, context); + } + + // ----------------------------------------------------------------------- + // Reference / slot expressions + // ----------------------------------------------------------------------- + + public R visitSlotRef(SlotRef expr, C context) { + return visit(expr, context); + } + + public R visitColumnRefExpr(ColumnRefExpr expr, C context) { + return visit(expr, context); + } + + public R visitInformationFunction(InformationFunction expr, C context) { + return visit(expr, context); + } + + public R visitEncryptKeyRef(EncryptKeyRef expr, C context) { + return visit(expr, context); + } + + public R visitVariableExpr(VariableExpr expr, C context) { + return visit(expr, context); + } + + // ----------------------------------------------------------------------- + // Predicates + // ----------------------------------------------------------------------- + + public R visitBinaryPredicate(BinaryPredicate expr, C context) { + return visit(expr, context); + } + + public R visitIsNullPredicate(IsNullPredicate expr, C context) { + return visit(expr, context); + } + + public R visitCompoundPredicate(CompoundPredicate expr, C context) { + return visit(expr, context); + } + + public R visitInPredicate(InPredicate expr, C context) { + return visit(expr, context); + } + + public R visitLikePredicate(LikePredicate expr, C context) { + return visit(expr, context); + } + + public R visitMatchPredicate(MatchPredicate expr, C context) { + return visit(expr, context); + } + + public R visitBetweenPredicate(BetweenPredicate expr, C context) { + return visit(expr, context); + } + + public R visitSearchPredicate(SearchPredicate expr, C context) { + return visit(expr, context); + } + + // ----------------------------------------------------------------------- + // Arithmetic / cast + // ----------------------------------------------------------------------- + + public R visitArithmeticExpr(ArithmeticExpr expr, C context) { + return visit(expr, context); + } + + public R visitCastExpr(CastExpr expr, C context) { + return visit(expr, context); + } + + public R visitTryCastExpr(TryCastExpr expr, C context) { + return visit(expr, context); + } + + public R visitTimestampArithmeticExpr(TimestampArithmeticExpr expr, C context) { + return visit(expr, context); + } + + // ----------------------------------------------------------------------- + // Functions / lambda / case + // ----------------------------------------------------------------------- + + public R visitFunctionCallExpr(FunctionCallExpr expr, C context) { + return visit(expr, context); + } + + public R visitLambdaFunctionCallExpr(LambdaFunctionCallExpr expr, C context) { + return visit(expr, context); + } + + public R visitLambdaFunctionExpr(LambdaFunctionExpr expr, C context) { + return visit(expr, context); + } + + public R visitCaseExpr(CaseExpr expr, C context) { + return visit(expr, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java index 412457e608d047..cd0ebd89476b34 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FloatLiteral.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -132,14 +130,8 @@ public int compareLiteral(LiteralExpr expr) { } @Override - public String toSqlImpl() { - return getStringValue(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getStringValue(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitFloatLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java index d4901620e479bd..4909e085214a0c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java @@ -23,8 +23,6 @@ import org.apache.doris.catalog.AggregateFunction; import org.apache.doris.catalog.Function; import org.apache.doris.catalog.FunctionSet; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.nereids.util.Utils; import org.apache.doris.planner.normalize.Normalizer; import org.apache.doris.qe.ConnectContext; @@ -180,237 +178,8 @@ public boolean equals(Object obj) { && fnParams.isStar() == o.fnParams.isStar(); } - private String paramsToSql() { - StringBuilder sb = new StringBuilder(); - sb.append("("); - - if (fnParams.isStar()) { - sb.append("*"); - } - if (fnParams.isDistinct()) { - sb.append("DISTINCT "); - } - int len = children.size(); - - if (fnName.getFunction().equalsIgnoreCase("char")) { - for (int i = 1; i < len; ++i) { - sb.append(children.get(i).toSql()); - if (i < len - 1) { - sb.append(", "); - } - } - sb.append(" using "); - String encodeType = children.get(0).toSql(); - if (encodeType.charAt(0) == '\'') { - encodeType = encodeType.substring(1, encodeType.length()); - } - if (encodeType.charAt(encodeType.length() - 1) == '\'') { - encodeType = encodeType.substring(0, encodeType.length() - 1); - } - sb.append(encodeType).append(")"); - return sb.toString(); - } - - // XXX_diff are used by nereids only - if (fnName.getFunction().equalsIgnoreCase("years_diff") || fnName.getFunction().equalsIgnoreCase("months_diff") - || fnName.getFunction().equalsIgnoreCase("days_diff") - || fnName.getFunction().equalsIgnoreCase("hours_diff") - || fnName.getFunction().equalsIgnoreCase("minutes_diff") - || fnName.getFunction().equalsIgnoreCase("seconds_diff") - || fnName.getFunction().equalsIgnoreCase("milliseconds_diff") - || fnName.getFunction().equalsIgnoreCase("microseconds_diff")) { - sb.append(children.get(0).toSql()).append(", "); - sb.append(children.get(1).toSql()).append(")"); - return sb.toString(); - } - // used by nereids END - - for (int i = 0; i < len; ++i) { - if (i != 0) { - if (fnName.getFunction().equalsIgnoreCase("group_concat") - && orderByElements.size() > 0 && i == len - orderByElements.size()) { - sb.append(" "); - } else { - sb.append(", "); - } - } - if (ConnectContext.get() != null && ConnectContext.get().getState().isQuery() && i == 1 - && (fnName.getFunction().equalsIgnoreCase("aes_decrypt") - || fnName.getFunction().equalsIgnoreCase("aes_encrypt") - || fnName.getFunction().equalsIgnoreCase("sm4_decrypt") - || fnName.getFunction().equalsIgnoreCase("sm4_encrypt"))) { - sb.append("\'***\'"); - continue; - } else if (orderByElements.size() > 0 && i == len - orderByElements.size()) { - sb.append("ORDER BY "); - } - sb.append(children.get(i).toSql()); - if (orderByElements.size() > 0 && i >= len - orderByElements.size()) { - if (orderByElements.get(i - len + orderByElements.size()).getIsAsc()) { - sb.append(" ASC"); - } else { - sb.append(" DESC"); - } - } - } - sb.append(")"); - return sb.toString(); - } - - private String paramsToSql(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder sb = new StringBuilder(); - sb.append("("); - - if (fnParams.isStar()) { - sb.append("*"); - } - if (fnParams.isDistinct()) { - sb.append("DISTINCT "); - } - int len = children.size(); - - if (fnName.getFunction().equalsIgnoreCase("char")) { - for (int i = 1; i < len; ++i) { - sb.append(children.get(i).toSql(disableTableName, needExternalSql, tableType, table)); - if (i < len - 1) { - sb.append(", "); - } - } - sb.append(" using "); - String encodeType = children.get(0).toSql(disableTableName, needExternalSql, tableType, table); - if (encodeType.charAt(0) == '\'') { - encodeType = encodeType.substring(1, encodeType.length()); - } - if (encodeType.charAt(encodeType.length() - 1) == '\'') { - encodeType = encodeType.substring(0, encodeType.length() - 1); - } - sb.append(encodeType).append(")"); - return sb.toString(); - } - - // XXX_diff are used by nereids only - if (fnName.getFunction().equalsIgnoreCase("years_diff") || fnName.getFunction().equalsIgnoreCase("months_diff") - || fnName.getFunction().equalsIgnoreCase("days_diff") - || fnName.getFunction().equalsIgnoreCase("hours_diff") - || fnName.getFunction().equalsIgnoreCase("minutes_diff") - || fnName.getFunction().equalsIgnoreCase("seconds_diff") - || fnName.getFunction().equalsIgnoreCase("milliseconds_diff") - || fnName.getFunction().equalsIgnoreCase("microseconds_diff")) { - sb.append(children.get(0).toSql(disableTableName, needExternalSql, tableType, table)).append(", "); - sb.append(children.get(1).toSql(disableTableName, needExternalSql, tableType, table)).append(")"); - return sb.toString(); - } - - for (int i = 0; i < len; ++i) { - if (i != 0) { - if (fnName.getFunction().equalsIgnoreCase("group_concat") - && orderByElements.size() > 0 && i == len - orderByElements.size()) { - sb.append(" "); - } else { - sb.append(", "); - } - } - if (ConnectContext.get() != null && ConnectContext.get().getState().isQuery() && i == 1 - && (fnName.getFunction().equalsIgnoreCase("aes_decrypt") - || fnName.getFunction().equalsIgnoreCase("aes_encrypt") - || fnName.getFunction().equalsIgnoreCase("sm4_decrypt") - || fnName.getFunction().equalsIgnoreCase("sm4_encrypt"))) { - sb.append("\'***\'"); - continue; - } else if (orderByElements.size() > 0 && i == len - orderByElements.size()) { - sb.append("ORDER BY "); - } - sb.append(children.get(i).toSql(disableTableName, needExternalSql, tableType, table)); - if (orderByElements.size() > 0 && i >= len - orderByElements.size()) { - if (orderByElements.get(i - len + orderByElements.size()).getIsAsc()) { - sb.append(" ASC"); - } else { - sb.append(" DESC"); - } - } - } - sb.append(")"); - return sb.toString(); - } - - @Override - public String toSqlImpl() { - StringBuilder sb = new StringBuilder(); - - // when function is like or regexp, the expr generated sql should be like this - // eg: child1 like child2 - if (fnName.getFunction().equalsIgnoreCase("like") - || fnName.getFunction().equalsIgnoreCase("regexp")) { - sb.append(children.get(0).toSql()); - sb.append(" "); - sb.append(this.fnName); - sb.append(" "); - sb.append(children.get(1).toSql()); - } else if (fnName.getFunction().equalsIgnoreCase("encryptkeyref")) { - sb.append("key "); - for (int i = 0; i < children.size(); i++) { - String str = ((StringLiteral) children.get(i)).getValue(); - if (str.isEmpty()) { - continue; - } - sb.append(str); - sb.append("."); - } - sb.deleteCharAt(sb.length() - 1); - } else { - sb.append(this.fnName); - sb.append(paramsToSql()); - if (fnName.getFunction().equalsIgnoreCase("json_quote") - || fnName.getFunction().equalsIgnoreCase("json_array") - || fnName.getFunction().equalsIgnoreCase("json_object") - || fnName.getFunction().equalsIgnoreCase("json_insert") - || fnName.getFunction().equalsIgnoreCase("json_replace") - || fnName.getFunction().equalsIgnoreCase("json_set")) { - return forJSON(sb.toString()); - } - } - return sb.toString(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder sb = new StringBuilder(); - - // when function is like or regexp, the expr generated sql should be like this - // eg: child1 like child2 - if (fnName.getFunction().equalsIgnoreCase("like") - || fnName.getFunction().equalsIgnoreCase("regexp")) { - sb.append(children.get(0).toSql(disableTableName, needExternalSql, tableType, table)); - sb.append(" "); - sb.append(this.fnName); - sb.append(" "); - sb.append(children.get(1).toSql(disableTableName, needExternalSql, tableType, table)); - } else if (fnName.getFunction().equalsIgnoreCase("encryptkeyref")) { - sb.append("key "); - for (int i = 0; i < children.size(); i++) { - String str = ((StringLiteral) children.get(i)).getValue(); - if (str.isEmpty()) { - continue; - } - sb.append(str); - sb.append("."); - } - sb.deleteCharAt(sb.length() - 1); - } else { - sb.append(this.fnName); - sb.append(paramsToSql(disableTableName, needExternalSql, tableType, table)); - if (fnName.getFunction().equalsIgnoreCase("json_quote") - || fnName.getFunction().equalsIgnoreCase("json_array") - || fnName.getFunction().equalsIgnoreCase("json_object") - || fnName.getFunction().equalsIgnoreCase("json_insert") - || fnName.getFunction().equalsIgnoreCase("json_replace") - || fnName.getFunction().equalsIgnoreCase("json_set")) { - return forJSON(sb.toString()); - } - } - return sb.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitFunctionCallExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java index 588780d12f12a9..cd585f18e659cc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv4Literal.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -104,14 +102,8 @@ public Expr clone() { } @Override - protected String toSqlImpl() { - return "\"" + getStringValue() + "\""; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "\"" + getStringValue() + "\""; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitIPv4Literal(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java index 4afd7d87446429..e642cef674ea23 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IPv6Literal.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -80,14 +78,8 @@ private void checkValueValid(String ipv6) throws AnalysisException { } @Override - protected String toSqlImpl() { - return "\"" + getStringValue() + "\""; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "\"" + getStringValue() + "\""; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitIPv6Literal(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ImportColumnDesc.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ImportColumnDesc.java index 1a9995056e81fe..7906fac2e9f8b8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ImportColumnDesc.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ImportColumnDesc.java @@ -68,7 +68,7 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append(columnName); if (expr != null) { - sb.append("=").append(expr.toSqlWithoutTbl()); + sb.append("=").append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); } return sb.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/InPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/InPredicate.java index f838c54170c093..b98137c682fd41 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/InPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/InPredicate.java @@ -22,8 +22,6 @@ import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -118,38 +116,24 @@ protected void toThrift(TExprNode msg) { } @Override - public String toSqlImpl() { - StringBuilder strBuilder = new StringBuilder(); - String notStr = (isNotIn) ? "NOT " : ""; - strBuilder.append(getChild(0).toSql() + " " + notStr + "IN ("); - for (int i = 1; i < children.size(); ++i) { - strBuilder.append(getChild(i).toSql()); - strBuilder.append((i + 1 != children.size()) ? ", " : ""); - } - strBuilder.append(")"); - return strBuilder.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitInPredicate(this, context); } @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { + public String toString() { StringBuilder strBuilder = new StringBuilder(); - String notStr = (isNotIn) ? "NOT " : ""; - strBuilder.append( - getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + " " + notStr + "IN ("); - for (int i = 1; i < children.size(); ++i) { - strBuilder.append(getChild(i).toSql(disableTableName, needExternalSql, tableType, table)); - strBuilder.append((i + 1 != children.size()) ? ", " : ""); + String notStr = isNotIn ? "NOT " : ""; + strBuilder.append(getChild(0).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)) + .append(" ").append(notStr).append("IN ("); + for (int i = 1; i < getChildren().size(); ++i) { + strBuilder.append(getChild(i).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + strBuilder.append((i + 1 != getChildren().size()) ? ", " : ""); } strBuilder.append(")"); return strBuilder.toString(); } - @Override - public String toString() { - return toSql(); - } - @Override public boolean equals(Object obj) { if (super.equals(obj)) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/InformationFunction.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/InformationFunction.java index daed693ce3dde0..99c55094895e03 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/InformationFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/InformationFunction.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -72,14 +70,8 @@ protected void toThrift(TExprNode msg) { } @Override - public String toSqlImpl() { - return funcType + "()"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return funcType + "()"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitInformationFunction(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java index e8eb4531729428..f2c509345d640c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IntLiteral.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.thrift.TExprNode; @@ -249,14 +247,8 @@ public double getDoubleValue() { } @Override - public String toSqlImpl() { - return getStringValue(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getStringValue(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitIntLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java index 46313223e457b0..1e9bc14c1e7155 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/IsNullPredicate.java @@ -22,8 +22,6 @@ import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -79,15 +77,8 @@ public boolean equals(Object obj) { } @Override - public String toSqlImpl() { - return getChild(0).toSql() + (isNotNull ? " IS NOT NULL" : " IS NULL"); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + (isNotNull ? " IS NOT NULL" - : " IS NULL"); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitIsNullPredicate(this, context); } public boolean isSlotRefChildren() { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/JsonLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/JsonLiteral.java index 79559ac25f0615..c4025910909a18 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/JsonLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/JsonLiteral.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -85,14 +83,8 @@ public boolean isMinValue() { } @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "'" + value.replaceAll("'", "''") + "'"; - } - - @Override - public String toSqlImpl() { - return "'" + value.replaceAll("'", "''") + "'"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitJsonLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java index a4f7cb9558525e..e5214e0ccf8477 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionCallExpr.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.Function; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -49,91 +47,8 @@ protected void toThrift(TExprNode msg) { } @Override - public String toSqlImpl() { - StringBuilder sb = new StringBuilder(); - - String fnName = getFnName().getFunction(); - if (fn != null) { - // `array_last` will be replaced with `element_at` function after analysis. - // At this moment, using the name `array_last` would generate invalid SQL. - fnName = fn.getFunctionName().getFunction(); - } - sb.append(fnName); - sb.append("("); - int childSize = children.size(); - Expr lastExpr = getChild(childSize - 1); - // eg: select array_map(x->x>10, k1) from table, - // but we need analyze each param, so change the function like this in parser - // array_map(x->x>10, k1) ---> array_map(k1, x->x>10), - // so maybe the lambda expr is the end position. and need this check. - boolean lastIsLambdaExpr = (lastExpr instanceof LambdaFunctionExpr); - if (lastIsLambdaExpr) { - sb.append(lastExpr.toSql()); - sb.append(", "); - } - for (int i = 0; i < childSize - 1; ++i) { - sb.append(getChild(i).toSql()); - if (i != childSize - 2) { - sb.append(", "); - } - } - // and some functions is only implement as a normal array function; - // but also want use as lambda function, select array_sortby(x->x,['b','a','c']); - // so we convert to: array_sortby(array('b', 'a', 'c'), array_map(x -> `x`, array('b', 'a', 'c'))) - if (!lastIsLambdaExpr) { - if (childSize > 1) { - // some functions don't have lambda expr, so don't need to add "," - // such as array_exists(array_map(x->x>3, [1,2,3,6,34,3,11])) - sb.append(", "); - } - sb.append(lastExpr.toSql()); - } - sb.append(")"); - return sb.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitLambdaFunctionCallExpr(this, context); } - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder sb = new StringBuilder(); - - String fnName = getFnName().getFunction(); - if (fn != null) { - // `array_last` will be replaced with `element_at` function after analysis. - // At this moment, using the name `array_last` would generate invalid SQL. - fnName = fn.getFunctionName().getFunction(); - } - sb.append(fnName); - sb.append("("); - int childSize = children.size(); - Expr lastExpr = getChild(childSize - 1); - // eg: select array_map(x->x>10, k1) from table, - // but we need analyze each param, so change the function like this in parser - // array_map(x->x>10, k1) ---> array_map(k1, x->x>10), - // so maybe the lambda expr is the end position. and need this check. - boolean lastIsLambdaExpr = (lastExpr instanceof LambdaFunctionExpr); - if (lastIsLambdaExpr) { - sb.append(lastExpr.toSql(disableTableName, needExternalSql, tableType, table)); - sb.append(", "); - } - for (int i = 0; i < childSize - 1; ++i) { - sb.append(getChild(i).toSql(disableTableName, needExternalSql, tableType, table)); - if (i != childSize - 2) { - sb.append(", "); - } - } - // and some functions is only implement as a normal array function; - // but also want use as lambda function, select array_sortby(x->x,['b','a','c']); - // so we convert to: array_sortby(array('b', 'a', 'c'), array_map(x -> `x`, array('b', 'a', 'c'))) - if (!lastIsLambdaExpr) { - if (childSize > 1) { - // some functions don't have lambda expr, so don't need to add "," - // such as array_exists(array_map(x->x>3, [1,2,3,6,34,3,11])) - sb.append(", "); - } - sb.append(lastExpr.toSql(disableTableName, needExternalSql, tableType, table)); - } - sb.append(")"); - return sb.toString(); - } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionExpr.java index 55b34fc40ba007..a874dcc1cd32a1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LambdaFunctionExpr.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -58,42 +56,21 @@ public LambdaFunctionExpr(LambdaFunctionExpr rhs) { this.params.addAll(rhs.params); } - @Override - protected String toSqlImpl() { - String nameStr = ""; - Expr lambdaExpr = slotExprs.get(0); - int exprSize = names.size(); - for (int i = 0; i < exprSize; ++i) { - nameStr = nameStr + names.get(i); - if (i != exprSize - 1) { - nameStr = nameStr + ","; - } - } - if (exprSize > 1) { - nameStr = "(" + nameStr + ")"; - } - String res = String.format("%s -> %s", nameStr, lambdaExpr.toSql()); - return res; + public ArrayList getNames() { + return names; + } + + public ArrayList getSlotExprs() { + return slotExprs; + } + + public ArrayList getParams() { + return params; } @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - String nameStr = ""; - Expr lambdaExpr = slotExprs.get(0); - int exprSize = names.size(); - for (int i = 0; i < exprSize; ++i) { - nameStr = nameStr + names.get(i); - if (i != exprSize - 1) { - nameStr = nameStr + ","; - } - } - if (exprSize > 1) { - nameStr = "(" + nameStr + ")"; - } - String res = String.format("%s -> %s", nameStr, - lambdaExpr.toSql(disableTableName, needExternalSql, tableType, table)); - return res; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitLambdaFunctionExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java index 385968e543f4ed..d24dfe932e19dc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LargeIntLiteral.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.thrift.TExprNode; @@ -171,14 +169,8 @@ public double getDoubleValue() { } @Override - public String toSqlImpl() { - return getStringValue(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getStringValue(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitLargeIntLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/LikePredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/LikePredicate.java index 453e356c9eb4a0..95202195afbf14 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LikePredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LikePredicate.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -50,7 +48,7 @@ public String toString() { } @SerializedName("op") - private Operator op; + Operator op; private LikePredicate() { // use for serde only @@ -88,15 +86,8 @@ public boolean equals(Object obj) { } @Override - public String toSqlImpl() { - return getChild(0).toSql() + " " + op.toString() + " " + getChild(1).toSql(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + " " + op.toString() + " " - + getChild(1).toSql(disableTableName, needExternalSql, tableType, table); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitLikePredicate(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ListPartitionDesc.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ListPartitionDesc.java index 73f99d358cae12..8bf92bf514c0d8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ListPartitionDesc.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ListPartitionDesc.java @@ -63,7 +63,7 @@ public String toSql() { sb.append(", "); } idx++; - sb.append(e.toSql()); + sb.append(e.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } sb.append(")\n(\n"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/MVColumnItem.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/MVColumnItem.java index 9c2cfb0d646afb..79b96f2daff3ee 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/MVColumnItem.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/MVColumnItem.java @@ -64,7 +64,7 @@ public MVColumnItem(String name, Type type, AggregateType aggregateType, Expr de } public MVColumnItem(Expr defineExpr) throws AnalysisException { - this(defineExpr.toSqlWithoutTbl(), defineExpr); + this(defineExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE), defineExpr); } public MVColumnItem(String name, Expr defineExpr) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java index 5aed8e3d056932..e442812188a202 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/MapLiteral.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.MapType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -104,24 +102,8 @@ public String getStringValueForQuery(FormatOptions options) { } @Override - protected String toSqlImpl() { - List list = new ArrayList<>(children.size()); - for (int i = 0; i < children.size() && i + 1 < children.size(); i += 2) { - list.add(children.get(i).toSqlImpl() + ":" + children.get(i + 1).toSqlImpl()); - } - return "MAP{" + StringUtils.join(list, ", ") + "}"; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - List list = new ArrayList<>(children.size()); - for (int i = 0; i < children.size() && i + 1 < children.size(); i += 2) { - list.add( - children.get(i).toSqlImpl(disableTableName, needExternalSql, tableType, table) + ":" + children.get( - i + 1).toSqlImpl(disableTableName, needExternalSql, tableType, table)); - } - return "MAP{" + StringUtils.join(list, ", ") + "}"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitMapLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/MatchPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/MatchPredicate.java index 6b9b47def37c65..3996caa893e1dd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/MatchPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/MatchPredicate.java @@ -20,8 +20,6 @@ import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; import org.apache.doris.catalog.Index; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -76,7 +74,7 @@ public TExprOpcode getOpcode() { } @SerializedName("op") - private Operator op; + Operator op; // Fields for thrift serialization (restored from old version) private String invertedIndexParser; private String invertedIndexParserMode; @@ -164,17 +162,8 @@ public boolean equals(Object obj) { } @Override - public String toSqlImpl() { - return getChild(0).toSql() + " " + op.toString() + " " + getChild(1).toSql() - + analyzerSqlFragment(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + " " + op.toString() + " " - + getChild(1).toSql(disableTableName, needExternalSql, tableType, table) - + analyzerSqlFragment(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitMatchPredicate(this, context); } @Override @@ -194,7 +183,7 @@ public int hashCode() { return Objects.hash(super.hashCode(), op, explicitAnalyzer, invertedIndexAnalyzerName, invertedIndexParser); } - private String analyzerSqlFragment() { + String analyzerSqlFragment() { return InvertedIndexUtil.buildAnalyzerSqlFragment(explicitAnalyzer); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/MaxLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/MaxLiteral.java index d22039fd5f2809..18a36ba47f6cb4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/MaxLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/MaxLiteral.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.common.FormatOptions; import org.apache.doris.thrift.TExprNode; @@ -54,19 +52,13 @@ protected void toThrift(TExprNode msg) { } @Override - public String toSqlImpl() { - return "MAXVALUE"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "MAXVALUE"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitMaxLiteral(this, context); } @Override public String toString() { - return toSql(); + return "MAXVALUE"; } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/NullLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/NullLiteral.java index 187d61d57bfa36..8a4327bfab0017 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/NullLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/NullLiteral.java @@ -21,8 +21,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FeConstants; @@ -89,14 +87,8 @@ public int compareLiteral(LiteralExpr expr) { } @Override - public String toSqlImpl() { - return getStringValue(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return getStringValue(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitNullLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/OrderByElement.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/OrderByElement.java index 300971bf15198d..caa3d3cd9496e6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/OrderByElement.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/OrderByElement.java @@ -77,7 +77,7 @@ public static List getOrderByExprs(List src) { public String toSql() { StringBuilder strBuilder = new StringBuilder(); - strBuilder.append(expr.toSql()); + strBuilder.append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); strBuilder.append(isAsc ? " ASC" : " DESC"); // When ASC and NULLS LAST or DESC and NULLS FIRST, we do not print NULLS FIRST/LAST diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionDesc.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionDesc.java index 87c7eee117a974..f248789c76ddf6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionDesc.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/PartitionDesc.java @@ -119,38 +119,39 @@ public static List getColNamesFromExpr(ArrayList exprs, boolean is } else { throw new AnalysisException( "auto create partition only support one slotRef in function expr. " - + expr.toSql()); + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } } } else { throw new AnalysisException( "auto create partition only support function call expr is date_trunc/date_floor/date_ceil. " - + expr.toSql()); + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } else if (expr instanceof SlotRef) { if (isAutoPartition && !isListPartition) { throw new AnalysisException( "auto create partition only support date_trunc function of RANGE partition. " - + expr.toSql()); + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } colNames.add(((SlotRef) expr).getColumnName()); } else { if (!isListPartition) { throw new AnalysisException( "auto create partition only support slotRef and date_trunc/date_floor/date_ceil" - + "function in range partitions. " + expr.toSql()); + + "function in range partitions. " + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } else { throw new AnalysisException( "auto create partition only support slotRef in list partitions. " - + expr.toSql()); + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } } if (colNames.isEmpty()) { throw new AnalysisException( "auto create partition have not find any partition columns. " - + exprs.get(0).toSql()); + + exprs.get(0).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } return colNames; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java index 0090a44f152def..475aed49934032 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/PlaceHolderExpr.java @@ -19,8 +19,6 @@ import org.apache.doris.catalog.MysqlColType; import org.apache.doris.catalog.PrimitiveType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -123,20 +121,8 @@ public Expr clone() { } @Override - public String toSqlImpl() { - if (this.lExpr == null) { - return "?"; - } - return "_placeholder_(" + this.lExpr.toSqlImpl() + ")"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - if (this.lExpr == null) { - return "?"; - } - return "_placeholder_(" + this.lExpr.toSqlImpl(disableTableName, needExternalSql, tableType, table) + ")"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitPlaceHolderExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SearchPredicate.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SearchPredicate.java index a1e679c147e604..d343b1b9640542 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SearchPredicate.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SearchPredicate.java @@ -77,15 +77,8 @@ protected SearchPredicate(SearchPredicate other) { } @Override - protected String toSqlImpl() { - return buildSqlForExplain(); - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, - org.apache.doris.catalog.TableIf.TableType tableType, - org.apache.doris.catalog.TableIf table) { - return buildSqlForExplain(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitSearchPredicate(this, context); } @Override @@ -220,33 +213,7 @@ private TSearchParam buildThriftParam() { return param; } - private String buildSqlForExplain() { - if (!isExplainVerboseContext()) { - return "search('" + dslString + "')"; - } - - StringBuilder sb = new StringBuilder("search('" + dslString + "')"); - - List astLines = buildDslAstExplainLines(); - if (!astLines.isEmpty()) { - sb.append("\n| dsl_ast:"); - for (String line : astLines) { - sb.append("\n| ").append(line); - } - } - - List bindings = buildFieldBindingExplainLines(); - if (!bindings.isEmpty()) { - sb.append("\n| field_bindings:"); - for (String binding : bindings) { - sb.append("\n| ").append(binding); - } - } - - return sb.toString(); - } - - private boolean isExplainVerboseContext() { + boolean isExplainVerboseContext() { ConnectContext ctx = ConnectContext.get(); if (ctx == null) { return false; @@ -259,7 +226,7 @@ private boolean isExplainVerboseContext() { return executor.getParsedStmt().getExplainOptions().isVerbose(); } - private List buildDslAstExplainLines() { + List buildDslAstExplainLines() { List lines = new ArrayList<>(); if (qsPlan == null || qsPlan.getRoot() == null) { return lines; @@ -290,7 +257,7 @@ private void appendClauseExplain(TSearchClause clause, List lines, int d } } - private List buildFieldBindingExplainLines() { + List buildFieldBindingExplainLines() { List lines = new ArrayList<>(); if (qsPlan == null || qsPlan.getFieldBindings() == null || qsPlan.getFieldBindings().isEmpty()) { return lines; @@ -302,9 +269,9 @@ private List buildFieldBindingExplainLines() { SlotRef slotRef = (SlotRef) children.get(index); slotDesc = slotRef.getSlotId() != null ? "slot=" + slotRef.getSlotId().asInt() - : slotRef.toSqlWithoutTbl(); + : slotRef.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); } else if (index < children.size()) { - slotDesc = children.get(index).toSqlWithoutTbl(); + slotDesc = children.get(index).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); } lines.add(binding.getFieldName() + " -> " + slotDesc); }); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java index 213e9396f41e0f..11b2d2a1f6aeec 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SetVar.java @@ -109,7 +109,8 @@ public void setVarType(SetVarType varType) { public String toSql() { StringBuilder sb = new StringBuilder(); sb.append(type.toSql()); - sb.append(" ").append(variable).append(" = ").append(value.toSql()); + sb.append(" ").append(variable).append(" = ").append( + value.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); return sb.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java index 2a5979661c676d..bbac3642e990d8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotDescriptor.java @@ -274,7 +274,9 @@ public String debugString() { return MoreObjects.toStringHelper(this).add("id", id.asInt()).add("parent", parentTupleId).add("col", caption) .add("type", typeStr).add("nullable", getIsNullable()) .add("isAutoIncrement", isAutoInc).add("subColPath", subColPath) - .add("virtualColumn", virtualColumn == null ? null : virtualColumn.toSql()).toString(); + .add("virtualColumn", + virtualColumn == null ? null + : virtualColumn.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).toString(); } @Override @@ -292,7 +294,9 @@ public String getExplainString(String prefix) { .append(", nullable=").append(isNullable) .append(", isAutoIncrement=").append(isAutoInc) .append(", subColPath=").append(subColPath) - .append(", virtualColumn=").append(virtualColumn == null ? null : virtualColumn.toSql()) + .append(", virtualColumn=") + .append(virtualColumn == null + ? null : virtualColumn.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)) .append("}") .toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java index 7efb79a005726e..ddc6601e822b03 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/SlotRef.java @@ -21,15 +21,9 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.Column; -import org.apache.doris.catalog.JdbcTable; -import org.apache.doris.catalog.OdbcTable; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; -import org.apache.doris.common.util.ToSqlContext; import org.apache.doris.info.TableNameInfo; import org.apache.doris.planner.normalize.Normalizer; -import org.apache.doris.qe.ConnectContext; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; import org.apache.doris.thrift.TSlotRef; @@ -116,6 +110,22 @@ public Expr clone() { return new SlotRef(this); } + public TableNameInfo getTableNameInfo() { + return tableNameInfo; + } + + public String getCol() { + return col; + } + + public String getLabel() { + return label; + } + + public List getSubColPath() { + return subColPath; + } + public SlotDescriptor getDesc() { return desc; } @@ -156,125 +166,14 @@ public String debugString() { } @Override - public String toSqlImpl() { - StringBuilder sb = new StringBuilder(); - String subColumnPaths = ""; - if (subColPath != null && !subColPath.isEmpty()) { - subColumnPaths = "." + String.join(".", subColPath); - } - if (tableNameInfo != null) { - return tableNameInfo.toSql() + "." + label + subColumnPaths; - } else if (label != null) { - if (ConnectContext.get() != null - && ConnectContext.get().getState().isNereids() - && !ConnectContext.get().getState().isQuery() - && ConnectContext.get().getSessionVariable() != null - && desc != null) { - return label + "[#" + desc.getId().asInt() + "]"; - } else { - return label; - } - } else if (desc == null) { - // virtual slot of an alias function - // when we try to translate an alias function to Nereids style, the desc in the place holding slotRef - // is null, and we just need the name of col. - return "`" + col + "`"; - } else if (desc.getSourceExprs() != null) { - if ((ToSqlContext.get() == null || ToSqlContext.get().isNeedSlotRefId())) { - if (desc.getId().asInt() != 1) { - sb.append(""); - } - } - for (Expr expr : desc.getSourceExprs()) { - sb.append(" "); - sb.append(expr.toSql()); - } - return sb.toString(); - } else { - return "" + sb.toString(); - } - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf inputTable) { - if (needExternalSql) { - return toExternalSqlImpl(tableType, inputTable); - } - - if (disableTableName && label != null) { - return label; - } - - StringBuilder sb = new StringBuilder(); - String subColumnPaths = ""; - if (subColPath != null && !subColPath.isEmpty()) { - subColumnPaths = "." + String.join(".", subColPath); - } - if (tableNameInfo != null) { - return tableNameInfo.toSql() + "." + label + subColumnPaths; - } else if (label != null) { - if (ConnectContext.get() != null - && ConnectContext.get().getState().isNereids() - && !ConnectContext.get().getState().isQuery() - && ConnectContext.get().getSessionVariable() != null - && desc != null) { - return label + "[#" + desc.getId().asInt() + "]"; - } else { - return label; - } - } else if (desc == null) { - // virtual slot of an alias function - // when we try to translate an alias function to Nereids style, the desc in the place holding slotRef - // is null, and we just need the name of col. - return "`" + col + "`"; - } else if (desc.getSourceExprs() != null) { - if (!disableTableName && (ToSqlContext.get() == null || ToSqlContext.get().isNeedSlotRefId())) { - if (desc.getId().asInt() != 1) { - sb.append(""); - } - } - for (Expr expr : desc.getSourceExprs()) { - if (!disableTableName) { - sb.append(" "); - } - sb.append(disableTableName ? expr.toSqlWithoutTbl() : expr.toSql()); - } - return sb.toString(); - } else { - return "" + sb.toString(); - } - } - - private String toExternalSqlImpl(TableType tableType, TableIf inputTable) { - if (col != null) { - if (tableType.equals(TableType.JDBC_EXTERNAL_TABLE) || tableType.equals(TableType.JDBC) || tableType - .equals(TableType.ODBC)) { - if (inputTable instanceof JdbcTable) { - return ((JdbcTable) inputTable).getProperRemoteColumnName( - ((JdbcTable) inputTable).getJdbcTableType(), col); - } else if (inputTable instanceof OdbcTable) { - return JdbcTable.databaseProperName(((OdbcTable) inputTable).getOdbcTableType(), col); - } else { - return col; - } - } else { - return col; - } - } else { - return ""; - } - } - - @Override - public String toColumnLabel() { - return col; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitSlotRef(this, context); } @Override public String getExprName() { if (!this.exprName.isPresent()) { - this.exprName = Optional.of(toColumnLabel()); + this.exprName = Optional.of(accept(ExprToColumnLabelVisitor.INSTANCE, null)); } return this.exprName.get(); } @@ -381,12 +280,11 @@ public void getTableIdToColumnNames(Map> tableIdToColumnNames) expr.getTableIdToColumnNames(tableIdToColumnNames); } } else { - TableIf table = desc.getParent().getTable(); - if (table == null) { + if (desc.getParent().getTable() == null) { // Maybe this column comes from inline view. return; } - Long tableId = table.getId(); + Long tableId = desc.getParent().getTable().getId(); Set columnNames = tableIdToColumnNames.get(tableId); if (columnNames == null) { columnNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java index 98b9a68e0f5406..a844998c350983 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringLiteral.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.FormatOptions; import org.apache.doris.thrift.TExprNode; @@ -30,14 +28,11 @@ import com.google.common.base.Preconditions; import com.google.gson.annotations.SerializedName; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import java.io.UnsupportedEncodingException; import java.util.Objects; public class StringLiteral extends LiteralExpr { - private static final Logger LOG = LogManager.getLogger(StringLiteral.class); @SerializedName("v") private String value; @@ -120,14 +115,8 @@ public boolean isMinValue() { } @Override - public String toSqlImpl() { - return "'" + value.replaceAll("'", "''") + "'"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return "'" + value.replaceAll("'", "''") + "'"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitStringLiteral(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java index 914d6060035fc7..ef6d7a67175593 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StructLiteral.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.StructType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -61,18 +59,8 @@ protected StructLiteral(StructLiteral other) { } @Override - protected String toSqlImpl() { - List list = new ArrayList<>(children.size()); - children.forEach(v -> list.add(v.toSqlImpl())); - return "STRUCT(" + StringUtils.join(list, ", ") + ")"; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - List list = new ArrayList<>(children.size()); - children.forEach(v -> list.add(v.toSqlImpl(disableTableName, needExternalSql, tableType, table))); - return "STRUCT(" + StringUtils.join(list, ", ") + ")"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitStructLiteral(this, context); } private String getStringValue(Expr expr) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TimeV2Literal.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TimeV2Literal.java index c1638141c6133f..c70014d5fbfc4c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TimeV2Literal.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TimeV2Literal.java @@ -18,8 +18,6 @@ package org.apache.doris.analysis; import org.apache.doris.catalog.ScalarType; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.thrift.TExprNode; @@ -81,13 +79,8 @@ public Expr clone() { } @Override - protected String toSqlImpl() { - return "\"" + getStringValue() + "\""; - } - - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, TableIf table) { - return "\"" + getStringValue() + "\""; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitTimeV2Literal(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java index ef6f66811c999b..b7dd69d46651dd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java @@ -20,8 +20,6 @@ import org.apache.doris.analysis.ArithmeticExpr.Operator; import org.apache.doris.catalog.Function; import org.apache.doris.catalog.Function.NullableMode; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.ErrorCode; @@ -127,6 +125,26 @@ protected void toThrift(TExprNode msg) { msg.setOpcode(opcode); } + public String getFuncName() { + return funcName; + } + + public String getTimeUnitIdent() { + return timeUnitIdent; + } + + public boolean isIntervalFirst() { + return intervalFirst; + } + + public Operator getOp() { + return op; + } + + public TimeUnit getTimeUnit() { + return timeUnit; + } + private TExprOpcode getOpCode() throws AnalysisException { // Select appropriate opcode based on op and timeUnit. switch (timeUnit) { @@ -187,80 +205,8 @@ private TExprOpcode getOpCode() throws AnalysisException { } @Override - public String toSqlImpl() { - StringBuilder strBuilder = new StringBuilder(); - if (funcName != null) { - if (funcName.equalsIgnoreCase("TIMESTAMPDIFF") || funcName.equalsIgnoreCase("TIMESTAMPADD")) { - strBuilder.append(funcName).append("("); - strBuilder.append(timeUnitIdent).append(", "); - strBuilder.append(getChild(1).toSql()).append(", "); - strBuilder.append(getChild(0).toSql()).append(")"); - return strBuilder.toString(); - } - // Function-call like version. - strBuilder.append(funcName).append("("); - strBuilder.append(getChild(0).toSql()).append(", "); - strBuilder.append("INTERVAL "); - strBuilder.append(getChild(1).toSql()); - strBuilder.append(" ").append(timeUnitIdent); - strBuilder.append(")"); - return strBuilder.toString(); - } - if (intervalFirst) { - // Non-function-call like version with interval as first operand. - strBuilder.append("INTERVAL "); - strBuilder.append(getChild(1).toSql() + " "); - strBuilder.append(timeUnitIdent); - strBuilder.append(" ").append(op.toString()).append(" "); - strBuilder.append(getChild(0).toSql()); - } else { - // Non-function-call like version with interval as second operand. - strBuilder.append(getChild(0).toSql()); - strBuilder.append(" " + op.toString() + " "); - strBuilder.append("INTERVAL "); - strBuilder.append(getChild(1).toSql() + " "); - strBuilder.append(timeUnitIdent); - } - return strBuilder.toString(); - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - StringBuilder strBuilder = new StringBuilder(); - if (funcName != null) { - if (funcName.equalsIgnoreCase("TIMESTAMPDIFF") || funcName.equalsIgnoreCase("TIMESTAMPADD")) { - strBuilder.append(funcName).append("("); - strBuilder.append(timeUnitIdent).append(", "); - strBuilder.append(getChild(1).toSql(disableTableName, needExternalSql, tableType, table)).append(", "); - strBuilder.append(getChild(0).toSql(disableTableName, needExternalSql, tableType, table)).append(")"); - return strBuilder.toString(); - } - // Function-call like version. - strBuilder.append(funcName).append("("); - strBuilder.append(getChild(0).toSql(disableTableName, needExternalSql, tableType, table)).append(", "); - strBuilder.append("INTERVAL "); - strBuilder.append(getChild(1).toSql(disableTableName, needExternalSql, tableType, table)); - strBuilder.append(" ").append(timeUnitIdent); - strBuilder.append(")"); - return strBuilder.toString(); - } - if (intervalFirst) { - // Non-function-call like version with interval as first operand. - strBuilder.append("INTERVAL "); - strBuilder.append(getChild(1).toSql(disableTableName, needExternalSql, tableType, table) + " "); - strBuilder.append(timeUnitIdent); - strBuilder.append(" ").append(op.toString()).append(" "); - strBuilder.append(getChild(0).toSql(disableTableName, needExternalSql, tableType, table)); - } else { - // Non-function-call like version with interval as second operand. - strBuilder.append(getChild(0).toSql(disableTableName, needExternalSql, tableType, table)); - strBuilder.append(" " + op.toString() + " "); - strBuilder.append("INTERVAL "); - strBuilder.append(getChild(1).toSql(disableTableName, needExternalSql, tableType, table) + " "); - strBuilder.append(timeUnitIdent); - } - return strBuilder.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitTimestampArithmeticExpr(this, context); } // Time units supported in timestamp arithmetic. diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ToSqlParams.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/ToSqlParams.java new file mode 100644 index 00000000000000..6d716ad50de84b --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ToSqlParams.java @@ -0,0 +1,48 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you 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 +// +// http://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 org.apache.doris.analysis; + +import org.apache.doris.catalog.TableIf; +import org.apache.doris.catalog.TableIf.TableType; + +/** + * Immutable context object carried through {@link ExprToExternalSqlVisitor}. + * Encapsulates the four parameters that were previously passed as arguments to + * {@code Expr.toSql(boolean, boolean, TableType, TableIf)}. + */ +public class ToSqlParams { + + /** + * Pre-built instance equivalent to {@code toSqlWithoutTbl()}: + * disableTableName=true, needExternalSql=false, tableType=null, table=null. + */ + public static final ToSqlParams WITHOUT_TABLE = new ToSqlParams(true, false, null, null); + public static final ToSqlParams WITH_TABLE = new ToSqlParams(false, false, null, null); + + public final boolean disableTableName; + public final boolean needExternalSql; + public final TableType tableType; + public final TableIf table; + + public ToSqlParams(boolean disableTableName, boolean needExternalSql, TableType tableType, TableIf table) { + this.disableTableName = disableTableName; + this.needExternalSql = needExternalSql; + this.tableType = tableType; + this.table = table; + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TryCastExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TryCastExpr.java index 7f1a4c2f89d35a..a5db387e197c24 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TryCastExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TryCastExpr.java @@ -20,8 +20,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -49,17 +47,8 @@ public Expr clone() { } @Override - public String toSqlImpl() { - return "TRY_CAST(" + getChild(0).toSql() + " AS " + type.toSql() + ")"; - } - - @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, TableIf table) { - if (needExternalSql) { - return getChild(0).toSql(disableTableName, needExternalSql, tableType, table); - } - return "TRY_CAST(" + getChild(0).toSql(disableTableName, needExternalSql, tableType, table) + " AS " - + type.toSql() + ")"; + public R accept(ExprVisitor visitor, C context) { + return visitor.visitTryCastExpr(this, context); } @Override diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/VarBinaryLiteral.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/VarBinaryLiteral.java index 81223cc34d00a6..a085c73932d0dc 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/VarBinaryLiteral.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/VarBinaryLiteral.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.FormatOptions; @@ -58,17 +56,11 @@ protected VarBinaryLiteral(VarBinaryLiteral other) { @Override - protected String toSqlImpl() { - return toHexLiteral(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitVarBinaryLiteral(this, context); } - @Override - protected String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { - return toHexLiteral(); - } - - private String toHexLiteral() { + String toHexLiteral() { String hex = BaseEncoding.base16().encode(value); // upper-case hex return "X'" + hex + "'"; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java index e680c47c3c5bc2..6565f95cf86f64 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/VariableExpr.java @@ -17,8 +17,6 @@ package org.apache.doris.analysis; -import org.apache.doris.catalog.TableIf; -import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.thrift.TBoolLiteral; import org.apache.doris.thrift.TExprNode; import org.apache.doris.thrift.TExprNodeType; @@ -149,41 +147,25 @@ protected void toThrift(TExprNode msg) { } @Override - public String toSqlImpl() { - StringBuilder sb = new StringBuilder(); - if (setType == SetType.USER) { - sb.append("@"); - } else { - sb.append("@@"); - if (setType == SetType.GLOBAL) { - sb.append("GLOBAL."); - } - } - sb.append(name); - return sb.toString(); + public R accept(ExprVisitor visitor, C context) { + return visitor.visitVariableExpr(this, context); } @Override - public String toSqlImpl(boolean disableTableName, boolean needExternalSql, TableType tableType, - TableIf table) { + public String toString() { StringBuilder sb = new StringBuilder(); - if (setType == SetType.USER) { + if (getSetType() == SetType.USER) { sb.append("@"); } else { sb.append("@@"); - if (setType == SetType.GLOBAL) { + if (getSetType() == SetType.GLOBAL) { sb.append("GLOBAL."); } } - sb.append(name); + sb.append(getName()); return sb.toString(); } - @Override - public String toString() { - return toSql(); - } - @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java index fe6d9127b7a746..a98e089580764a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/AliasFunction.java @@ -18,8 +18,10 @@ package org.apache.doris.catalog; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.FunctionName; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.thrift.TFunctionBinaryType; import com.google.gson.annotations.SerializedName; @@ -106,7 +108,7 @@ public String toSql(boolean ifNotExists) { .append(" WITH PARAMETER(") .append(getParamsSting(parameters)) .append(") AS ") - .append(originFunction.toSqlWithoutTbl()) + .append(originFunction.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)) .append(";"); return sb.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java index bf5254280614cd..d6c03b702310b0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java @@ -20,7 +20,9 @@ import org.apache.doris.alter.SchemaChangeHandler; import org.apache.doris.analysis.DefaultValueExprDef; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.common.CaseSensibility; import org.apache.doris.common.Config; import org.apache.doris.common.DdlException; @@ -411,7 +413,8 @@ public String getDisplayName() { if (defineExpr == null) { return name; } else { - return MaterializedIndexMeta.normalizeName(defineExpr.toSql()); + return MaterializedIndexMeta.normalizeName( + defineExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); } } @@ -1076,7 +1079,8 @@ public String toSql(boolean isUniqueTable, boolean isCompatible) { sb.append(" ").append(aggregationType.toSql()); } if (generatedColumnInfo != null) { - sb.append(" AS (").append(generatedColumnInfo.getExpr().toSql()).append(")"); + sb.append(" AS (").append(generatedColumnInfo.getExpr() + .accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append(")"); } if (isAllowNull) { sb.append(" NULL"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java index 638c5e6f42f1fc..b292e657a67ce1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java @@ -26,7 +26,9 @@ import org.apache.doris.alter.SystemHandler; import org.apache.doris.analysis.DistributionDesc; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.authentication.AuthenticationIntegrationMgr; import org.apache.doris.backup.BackupHandler; import org.apache.doris.backup.RestoreJob; @@ -5840,7 +5842,7 @@ private void renameColumn(Database db, OlapTable table, String colName, List slots = new ArrayList<>(); expr.collect(SlotRef.class, slots); for (SlotRef slot : slots) { - String name = slot.toSqlWithoutTbl(); + String name = slot.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); if (slot.getColumn() != null) { name = slot.getColumn().getName(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/GeneratedColumnInfo.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/GeneratedColumnInfo.java index b14343a5c9f5f8..eff55fc8a47a7f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/GeneratedColumnInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/GeneratedColumnInfo.java @@ -18,6 +18,8 @@ package org.apache.doris.catalog; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import com.google.gson.annotations.SerializedName; import jline.internal.Nullable; @@ -53,7 +55,7 @@ public GeneratedColumnInfo(@Nullable String exprSql, Expr expr, Expr expandExprF if (exprSql != null) { this.exprSql = exprSql; } else { - this.exprSql = expr.toSqlWithoutTbl(); + this.exprSql = expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); } this.expr = expr; this.expandExprForLoad = expandExprForLoad; diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java index ced71e5a40be25..13a8889c667d0a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/MaterializedIndexMeta.java @@ -108,9 +108,6 @@ public MaterializedIndexMeta(long indexId, List schema, int schemaVersio public void setWhereClause(Expr whereClause) { this.whereClause = whereClause; - if (this.whereClause != null) { - this.whereClause.disableTableName(); - } } public Expr getWhereClause() { @@ -311,7 +308,6 @@ public void parseStmt() throws IOException { List columnDefineExprs = new ArrayList<>(mvColumnItemList.size()); for (MVColumnItem item : mvColumnItemList) { Expr defineExpr = item.getDefineExpr(); - defineExpr.disableTableName(); columnDefineExprs.add(defineExpr); } setColumnsDefineExpr(columnDefineExprs); diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java index 13ac91b38b6c05..a5dcb9d12eb21d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/PartitionKey.java @@ -19,12 +19,14 @@ import org.apache.doris.analysis.DateLiteral; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.IntLiteral; import org.apache.doris.analysis.LargeIntLiteral; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.MaxLiteral; import org.apache.doris.analysis.NullLiteral; import org.apache.doris.analysis.PartitionValue; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.io.Text; import org.apache.doris.common.io.Writable; @@ -378,13 +380,13 @@ public String toSql() { for (LiteralExpr expr : keys) { Object value = null; if (expr == MaxLiteral.MAX_VALUE || expr.isNullLiteral()) { - value = expr.toSql(); + value = expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); sb.append(value); } else { value = "\"" + expr.getRealValue() + "\""; if (expr instanceof DateLiteral) { DateLiteral dateLiteral = (DateLiteral) expr; - value = dateLiteral.toSql(); + value = dateLiteral.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); } sb.append(value); } @@ -427,7 +429,7 @@ public static String toString(List keys) { for (LiteralExpr expr : keys) { Object value = null; if (expr == MaxLiteral.MAX_VALUE || expr.isNullLiteral()) { - value = expr.toSql(); + value = expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); } else { value = expr.getRealValue(); if (expr instanceof DateLiteral) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java index b85f55e7d00aea..e06c1ebf34692e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/RangePartitionInfo.java @@ -19,10 +19,12 @@ import org.apache.doris.analysis.AllPartitionDesc; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.PartitionDesc; import org.apache.doris.analysis.PartitionKeyDesc; import org.apache.doris.analysis.RangePartitionDesc; import org.apache.doris.analysis.SinglePartitionDesc; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.DdlException; import org.apache.doris.common.util.RangeUtils; @@ -227,7 +229,7 @@ public String toSql(OlapTable table, List partitionId) { sb.append("AUTO PARTITION BY RANGE "); for (Expr e : partitionExprs) { sb.append("("); - sb.append(e.toSql()); + sb.append(e.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); sb.append(")"); } sb.append("\n("); diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/source/RemoteDorisScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/source/RemoteDorisScanNode.java index 41476afd03fb53..056961eb2b7763 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/source/RemoteDorisScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/doris/source/RemoteDorisScanNode.java @@ -22,8 +22,11 @@ import org.apache.doris.analysis.DateLiteral; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.ExprSubstitutionMap; +import org.apache.doris.analysis.ExprToExternalSqlVisitor; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.TableIf; @@ -128,7 +131,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append(prefix).append("QUERY: ").append(getQueryStr()).append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } return output.toString(); @@ -260,10 +264,11 @@ private void createFilters() { private String conjunctExprToString(Expr expr, TableIf tbl) { if (expr.contains(DateLiteral.class) && expr instanceof BinaryPredicate) { ArrayList children = expr.getChildren(); - String filter = children.get(0).toExternalSql(TableIf.TableType.DORIS_EXTERNAL_TABLE, tbl); + ToSqlParams params = new ToSqlParams(false, true, TableIf.TableType.DORIS_EXTERNAL_TABLE, tbl); + String filter = children.get(0).accept(ExprToExternalSqlVisitor.INSTANCE, params); filter += " " + ((BinaryPredicate) expr).getOp().toString() + " "; - filter += children.get(1).toExternalSql(TableIf.TableType.DORIS_EXTERNAL_TABLE, tbl); + filter += children.get(1).accept(ExprToExternalSqlVisitor.INSTANCE, params); return filter; } @@ -274,7 +279,8 @@ private String conjunctExprToString(Expr expr, TableIf tbl) { return "1 = 1"; } - return expr.toExternalSql(TableIf.TableType.DORIS_EXTERNAL_TABLE, tbl); + return expr.accept(ExprToExternalSqlVisitor.INSTANCE, + new ToSqlParams(false, true, TableIf.TableType.DORIS_EXTERNAL_TABLE, tbl)); } // TODO: Use AST parsing instead of string matching for EXPLAIN detection diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcFunctionPushDownRule.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcFunctionPushDownRule.java index 48aac798cf088a..bd0867e9eea61b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcFunctionPushDownRule.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcFunctionPushDownRule.java @@ -18,9 +18,11 @@ package org.apache.doris.datasource.jdbc.source; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToExternalSqlVisitor; import org.apache.doris.analysis.FunctionCallExpr; import org.apache.doris.analysis.FunctionName; import org.apache.doris.analysis.TimestampArithmeticExpr; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.TableIf.TableType; import org.apache.doris.common.Config; import org.apache.doris.datasource.ExternalFunctionRules; @@ -126,8 +128,9 @@ private static Expr processFunctionsRecursively(Expr expr, ExternalFunctionRules // 1. check can push down if (!functionRules.getFunctionPushDownRule().canPushDown(func)) { if (LOG.isDebugEnabled()) { - String errMsg = "Unsupported function: " + func + " in expr: " + expr.toExternalSql( - TableType.JDBC_EXTERNAL_TABLE, null) + String errMsg = "Unsupported function: " + func + " in expr: " + + expr.accept(ExprToExternalSqlVisitor.INSTANCE, + new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, null)) + " in JDBC Table Type: " + tableType; LOG.debug(errMsg); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcScanNode.java index fb832119139f0c..be6a415f61d5ef 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/jdbc/source/JdbcScanNode.java @@ -25,11 +25,14 @@ import org.apache.doris.analysis.DateLiteral; import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.ExprSubstitutionMap; +import org.apache.doris.analysis.ExprToExternalSqlVisitor; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.FunctionCallExpr; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.NullLiteral; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.JdbcTable; @@ -225,7 +228,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append(prefix).append("QUERY: ").append(getJdbcQueryStr()).append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } } if (useTopnFilter()) { @@ -331,7 +335,8 @@ public static String conjunctExprToString(TOdbcTableType tableType, Expr expr, T if (expr.contains(DateLiteral.class) && expr instanceof BinaryPredicate) { ArrayList children = expr.getChildren(); - String filter = children.get(0).toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + ToSqlParams params = new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, tbl); + String filter = children.get(0).accept(ExprToExternalSqlVisitor.INSTANCE, params); filter += " " + ((BinaryPredicate) expr).getOp().toString() + " "; if (tableType.equals(TOdbcTableType.ORACLE)) { @@ -341,7 +346,7 @@ public static String conjunctExprToString(TOdbcTableType tableType, Expr expr, T } else if (tableType.equals(TOdbcTableType.SQLSERVER)) { filter += handleSQLServerDateFormat(children.get(1), tbl); } else { - filter += children.get(1).toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + filter += children.get(1).accept(ExprToExternalSqlVisitor.INSTANCE, params); } return filter; @@ -350,7 +355,8 @@ public static String conjunctExprToString(TOdbcTableType tableType, Expr expr, T if (expr.contains(DateLiteral.class) && expr instanceof InPredicate) { InPredicate inPredicate = (InPredicate) expr; Expr leftChild = inPredicate.getChild(0); - String filter = leftChild.toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + ToSqlParams params = new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, tbl); + String filter = leftChild.accept(ExprToExternalSqlVisitor.INSTANCE, params); if (inPredicate.isNotIn()) { filter += " NOT"; @@ -367,7 +373,7 @@ public static String conjunctExprToString(TOdbcTableType tableType, Expr expr, T } else if (tableType.equals(TOdbcTableType.SQLSERVER)) { inItemStrings.add(handleSQLServerDateFormat(inItem, tbl)); } else { - inItemStrings.add(inItem.toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl)); + inItemStrings.add(inItem.accept(ExprToExternalSqlVisitor.INSTANCE, params)); } } @@ -382,7 +388,8 @@ public static String conjunctExprToString(TOdbcTableType tableType, Expr expr, T return "1 = 1"; } - return expr.toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + return expr.accept(ExprToExternalSqlVisitor.INSTANCE, + new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, tbl)); } private static String handleOracleDateFormat(Expr expr, TableIf tbl) { @@ -399,7 +406,8 @@ private static String handleOracleDateFormat(Expr expr, TableIf tbl) { // Regular datetime without fractional seconds return "to_date('" + dateStr + "', 'yyyy-mm-dd hh24:mi:ss')"; } - return expr.toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + return expr.accept(ExprToExternalSqlVisitor.INSTANCE, + new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, tbl)); } @NotNull @@ -426,7 +434,8 @@ private static String handleTrinoDateFormat(Expr expr, TableIf tbl) { return "timestamp '" + expr.getStringValue() + "'"; } } - return expr.toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + return expr.accept(ExprToExternalSqlVisitor.INSTANCE, + new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, tbl)); } private static String handleSQLServerDateFormat(Expr expr, TableIf tbl) { @@ -441,7 +450,8 @@ private static String handleSQLServerDateFormat(Expr expr, TableIf tbl) { return "CONVERT(DATE, '" + expr.getStringValue() + "', 23)"; } } - return expr.toExternalSql(TableType.JDBC_EXTERNAL_TABLE, tbl); + return expr.accept(ExprToExternalSqlVisitor.INSTANCE, + new ToSqlParams(false, true, TableType.JDBC_EXTERNAL_TABLE, tbl)); } private static boolean containsNullLiteral(Expr expr) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeMetadataOps.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeMetadataOps.java index 2b956468d010b9..f9bda6936c9a40 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeMetadataOps.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/maxcompute/MaxComputeMetadataOps.java @@ -19,10 +19,12 @@ import org.apache.doris.analysis.DistributionDesc; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.FunctionCallExpr; import org.apache.doris.analysis.HashDistributionDesc; import org.apache.doris.analysis.PartitionDesc; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.ArrayType; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.MapType; @@ -451,7 +453,8 @@ private void validatePartitionDesc(PartitionDesc partitionDesc) throws UserExcep "MaxCompute does not support partition transform '" + funcName + "'. Only identity partitions are supported."); } else { - throw new UserException("Invalid partition expression: " + expr.toSql()); + throw new UserException("Invalid partition expression: " + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/odbc/source/OdbcScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/odbc/source/OdbcScanNode.java index aa8d105959d67b..abe1ff6f072be0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/odbc/source/OdbcScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/odbc/source/OdbcScanNode.java @@ -19,9 +19,11 @@ import org.apache.doris.analysis.Expr; import org.apache.doris.analysis.ExprSubstitutionMap; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.FunctionCallExpr; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.JdbcTable; @@ -105,7 +107,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append(prefix).append("QUERY: ").append(getOdbcQueryStr()).append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } if (useTopnFilter()) { String topnFilterSources = String.join(",", diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/BrokerFileGroup.java b/fe/fe-core/src/main/java/org/apache/doris/load/BrokerFileGroup.java index e8c2e755146f0a..edeff1b930028f 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/BrokerFileGroup.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/BrokerFileGroup.java @@ -19,7 +19,9 @@ import org.apache.doris.analysis.DataDescription; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.ImportColumnDesc; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.AggregateType; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Database; @@ -375,20 +377,24 @@ public String toString() { public NereidsBrokerFileGroup toNereidsBrokerFileGroup() throws UserException { Expression deleteCondition = getDeleteCondition() != null - ? NereidsLoadUtils.parseExpressionSeq(getDeleteCondition().toSqlWithoutTbl()).get(0) + ? NereidsLoadUtils.parseExpressionSeq(getDeleteCondition().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).get(0) : null; Expression precedingFilter = getPrecedingFilterExpr() != null - ? NereidsLoadUtils.parseExpressionSeq(getPrecedingFilterExpr().toSqlWithoutTbl()).get(0) + ? NereidsLoadUtils.parseExpressionSeq(getPrecedingFilterExpr().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).get(0) : null; Expression whereExpr = getWhereExpr() != null - ? NereidsLoadUtils.parseExpressionSeq(getWhereExpr().toSqlWithoutTbl()).get(0) + ? NereidsLoadUtils.parseExpressionSeq(getWhereExpr().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).get(0) : null; List importColumnDescs = null; if (columnExprList != null && !columnExprList.isEmpty()) { importColumnDescs = new ArrayList<>(columnExprList.size()); for (ImportColumnDesc desc : columnExprList) { Expression expression = desc.getExpr() != null - ? NereidsLoadUtils.parseExpressionSeq(desc.getExpr().toSqlWithoutTbl()).get(0) + ? NereidsLoadUtils.parseExpressionSeq(desc.getExpr().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).get(0) : null; importColumnDescs.add(new NereidsImportColumnDesc(desc.getColumnName(), expression)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java index 2f619a4cc53a89..99e22aa2a08d22 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteJob.java @@ -18,11 +18,13 @@ package org.apache.doris.load; import org.apache.doris.analysis.BinaryPredicate; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.IsNullPredicate; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.Predicate; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Database; import org.apache.doris.catalog.Env; @@ -807,7 +809,8 @@ private List getDeleteCondString(List conditions) { String notStr = inPredicate.isNotIn() ? "NOT " : ""; strBuilder.append(columnName).append(" ").append(notStr).append("IN ("); for (int i = 1; i <= inPredicate.getInElementNum(); ++i) { - strBuilder.append(inPredicate.getChild(i).toSql()); + strBuilder.append(inPredicate.getChild(i) + .accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); strBuilder.append((i != inPredicate.getInElementNum()) ? ", " : ""); } strBuilder.append(")"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/MysqlLoadManager.java b/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/MysqlLoadManager.java index 5b11d225b59a22..12f000b7b166ba 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/MysqlLoadManager.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/loadv2/MysqlLoadManager.java @@ -19,8 +19,10 @@ import org.apache.doris.analysis.DataDescription; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SetVar; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.Env; import org.apache.doris.cluster.ClusterNamespace; @@ -394,7 +396,7 @@ private String getColumns(DataDescription desc) { fieldString.append(","); List mappings = new ArrayList<>(); for (Expr expr : desc.getColumnMappingList()) { - mappings.add(expr.toSql().replaceAll("`", "")); + mappings.add(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE).replaceAll("`", "")); } fieldString.append(Joiner.on(",").join(mappings)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/routineload/KafkaRoutineLoadJob.java b/fe/fe-core/src/main/java/org/apache/doris/load/routineload/KafkaRoutineLoadJob.java index 7cd2a71d2f26c7..4e2827403a4a6a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/routineload/KafkaRoutineLoadJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/routineload/KafkaRoutineLoadJob.java @@ -17,7 +17,9 @@ package org.apache.doris.load.routineload; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.ImportColumnDesc; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.Database; import org.apache.doris.catalog.Env; @@ -953,20 +955,26 @@ public Long totalLag() { @Override public NereidsRoutineLoadTaskInfo toNereidsRoutineLoadTaskInfo() throws UserException { Expression deleteCondition = getDeleteCondition() != null - ? NereidsLoadUtils.parseExpressionSeq(getDeleteCondition().toSql()).get(0) + ? NereidsLoadUtils.parseExpressionSeq( + getDeleteCondition().accept(ExprToSqlVisitor.INSTANCE, + ToSqlParams.WITHOUT_TABLE)).get(0) : null; Expression precedingFilter = getPrecedingFilter() != null - ? NereidsLoadUtils.parseExpressionSeq(getPrecedingFilter().toSql()).get(0) + ? NereidsLoadUtils.parseExpressionSeq( + getPrecedingFilter().accept(ExprToSqlVisitor.INSTANCE, + ToSqlParams.WITHOUT_TABLE)).get(0) : null; Expression whereExpr = getWhereExpr() != null - ? NereidsLoadUtils.parseExpressionSeq(getWhereExpr().toSqlWithoutTbl()).get(0) + ? NereidsLoadUtils.parseExpressionSeq(getWhereExpr().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).get(0) : null; NereidsLoadTaskInfo.NereidsImportColumnDescs importColumnDescs = null; if (columnDescs != null) { importColumnDescs = new NereidsLoadTaskInfo.NereidsImportColumnDescs(); for (ImportColumnDesc desc : columnDescs.descs) { Expression expression = desc.getExpr() != null - ? NereidsLoadUtils.parseExpressionSeq(desc.getExpr().toSqlWithoutTbl()).get(0) + ? NereidsLoadUtils.parseExpressionSeq(desc.getExpr().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).get(0) : null; importColumnDescs.descs.add(new NereidsImportColumnDesc(desc.getColumnName(), expression)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/routineload/RoutineLoadJob.java b/fe/fe-core/src/main/java/org/apache/doris/load/routineload/RoutineLoadJob.java index 796c427a16c67c..0266d9f5e7be26 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/load/routineload/RoutineLoadJob.java +++ b/fe/fe-core/src/main/java/org/apache/doris/load/routineload/RoutineLoadJob.java @@ -18,8 +18,10 @@ package org.apache.doris.load.routineload; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.ImportColumnsStmt; import org.apache.doris.analysis.Separator; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.Database; import org.apache.doris.catalog.Env; @@ -1763,7 +1765,8 @@ public String getShowCreateInfo() { } // 4.3.where_predicates if (whereExpr != null) { - sb.append("WHERE ").append(whereExpr.toSqlWithoutTbl()).append(",\n"); + sb.append("WHERE ").append(whereExpr.accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).append(",\n"); } // 4.4.partitions if (partitionNamesInfo != null) { @@ -1771,7 +1774,8 @@ public String getShowCreateInfo() { } // 4.5.delete_on_predicates if (deleteCondition != null) { - sb.append("DELETE ON ").append(deleteCondition.toSqlWithoutTbl()).append(",\n"); + sb.append("DELETE ON ").append(deleteCondition.accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).append(",\n"); } // 4.6.source_sequence if (sequenceCol != null) { @@ -1779,7 +1783,8 @@ public String getShowCreateInfo() { } // 4.7.preceding_predicates if (precedingFilter != null) { - sb.append("PRECEDING FILTER ").append(precedingFilter.toSqlWithoutTbl()).append(",\n"); + sb.append("PRECEDING FILTER ").append(precedingFilter.accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)).append(",\n"); } // remove the last , if (sb.charAt(sb.length() - 2) == ',') { @@ -1874,8 +1879,10 @@ public String jobPropertiesToJsonString() { ? STAR_STRING : Joiner.on(",").join(partitionNamesInfo.getPartitionNames())); jobProperties.put("columnToColumnExpr", columnDescs == null ? STAR_STRING : Joiner.on(",").join(columnDescs.descs)); - jobProperties.put("precedingFilter", precedingFilter == null ? STAR_STRING : precedingFilter.toSqlWithoutTbl()); - jobProperties.put("whereExpr", whereExpr == null ? STAR_STRING : whereExpr.toSqlWithoutTbl()); + jobProperties.put("precedingFilter", precedingFilter == null ? STAR_STRING + : precedingFilter.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); + jobProperties.put("whereExpr", whereExpr == null ? STAR_STRING + : whereExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); if (getFormat().equalsIgnoreCase("json")) { jobProperties.put(FileFormatProperties.PROP_FORMAT, "json"); } else { @@ -1885,7 +1892,8 @@ public String jobPropertiesToJsonString() { lineDelimiter == null ? "\n" : lineDelimiter.toString()); } jobProperties.put(LoadCommand.KEY_IN_PARAM_DELETE_CONDITION, - deleteCondition == null ? STAR_STRING : deleteCondition.toSqlWithoutTbl()); + deleteCondition == null ? STAR_STRING + : deleteCondition.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); jobProperties.put(LoadCommand.KEY_IN_PARAM_SEQUENCE_COL, sequenceCol == null ? STAR_STRING : sequenceCol); diff --git a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPlanUtil.java b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPlanUtil.java index 17801b7607296f..4be21db3008033 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPlanUtil.java +++ b/fe/fe-core/src/main/java/org/apache/doris/mtmv/MTMVPlanUtil.java @@ -18,7 +18,9 @@ package org.apache.doris.mtmv; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.StatementBase; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.catalog.AggregateType; import org.apache.doris.catalog.Column; @@ -388,7 +390,8 @@ public static MTMVAnalyzeQueryInfo analyzeQueryWithSql(MTMV mtmv, ConnectContext mtmvPartitionDefinition.setPartitionType(mvPartitionInfo.getPartitionType()); Expr expr = mvPartitionInfo.getExpr(); if (expr != null) { - mtmvPartitionDefinition.setFunctionCallExpression(new NereidsParser().parseExpression(expr.toSql())); + mtmvPartitionDefinition.setFunctionCallExpression(new NereidsParser().parseExpression( + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE))); } List keys = mtmv.getBaseSchema().stream() .filter(Column::isKey) diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/load/NereidsStreamLoadTask.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/load/NereidsStreamLoadTask.java index 4b372bcae0ec1d..00ff14e11e2534 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/load/NereidsStreamLoadTask.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/load/NereidsStreamLoadTask.java @@ -17,7 +17,9 @@ package org.apache.doris.nereids.load; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.Separator; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.info.PartitionNamesInfo; import org.apache.doris.common.AnalysisException; import org.apache.doris.common.Config; @@ -368,10 +370,12 @@ public static NereidsStreamLoadTask fromTStreamLoadPutRequest(TStreamLoadPutRequ public void setMultiTableBaseTaskInfo(LoadTaskInfo task) throws UserException { this.mergeType = task.getMergeType(); this.columnSeparator = task.getColumnSeparator(); - this.whereExpr = task.getWhereExpr() != null ? parseWhereExpr(task.getWhereExpr().toSqlWithoutTbl()) : null; + this.whereExpr = task.getWhereExpr() != null ? parseWhereExpr( + task.getWhereExpr().accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)) : null; this.partitionNamesInfo = task.getPartitionNamesInfo(); this.deleteCondition = task.getDeleteCondition() != null - ? parseWhereExpr(task.getDeleteCondition().toSqlWithoutTbl()) + ? parseWhereExpr(task.getDeleteCondition().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)) : null; this.lineDelimiter = task.getLineDelimiter(); this.strictMode = task.isStrictMode(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java index b887180c69f649..33eff55f0acb0c 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/BindSink.java @@ -18,7 +18,9 @@ package org.apache.doris.nereids.rules.analysis; import org.apache.doris.analysis.ColumnDef.DefaultValue; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Database; import org.apache.doris.catalog.DatabaseIf; @@ -490,7 +492,8 @@ private static Map getColumnToOutput( try (AutoCloseSessionVariable autoClose = new AutoCloseSessionVariable(ctx.connectContext, column.getSessionVariables())) { GeneratedColumnInfo info = column.getGeneratedColumnInfo(); - Expression parsedExpression = new NereidsParser().parseExpression(info.getExpr().toSqlWithoutTbl()); + Expression parsedExpression = new NereidsParser().parseExpression( + info.getExpr().accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); Expression boundExpression = new CustomExpressionAnalyzer(boundSink, ctx.cascadesContext, columnToReplaced) .analyze(parsedExpression); @@ -519,7 +522,7 @@ private static Map getColumnToOutput( try (AutoCloseSessionVariable autoClose = new AutoCloseSessionVariable(ctx.connectContext, column.getSessionVariables())) { Expression parsedExpression = expressionParser.parseExpression( - column.getDefineExpr().toSqlWithoutTbl()); + column.getDefineExpr().accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); // the boundSlotExpression is an expression whose slots are bound but function // may not be bound, we have to bind it again. // for example: to_bitmap. @@ -536,7 +539,8 @@ private static Map getColumnToOutput( } boundExpression = TypeCoercionUtils.castIfNotSameType(boundExpression, DataType.fromCatalogType(column.getType())); - Alias output = new Alias(boundExpression, column.getDefineExpr().toSqlWithoutTbl()); + Alias output = new Alias(boundExpression, column.getDefineExpr().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); columnToOutput.put(column.getName(), output); columnToReplaced.put(column.getName(), output.toSlot()); replaceMap.put(output.toSlot(), output.child()); @@ -1163,7 +1167,8 @@ public LegacyExprTranslator(OlapTable table, List outputs) { public List createPartitionExprList() { return olapTable.getPartitionInfo().getPartitionExprs().stream() - .map(expr -> analyze(expr.toSql())).collect(Collectors.toList()); + .map(expr -> analyze(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE))) + .collect(Collectors.toList()); } public Map createSyncMvWhereClause() { @@ -1175,7 +1180,8 @@ public Map createSyncMvWhereClause() { if (entry.getKey() == baseIndexId || entry.getValue().getWhereClause() == null) { continue; } - Expression predicate = analyze(entry.getValue().getWhereClause().toSqlWithoutTbl()); + Expression predicate = analyze(entry.getValue().getWhereClause().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); predicate = predicate.accept(new AddSessionVarGuardRewriter( entry.getValue().getSessionVariables()), Boolean.FALSE); mvWhereClauses.put(entry.getKey(), predicate); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java index ada1808351f8a4..041df6694d4574 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/udf/AliasUdf.java @@ -17,6 +17,8 @@ package org.apache.doris.nereids.trees.expressions.functions.udf; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.AliasFunction; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.FunctionSignature; @@ -97,7 +99,8 @@ public boolean nullable() { * translate catalog alias function to nereids alias function */ public static void translateToNereidsFunction(String dbName, AliasFunction function) { - String functionSql = function.getOriginFunction().toSqlWithoutTbl(); + String functionSql = function.getOriginFunction().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); Map sessionVariables = function.getSessionVariables(); Expression parsedFunction; try (AutoCloseSessionVariable autoClose = new AutoCloseSessionVariable(ConnectContext.get(), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java index ba6d783753914f..876a761e05709b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateFunctionCommand.java @@ -1182,7 +1182,6 @@ public Expr visitSlotReference(SlotReference slotReference, PlanTranslatorContex SlotRef slotRef = new SlotRef(slotReference.getDataType().toCatalogDataType(), slotReference.nullable()); slotRef.setLabel(slotReference.getName()); slotRef.setCol(slotReference.getName()); - slotRef.disableTableName(); return slotRef; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateMaterializedViewCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateMaterializedViewCommand.java index fc1327586e64f7..4acdaa91e7bc0e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateMaterializedViewCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateMaterializedViewCommand.java @@ -18,9 +18,11 @@ package org.apache.doris.nereids.trees.plans.commands; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.MVColumnItem; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StmtType; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.AggregateType; import org.apache.doris.catalog.Column; @@ -288,7 +290,6 @@ public Plan visitLogicalOlapScan(LogicalOlapScan olapScan, ValidateContext valid translatorContext.createSlotDesc(tupleDescriptor, (SlotReference) slot, olapTable); SlotRef slotRef = translatorContext.findSlotRef(slot.getExprId()); slotRef.setLabel("`" + slot.getName() + "`"); - slotRef.disableTableName(); } return olapScan; } @@ -329,7 +330,9 @@ public Plan visitLogicalFilter(LogicalFilter filter, ValidateCon } try { Expr defineExpr = translateToLegacyExpr(predicate, context.planTranslatorContext); - context.filterItem = new MVColumnItem(defineExpr.toSqlWithoutTbl(), defineExpr); + context.filterItem = new MVColumnItem( + defineExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE), + defineExpr); } catch (Exception ex) { throw new AnalysisException(ex.getMessage()); } @@ -629,7 +632,6 @@ private MVColumnItem buildMVColumnItem(String name, AggregateFunction aggregateF private Expr translateToLegacyExpr(Expression expression, PlanTranslatorContext context) { Expr expr = ExpressionTranslator.translate(expression, context); - expr.disableTableName(); return expr; } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DeleteFromCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DeleteFromCommand.java index 04e155b29fc42b..fa451743733947 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DeleteFromCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DeleteFromCommand.java @@ -18,11 +18,13 @@ package org.apache.doris.nereids.trees.plans.commands; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.Predicate; import org.apache.doris.analysis.SetVar; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StmtType; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Database; import org.apache.doris.catalog.Env; @@ -210,7 +212,8 @@ public void run(ConnectContext ctx, StmtExecutor executor) throws Exception { if (c instanceof Predicate) { return (Predicate) c; } else { - throw new AnalysisException("non predicate in filter: " + c.toSql()); + throw new AnalysisException("non predicate in filter: " + + c.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } }).collect(Collectors.toList()); if (predicates.isEmpty()) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java index 1d5c0713d641f9..9cdaed1e2d02f6 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/DescribeCommand.java @@ -18,6 +18,8 @@ package org.apache.doris.nereids.trees.plans.commands; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.Env; @@ -342,8 +344,8 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exc String defineExprStr = ""; Expr defineExpr = column.getDefineExpr(); if (defineExpr != null) { - column.getDefineExpr().disableTableName(); - defineExprStr = defineExpr.toSqlWithoutTbl(); + defineExprStr = defineExpr.accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); } List row = Arrays.asList( @@ -367,7 +369,8 @@ public ShowResultSet doRun(ConnectContext ctx, StmtExecutor executor) throws Exc row.set(1, indexMeta.getKeysType().name()); Expr where = indexMeta.getWhereClause(); row.set(getMetaData().getColumns().size() - 1, - where == null ? "" : where.toSqlWithoutTbl()); + where == null ? "" : where.accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); } rows.add(row); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java index 418bfcca81f005..aeb0821f55cff8 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowColumnStatsCommand.java @@ -17,6 +17,8 @@ package org.apache.doris.nereids.trees.plans.commands; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.Env; @@ -277,8 +279,10 @@ private ShowResultSet constructResultSet(List, ColumnS row.add(String.valueOf(p.second.numNulls)); row.add(String.valueOf(p.second.dataSize)); row.add(String.valueOf(p.second.avgSizeByte)); - row.add(String.valueOf(p.second.minExpr == null ? "N/A" : p.second.minExpr.toSql())); - row.add(String.valueOf(p.second.maxExpr == null ? "N/A" : p.second.maxExpr.toSql())); + row.add(String.valueOf(p.second.minExpr == null ? "N/A" + : p.second.minExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE))); + row.add(String.valueOf(p.second.maxExpr == null ? "N/A" + : p.second.maxExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE))); ColStatsMeta colStatsMeta = analysisManager.findColStatsMeta(table.getId(), p.first.first, p.first.second); row.add(String.valueOf(colStatsMeta == null ? "N/A" : colStatsMeta.analysisMethod)); row.add(String.valueOf(colStatsMeta == null ? "N/A" : colStatsMeta.analysisType)); @@ -351,8 +355,10 @@ private ShowResultSet constructPartitionCachedColumnStats( row.add(String.valueOf(value.count)); // count row.add(String.valueOf(value.ndv.estimateCardinality())); // ndv row.add(String.valueOf(value.numNulls)); // num_null - row.add(String.valueOf(value.minExpr == null ? "N/A" : value.minExpr.toSql())); // min - row.add(String.valueOf(value.maxExpr == null ? "N/A" : value.maxExpr.toSql())); // max + row.add(String.valueOf(value.minExpr == null ? "N/A" + : value.minExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE))); // min + row.add(String.valueOf(value.maxExpr == null ? "N/A" + : value.maxExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE))); // max row.add(String.valueOf(value.dataSize)); // data_size row.add(value.updatedTime); // updated_time row.add("N/A"); // update_rows diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java index d49e2d8351c49b..f64f201a7ae61b 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/ShowFunctionsCommand.java @@ -17,7 +17,9 @@ package org.apache.doris.nereids.trees.plans.commands; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SetType; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.AggregateFunction; import org.apache.doris.catalog.AliasFunction; import org.apache.doris.catalog.Column; @@ -327,7 +329,9 @@ private String buildProperties(Function function) { if (function instanceof AliasFunction) { AliasFunction aliasFunction = (AliasFunction) function; - properties.put("ALIAS_OF", aliasFunction.getOriginFunction().toSqlWithoutTbl()); + properties.put("ALIAS_OF", + aliasFunction.getOriginFunction().accept( + ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE)); if (aliasFunction.getParameters() != null && !aliasFunction.getParameters().isEmpty()) { properties.put("PARAMETERS", String.join(",", aliasFunction.getParameters())); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/FrontendConjunctsUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/FrontendConjunctsUtils.java index 2253df2f4b05d5..0c3aa7b56c4812 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/FrontendConjunctsUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/FrontendConjunctsUtils.java @@ -18,6 +18,8 @@ package org.apache.doris.nereids.util; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.nereids.analyzer.UnboundSlot; import org.apache.doris.nereids.parser.NereidsParser; import org.apache.doris.nereids.rules.expression.rules.FoldConstantRuleOnFE; @@ -55,7 +57,7 @@ public static List convertToExpression(String conjuncts) { public static Expression exprToExpression(Expr expr) { NereidsParser nereidsParser = new NereidsParser(); - return nereidsParser.parseExpression(expr.toSql()); + return nereidsParser.parseExpression(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } /** diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java index 5f0de7da4e8905..a635c2b1fd0b8e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/util/PlanUtils.java @@ -484,7 +484,6 @@ public Expr visitSlotReference(SlotReference slotReference, PlanTranslatorContex SlotRef slotRef = new SlotRef(slotReference.getDataType().toCatalogDataType(), slotReference.nullable()); slotRef.setLabel(slotReference.getName()); slotRef.setCol(slotReference.getName()); - slotRef.disableTableName(); return slotRef; } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/AnalyticEvalNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/AnalyticEvalNode.java index 6992eeb001ae6f..206aad604a56e4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/AnalyticEvalNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/AnalyticEvalNode.java @@ -22,7 +22,9 @@ import org.apache.doris.analysis.AnalyticWindow; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.OrderByElement; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.thrift.TAnalyticNode; import org.apache.doris.thrift.TExplainLevel; @@ -99,7 +101,7 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { List strings = Lists.newArrayList(); for (Expr fnCall : analyticFnCalls) { - strings.add("[" + fnCall.toSql() + "]"); + strings.add("[" + fnCall.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE) + "]"); } output.append(Joiner.on(", ").join(strings)); @@ -110,7 +112,7 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { strings.clear(); for (Expr partitionExpr : partitionExprs) { - strings.add(partitionExpr.toSql()); + strings.add(partitionExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } output.append(Joiner.on(", ").join(strings)); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/DataPartition.java b/fe/fe-core/src/main/java/org/apache/doris/planner/DataPartition.java index 648fbace47c890..a08f2329035109 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/DataPartition.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/DataPartition.java @@ -21,6 +21,8 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.thrift.TDataPartition; import org.apache.doris.thrift.TExplainLevel; import org.apache.doris.thrift.TPartitionType; @@ -103,7 +105,7 @@ public String getExplainString(TExplainLevel explainLevel) { if (!partitionExprs.isEmpty()) { List strings = Lists.newArrayList(); for (Expr expr : partitionExprs) { - strings.add(expr.toSql()); + strings.add(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } str.append(": ").append(Joiner.on(", ").join(strings)); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/DataStreamSink.java b/fe/fe-core/src/main/java/org/apache/doris/planner/DataStreamSink.java index 155b63d6224516..7ba15418dc5c51 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/DataStreamSink.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/DataStreamSink.java @@ -21,6 +21,8 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.thrift.TDataSink; import org.apache.doris.thrift.TDataSinkType; @@ -163,7 +165,8 @@ public String getExplainString(String prefix, TExplainLevel explainLevel) { } if (!conjuncts.isEmpty()) { Expr expr = PlanNode.convertConjunctsToAndCompoundPredicate(conjuncts); - strBuilder.append(prefix).append(" CONJUNCTS: ").append(expr.toSql()).append("\n"); + strBuilder.append(prefix).append(" CONJUNCTS: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } if (!runtimeFilters.isEmpty()) { strBuilder.append(prefix).append(" runtime filters: "); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/HashJoinNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/HashJoinNode.java index e5e40126b13c89..bce81edf508dfa 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/HashJoinNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/HashJoinNode.java @@ -22,8 +22,10 @@ import org.apache.doris.analysis.BinaryPredicate; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.JoinOperator; import org.apache.doris.analysis.SlotId; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.nereids.trees.expressions.ExprId; import org.apache.doris.thrift.TEqJoinCondition; @@ -201,7 +203,8 @@ public String getNodeExplainString(String detailPrefix, TExplainLevel detailLeve } for (BinaryPredicate eqJoinPredicate : eqJoinConjuncts) { - output.append(detailPrefix).append("equal join conjunct: ").append(eqJoinPredicate.toSql()).append("\n"); + output.append(detailPrefix).append("equal join conjunct: ") + .append(eqJoinPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } if (!otherJoinConjuncts.isEmpty()) { output.append(detailPrefix).append("other join predicates: ") diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java index 8e2425e65ad51e..06c9a4d7e4c5f5 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapScanNode.java @@ -18,12 +18,14 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotId; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.SortInfo; import org.apache.doris.analysis.TableSample; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.analysis.TupleId; import org.apache.doris.catalog.AggregateType; @@ -993,7 +995,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { if (sortInfo != null) { output.append(prefix).append("SORT INFO:\n"); sortInfo.getOrderingExprs().forEach(expr -> { - output.append(prefix).append(prefix).append(expr.toSql()).append("\n"); + output.append(prefix).append(prefix) + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); }); } if (sortLimit != -1) { @@ -1002,7 +1005,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { if (scoreSortInfo != null) { output.append(prefix).append("SCORE SORT INFO:\n"); scoreSortInfo.getOrderingExprs().forEach(expr -> { - output.append(prefix).append(prefix).append(expr.toSql()).append("\n"); + output.append(prefix).append(prefix) + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); }); } if (scoreSortLimit != -1) { @@ -1012,7 +1016,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { if (annSortInfo != null) { output.append(prefix).append("ANN SORT INFO:\n"); annSortInfo.getOrderingExprs().forEach(expr -> { - output.append(prefix).append(prefix).append(expr.toSql()).append("\n"); + output.append(prefix).append(prefix) + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); }); } if (annSortLimit != -1) { @@ -1028,7 +1033,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } String selectedPartitions = getSelectedPartitionIds().stream().sorted() diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java index a84c14083cc012..9feff0d36a448a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/OlapTableSink.java @@ -19,9 +19,11 @@ import org.apache.doris.alter.SchemaChangeHandler; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.NullLiteral; import org.apache.doris.analysis.SlotDescriptor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.DistributionInfo; @@ -427,7 +429,8 @@ private TOlapTableSchemaParam createSchema(long dbId, OlapTable table) throws An if (whereClause != null) { Expr expr = syncMvWhereClauses.getOrDefault(pair.getKey(), null); if (expr == null) { - throw new AnalysisException(String.format("%s is not analyzed", whereClause.toSqlWithoutTbl())); + throw new AnalysisException(String.format("%s is not analyzed", + whereClause.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE))); } indexSchema.setWhereClause(expr.treeToThrift()); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/PartitionSortNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/PartitionSortNode.java index e8953f56fa7792..ef56f9062e17f4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/PartitionSortNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/PartitionSortNode.java @@ -18,7 +18,9 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SortInfo; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.nereids.trees.plans.PartitionTopnPhase; import org.apache.doris.nereids.trees.plans.WindowFuncType; import org.apache.doris.thrift.TExplainLevel; @@ -90,7 +92,7 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append(prefix).append("partition by: "); for (Expr partitionExpr : partitionExprs) { - strings.add(partitionExpr.toSql()); + strings.add(partitionExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } output.append(Joiner.on(", ").join(strings)); @@ -108,7 +110,7 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { } else { output.append(", "); } - output.append(expr.next().toSql()).append(" "); + output.append(expr.next().accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append(" "); output.append(isAsc.next() ? "ASC" : "DESC"); } output.append("\n"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java index 4c77bef0b87b0f..7d6137aec23af9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanFragment.java @@ -21,10 +21,12 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.JoinOperator; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StatementBase; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.common.TreeNode; import org.apache.doris.nereids.trees.plans.distribute.NereidsSpecifyInstances; @@ -354,7 +356,9 @@ public String getExplainString(TExplainLevel explainLevel) { Preconditions.checkState(dataPartition != null); if (CollectionUtils.isNotEmpty(outputExprs)) { str.append(" OUTPUT EXPRS:\n "); - str.append(outputExprs.stream().map(Expr::toSql).collect(Collectors.joining("\n "))); + str.append(outputExprs.stream() + .map(e -> e.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)) + .collect(Collectors.joining("\n "))); } str.append("\n"); str.append(" PARTITION: " + dataPartition.getExplainString(explainLevel) + "\n"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java index 14923c381b88da..c916c443c2bcb4 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/PlanNode.java @@ -22,9 +22,11 @@ import org.apache.doris.analysis.CompoundPredicate; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotDescriptor; import org.apache.doris.analysis.SlotId; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.analysis.TupleId; import org.apache.doris.common.Id; @@ -633,7 +635,7 @@ public static String getExplainString(List exprs) { if (i > 0) { output.append(", "); } - output.append(exprs.get(i).toSql()); + output.append(exprs.get(i).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } return output.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteNode.java index 96b6b97ef38c98..838facd27b320a 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteNode.java @@ -18,6 +18,8 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleId; import org.apache.doris.thrift.TExplainLevel; import org.apache.doris.thrift.TPlanNode; @@ -70,7 +72,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append(prefix).append("isUnionAll: ").append(isUnionAll).append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } return output.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java index 6f01cf624fe432..c0ed988010ca97 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/RecursiveCteScanNode.java @@ -18,6 +18,8 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.thrift.TExplainLevel; import org.apache.doris.thrift.TPlanNode; @@ -40,7 +42,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append(prefix).append("Recursive Cte: ").append(recursiveCteName).append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } return output.toString(); } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java b/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java index 6dc33a88c0b60c..eddaf2a7f9b551 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/RuntimeFilter.java @@ -19,7 +19,9 @@ import org.apache.doris.analysis.BinaryPredicate; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotId; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleId; import org.apache.doris.common.FeConstants; import org.apache.doris.qe.ConnectContext; @@ -493,7 +495,7 @@ public String getExplainString(PlanNodeId nodeId) { if (getBuilderNode().getId().equals(nodeId)) { // source side filterStr.append(" <- "); - filterStr.append(getSrcExpr().toSql()); + filterStr.append(getSrcExpr().accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); filterStr.append("(").append(getEstimateNdv()).append("/") .append(getExpectFilterSizeBytes()).append("/") .append(getFilterSizeBytes()).append(")"); @@ -501,7 +503,7 @@ public String getExplainString(PlanNodeId nodeId) { // target side if (getTargetExpr(nodeId) != null) { filterStr.append(" -> "); - filterStr.append(getTargetExpr(nodeId).toSql()); + filterStr.append(getTargetExpr(nodeId).accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } return filterStr.toString(); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SchemaScanNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/SchemaScanNode.java index 88448d7df68e2d..1de7b4ad800cfd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/SchemaScanNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SchemaScanNode.java @@ -18,6 +18,8 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleDescriptor; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.SchemaTable; @@ -183,11 +185,13 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { output.append("\n"); if (!conjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(conjuncts); - output.append(prefix).append("PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } if (!frontendConjuncts.isEmpty()) { Expr expr = convertConjunctsToAndCompoundPredicate(frontendConjuncts); - output.append(prefix).append("FRONTEND PREDICATES: ").append(expr.toSql()).append("\n"); + output.append(prefix).append("FRONTEND PREDICATES: ") + .append(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append("\n"); } if (!runtimeFilters.isEmpty()) { output.append(prefix).append("runtime filters: "); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SetOperationNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/SetOperationNode.java index 2745fcaa135324..f54c5c7a967b37 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/SetOperationNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SetOperationNode.java @@ -18,6 +18,8 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleId; import org.apache.doris.thrift.TExceptNode; import org.apache.doris.thrift.TExplainLevel; @@ -147,7 +149,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { if (CollectionUtils.isNotEmpty(materializedConstExprLists)) { output.append(prefix).append("constant exprs: ").append("\n"); for (List exprs : materializedConstExprLists) { - output.append(prefix).append(" ").append(exprs.stream().map(Expr::toSql) + output.append(prefix).append(" ").append(exprs.stream() + .map(e -> e.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)) .collect(Collectors.joining(" | "))).append("\n"); } } @@ -155,7 +158,8 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { if (CollectionUtils.isNotEmpty(materializedResultExprLists)) { output.append(prefix).append("child exprs: ").append("\n"); for (List exprs : materializedResultExprLists) { - output.append(prefix).append(" ").append(exprs.stream().map(Expr::toSql) + output.append(prefix).append(" ").append(exprs.stream() + .map(e -> e.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)) .collect(Collectors.joining(" | "))).append("\n"); } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java index a0e65a380115bd..c94c1764d61be2 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/SortNode.java @@ -21,7 +21,9 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SortInfo; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.common.Pair; import org.apache.doris.qe.ConnectContext; import org.apache.doris.thrift.TExplainLevel; @@ -160,7 +162,7 @@ public String getNodeExplainString(String detailPrefix, TExplainLevel detailLeve } else { output.append(", "); } - output.append(expr.next().toSql()).append(" "); + output.append(expr.next().accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append(" "); output.append(isAsc.next() ? "ASC" : "DESC"); } output.append("\n"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java b/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java index 21babbcc98942c..c9a67f2376b0ca 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java +++ b/fe/fe-core/src/main/java/org/apache/doris/planner/TableFunctionNode.java @@ -18,7 +18,9 @@ package org.apache.doris.planner; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.SlotId; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.TupleId; import org.apache.doris.thrift.TExplainLevel; import org.apache.doris.thrift.TPlanNode; @@ -73,7 +75,7 @@ public String getNodeExplainString(String prefix, TExplainLevel detailLevel) { StringBuilder output = new StringBuilder(); output.append(prefix).append("table function: "); for (Expr fnExpr : fnCallExprList) { - output.append(fnExpr.toSql()).append(" "); + output.append(fnExpr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)).append(" "); } output.append("\n"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java index 8ddf2487313817..01559bbb64dbd1 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java @@ -19,8 +19,10 @@ import org.apache.doris.analysis.BinaryPredicate; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.SlotRef; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.Env; import org.apache.doris.catalog.OlapTable; @@ -176,7 +178,8 @@ private static void updateScanNodeConjuncts(OlapScanNode scanNode, slot = (SlotRef) binaryPredicate.getChildWithoutCast(0); updateChildIdx = 1; } else { - Preconditions.checkState(false, "Should contains literal in " + binaryPredicate.toSqlImpl()); + Preconditions.checkState(false, "Should contains literal in " + + binaryPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // not a placeholder to replace if (!colNameToConjunct.containsKey(slot.getColumnName())) { diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java index 5480c2933b1c06..5005ad0759c660 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java @@ -18,6 +18,7 @@ package org.apache.doris.qe; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.OutFileClause; import org.apache.doris.analysis.PlaceHolderExpr; import org.apache.doris.analysis.Queriable; @@ -25,6 +26,7 @@ import org.apache.doris.analysis.StatementBase; import org.apache.doris.analysis.StorageBackend; import org.apache.doris.analysis.StorageBackend.StorageType; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Column; import org.apache.doris.catalog.DatabaseIf; import org.apache.doris.catalog.Env; @@ -282,7 +284,8 @@ public static InternalService.PDataRow getRowStringValue(List cols, } if (!expr.isLiteralOrCastExpr()) { throw new UserException( - "do not support non-literal expr in transactional insert operation: " + expr.toSql()); + "do not support non-literal expr in transactional insert operation: " + + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } row.addColBuilder().setValue(expr.getStringValueForStreamLoad(options)); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java index 32fa51706ecf2e..7d797e21b5baaf 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/DateLiteralTest.java @@ -35,7 +35,7 @@ public void testTimestampTzInit() throws AnalysisException { value = "2020-02-02 09:03:04.123456+08:00"; dateLiteral = new DateLiteral(value, ScalarType.createTimeStampTzType(6)); expectedResult = "'2020-02-02 01:03:04.123456+00:00'"; - Assertions.assertEquals(expectedResult, dateLiteral.toSql()); + Assertions.assertEquals(expectedResult, dateLiteral.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -72,12 +72,12 @@ public void testDatetimeV2Init() throws AnalysisException { value = "2020-02-02 09:03:04.123456+08:00"; dateLiteral = new DateLiteral(value, ScalarType.createDatetimeV2Type(6)); expectedResult = "'2020-02-02 09:03:04.123456'"; - Assertions.assertEquals(expectedResult, dateLiteral.toSql()); + Assertions.assertEquals(expectedResult, dateLiteral.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); value = "2020-02-02 09:03:04.123456+09:00"; dateLiteral = new DateLiteral(value, ScalarType.createDatetimeV2Type(6)); expectedResult = "'2020-02-02 08:03:04.123456'"; - Assertions.assertEquals(expectedResult, dateLiteral.toSql()); + Assertions.assertEquals(expectedResult, dateLiteral.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -89,10 +89,10 @@ public void testDateV2Init() throws AnalysisException { value = "2020-02-02+08:00"; dateLiteral = new DateLiteral(value, ScalarType.DATEV2); expectedResult = "'2020-02-02'"; - Assertions.assertEquals(expectedResult, dateLiteral.toSql()); + Assertions.assertEquals(expectedResult, dateLiteral.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); value = "2020-02-02+09:00"; dateLiteral = new DateLiteral(value, ScalarType.DATEV2); expectedResult = "'2020-02-01'"; - Assertions.assertEquals(expectedResult, dateLiteral.toSql()); + Assertions.assertEquals(expectedResult, dateLiteral.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToSqlTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToSqlTest.java index 6c38ff38978679..8afb41d101de57 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToSqlTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToSqlTest.java @@ -26,7 +26,11 @@ import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.info.TableNameInfo; +import org.apache.doris.nereids.util.MoreFieldsThread; +import org.apache.doris.qe.ConnectContext; +import org.apache.doris.qe.SessionVariable; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -35,11 +39,26 @@ import java.util.List; /** - * Unit tests verifying toSql() output for all 39 concrete Expr subclasses. - * These tests validate current behavior prior to visitor-pattern refactoring. + * Unit tests verifying visitor-based SQL generation for all 39 concrete Expr subclasses. + * Uses ExprToSqlVisitor and ExprToExternalSqlVisitor instead of the removed toSql() methods. */ public class ExprToSqlTest { + /** Remove any ConnectContext installed by a test so it does not leak into the next one. */ + @AfterEach + public void tearDown() { + ConnectContext.remove(); + } + + // helper: install a minimal ConnectContext with the given flags into the current thread. + private void installConnectContext(boolean isNereids, boolean isQuery) { + ConnectContext ctx = new ConnectContext(); + ctx.getState().setNereids(isNereids); + ctx.getState().setIsQuery(isQuery); + ctx.setSessionVariable(new SessionVariable()); + MoreFieldsThread.setConnectContext(ctx); + } + // ----------------------------------------------------------------------- // Literals // ----------------------------------------------------------------------- @@ -47,128 +66,128 @@ public class ExprToSqlTest { @Test public void testBoolLiteralTrue() { BoolLiteral expr = new BoolLiteral(true); - Assertions.assertEquals("TRUE", expr.toSql()); + Assertions.assertEquals("TRUE", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testBoolLiteralFalse() { BoolLiteral expr = new BoolLiteral(false); - Assertions.assertEquals("FALSE", expr.toSql()); + Assertions.assertEquals("FALSE", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testStringLiteralSimple() { StringLiteral expr = new StringLiteral("hello"); - Assertions.assertEquals("'hello'", expr.toSql()); + Assertions.assertEquals("'hello'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testStringLiteralWithSingleQuote() { // Single quotes inside the value should be escaped as '' StringLiteral expr = new StringLiteral("it's"); - Assertions.assertEquals("'it''s'", expr.toSql()); + Assertions.assertEquals("'it''s'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testIntLiteral() { IntLiteral expr = new IntLiteral(42L); - Assertions.assertEquals("42", expr.toSql()); + Assertions.assertEquals("42", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testFloatLiteralDouble() { FloatLiteral expr = new FloatLiteral(3.14, Type.DOUBLE); - Assertions.assertEquals("3.14", expr.toSql()); + Assertions.assertEquals("3.14", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testFloatLiteralDoubleWholeNumber() { // Trailing zeros are stripped: 1.0 → "1" FloatLiteral expr = new FloatLiteral(1.0, Type.DOUBLE); - Assertions.assertEquals("1", expr.toSql()); + Assertions.assertEquals("1", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testFloatLiteralFloat() { // FLOAT type uses maxFractionDigits=7; 1.5f fits exactly FloatLiteral expr = new FloatLiteral(1.5, Type.FLOAT); - Assertions.assertEquals("1.5", expr.toSql()); + Assertions.assertEquals("1.5", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testFloatLiteralFloatPrecisionArtifact() { // 3.14 cannot be represented exactly as a 32-bit float, exposing a precision artifact FloatLiteral expr = new FloatLiteral((double) 3.14f, Type.FLOAT); - Assertions.assertTrue(expr.toSql().startsWith("3.1400")); + Assertions.assertTrue(expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE).startsWith("3.1400")); } @Test public void testDecimalLiteral() { DecimalLiteral expr = new DecimalLiteral(new java.math.BigDecimal("1.5")); - Assertions.assertEquals("1.5", expr.toSql()); + Assertions.assertEquals("1.5", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testLargeIntLiteral() { LargeIntLiteral expr = new LargeIntLiteral(java.math.BigInteger.valueOf(12345678901234L)); - Assertions.assertEquals("12345678901234", expr.toSql()); + Assertions.assertEquals("12345678901234", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testNullLiteral() { NullLiteral expr = new NullLiteral(); - Assertions.assertEquals("NULL", expr.toSql()); + Assertions.assertEquals("NULL", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testMaxLiteral() { MaxLiteral expr = MaxLiteral.MAX_VALUE; - Assertions.assertEquals("MAXVALUE", expr.toSql()); + Assertions.assertEquals("MAXVALUE", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testJsonLiteral() throws AnalysisException { JsonLiteral expr = new JsonLiteral("{\"k\":1}"); - Assertions.assertEquals("'{\"k\":1}'", expr.toSql()); + Assertions.assertEquals("'{\"k\":1}'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testIPv4Literal() throws AnalysisException { IPv4Literal expr = new IPv4Literal("192.168.1.1"); - Assertions.assertEquals("\"192.168.1.1\"", expr.toSql()); + Assertions.assertEquals("\"192.168.1.1\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testIPv6Literal() throws AnalysisException { IPv6Literal expr = new IPv6Literal("::1"); - // IPv6Literal.toSqlImpl() returns '"' + value + '"' - Assertions.assertEquals("\"::1\"", expr.toSql()); + // IPv6Literal visitor returns '"' + value + '"' + Assertions.assertEquals("\"::1\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTimeV2LiteralPositive() { // 01:02:03.000000, scale 6, not negative TimeV2Literal expr = new TimeV2Literal(1, 2, 3, 0, 6, false); - Assertions.assertEquals("\"01:02:03.000000\"", expr.toSql()); + Assertions.assertEquals("\"01:02:03.000000\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTimeV2LiteralNegative() { TimeV2Literal expr = new TimeV2Literal(10, 20, 30, 0, 0, true); - Assertions.assertEquals("\"-10:20:30\"", expr.toSql()); + Assertions.assertEquals("\"-10:20:30\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testVarBinaryLiteral() throws AnalysisException { byte[] bytes = new byte[]{0x68, 0x65, 0x6c, 0x6c, 0x6f}; VarBinaryLiteral expr = new VarBinaryLiteral(bytes); - Assertions.assertEquals("X'68656C6C6F'", expr.toSql()); + Assertions.assertEquals("X'68656C6C6F'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteral() throws AnalysisException { DateLiteral expr = new DateLiteral("2024-01-15", Type.DATEV2); - Assertions.assertEquals("'2024-01-15'", expr.toSql()); + Assertions.assertEquals("'2024-01-15'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -176,13 +195,13 @@ public void testArrayLiteral() { ArrayType arrayType = new ArrayType(Type.INT); ArrayLiteral expr = new ArrayLiteral(arrayType, new IntLiteral(1L), new IntLiteral(2L), new IntLiteral(3L)); - Assertions.assertEquals("[1, 2, 3]", expr.toSql()); + Assertions.assertEquals("[1, 2, 3]", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testArrayLiteralEmpty() { ArrayLiteral expr = new ArrayLiteral(); - Assertions.assertEquals("[]", expr.toSql()); + Assertions.assertEquals("[]", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -191,7 +210,7 @@ public void testMapLiteral() { List keys = Arrays.asList(new StringLiteral("a"), new StringLiteral("b")); List values = Arrays.asList(new IntLiteral(1L), new IntLiteral(2L)); MapLiteral expr = new MapLiteral(mapType, keys, values); - Assertions.assertEquals("MAP{'a':1, 'b':2}", expr.toSql()); + Assertions.assertEquals("MAP{'a':1, 'b':2}", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -200,20 +219,20 @@ public void testStructLiteral() throws AnalysisException { new StructField("f1", Type.INT), new StructField("f2", Type.VARCHAR)); StructLiteral expr = new StructLiteral(structType, new IntLiteral(10L), new StringLiteral("x")); - Assertions.assertEquals("STRUCT(10, 'x')", expr.toSql()); + Assertions.assertEquals("STRUCT(10, 'x')", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testPlaceHolderExprNull() { // null lExpr case → "?" PlaceHolderExpr expr = new PlaceHolderExpr(); - Assertions.assertEquals("?", expr.toSql()); + Assertions.assertEquals("?", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testPlaceHolderExprWithLiteral() throws AnalysisException { PlaceHolderExpr expr = PlaceHolderExpr.create("42", Type.INT); - Assertions.assertEquals("_placeholder_(42)", expr.toSql()); + Assertions.assertEquals("_placeholder_(42)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -224,13 +243,13 @@ public void testPlaceHolderExprWithLiteral() throws AnalysisException { public void testColumnRefExpr() { ColumnRefExpr expr = new ColumnRefExpr(false); expr.setName("my_col"); - Assertions.assertEquals("my_col", expr.toSql()); + Assertions.assertEquals("my_col", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testInformationFunction() { InformationFunction expr = new InformationFunction("DATABASE"); - Assertions.assertEquals("DATABASE()", expr.toSql()); + Assertions.assertEquals("DATABASE()", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -238,7 +257,7 @@ public void testEncryptKeyRefNoDb() { // parts = ["mykey"] → db=null, keyName="mykey" EncryptKeyName keyName = new EncryptKeyName(Collections.singletonList("mykey")); EncryptKeyRef expr = new EncryptKeyRef(keyName); - Assertions.assertEquals("KEY mykey", expr.toSql()); + Assertions.assertEquals("KEY mykey", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -246,21 +265,144 @@ public void testEncryptKeyRefWithDb() { // parts = ["mydb", "mykey"] EncryptKeyName keyName = new EncryptKeyName(Arrays.asList("mydb", "mykey")); EncryptKeyRef expr = new EncryptKeyRef(keyName); - Assertions.assertEquals("KEY mydb.mykey", expr.toSql()); + Assertions.assertEquals("KEY mydb.mykey", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testSlotRefNoTable() { // No table, no desc → falls back to label SlotRef expr = new SlotRef(null, "col1"); - Assertions.assertEquals("`col1`", expr.toSql()); + Assertions.assertEquals("`col1`", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testSlotRefWithTable() { SlotRef expr = new SlotRef(new TableNameInfo("mytbl"), "col1"); // TableNameInfo("mytbl").toSql() = "`mytbl`" - Assertions.assertEquals("`mytbl`.`col1`", expr.toSql()); + Assertions.assertEquals("`mytbl`.`col1`", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefLabelNoConnectContext() { + // label is set, ConnectContext is absent → returns label as-is + SlotRef expr = new SlotRef(null, "amount"); + Assertions.assertEquals("`amount`", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefLabelNereidsNotQuery() { + // isNereids=true, isQuery=false, sessionVariable set, desc set + // → Nereids plan-printing path: label + "[#]" + TupleDescriptor tupleDesc = new TupleDescriptor(new TupleId(0)); + SlotDescriptor slotDesc = new SlotDescriptor(new SlotId(3), tupleDesc); + slotDesc.setLabel("`col`"); + SlotRef expr = new SlotRef(null, "col"); + expr.setDesc(slotDesc); + + installConnectContext(true, false); + Assertions.assertEquals("`col`[#3]", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefLabelNereidsIsQuery() { + // isNereids=true, isQuery=true → query execution path, slot-id suffix suppressed + TupleDescriptor tupleDesc = new TupleDescriptor(new TupleId(0)); + SlotDescriptor slotDesc = new SlotDescriptor(new SlotId(5), tupleDesc); + slotDesc.setLabel("`score`"); + SlotRef expr = new SlotRef(null, "score"); + expr.setDesc(slotDesc); + + installConnectContext(true, true); + Assertions.assertEquals("`score`", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefLabelNotNereids() { + // isNereids=false → non-Nereids path, no slot-id suffix regardless of desc + TupleDescriptor tupleDesc = new TupleDescriptor(new TupleId(0)); + SlotDescriptor slotDesc = new SlotDescriptor(new SlotId(7), tupleDesc); + slotDesc.setLabel("`price`"); + SlotRef expr = new SlotRef(null, "price"); + expr.setDesc(slotDesc); + + installConnectContext(false, false); + Assertions.assertEquals("`price`", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefNoLabelNoDesc() { + // label=null, desc=null → virtual alias-function slot, returns "`col`" + SlotRef expr = new SlotRef(null, "alias_col"); + // forcibly clear the label that the (TableNameInfo, String) ctor sets + java.lang.reflect.Field labelField; + try { + labelField = SlotRef.class.getDeclaredField("label"); + labelField.setAccessible(true); + labelField.set(expr, null); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + Assertions.assertEquals("`alias_col`", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefDescWithSourceExprs() { + // label=null, desc has sourceExprs → " expr visitor result" + TupleDescriptor tupleDesc = new TupleDescriptor(new TupleId(0)); + SlotDescriptor slotDesc = new SlotDescriptor(new SlotId(2), tupleDesc); + slotDesc.setSourceExpr(new IntLiteral(42L)); + + SlotRef expr = new SlotRef(null, "x"); + try { + java.lang.reflect.Field labelField = SlotRef.class.getDeclaredField("label"); + labelField.setAccessible(true); + labelField.set(expr, null); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + expr.setDesc(slotDesc); + // SlotId=2 (!=1) → " 42" + Assertions.assertEquals(" 42", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefDescNoSourceExprs() { + // label=null, desc has no sourceExprs → "" + TupleDescriptor tupleDesc = new TupleDescriptor(new TupleId(0)); + SlotDescriptor slotDesc = new SlotDescriptor(new SlotId(4), tupleDesc); + + SlotRef expr = new SlotRef(null, "x"); + try { + java.lang.reflect.Field labelField = SlotRef.class.getDeclaredField("label"); + labelField.setAccessible(true); + labelField.set(expr, null); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + expr.setDesc(slotDesc); + Assertions.assertEquals("", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefWithTableAndSubColPath() { + // tableNameInfo present, subColPath set → "`tbl`.`col`.field1.field2" + SlotRef expr = new SlotRef(new TableNameInfo("tbl"), "col"); + try { + java.lang.reflect.Field subColField = SlotRef.class.getDeclaredField("subColPath"); + subColField.setAccessible(true); + subColField.set(expr, Arrays.asList("field1", "field2")); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + Assertions.assertEquals("`tbl`.`col`.field1.field2", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); + } + + @Test + public void testSlotRefDisableTableName() { + // toSqlWithoutTbl(): disableTableName=true, label present → returns label only, table stripped + SlotRef expr = new SlotRef(new TableNameInfo("tbl"), "col"); + String sql = expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITHOUT_TABLE); + Assertions.assertEquals("`col`", sql); } // ----------------------------------------------------------------------- @@ -272,7 +414,7 @@ public void testBinaryPredicateEq() { Expr e1 = new SlotRef(null, "a"); Expr e2 = new IntLiteral(1L); BinaryPredicate expr = new BinaryPredicate(BinaryPredicate.Operator.EQ, e1, e2); - Assertions.assertEquals("(`a` = 1)", expr.toSql()); + Assertions.assertEquals("(`a` = 1)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -280,21 +422,21 @@ public void testBinaryPredicateNe() { Expr e1 = new SlotRef(null, "x"); Expr e2 = new IntLiteral(0L); BinaryPredicate expr = new BinaryPredicate(BinaryPredicate.Operator.NE, e1, e2); - Assertions.assertEquals("(`x` != 0)", expr.toSql()); + Assertions.assertEquals("(`x` != 0)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testIsNullPredicate() { Expr e1 = new SlotRef(null, "col"); IsNullPredicate expr = new IsNullPredicate(e1, false); - Assertions.assertEquals("`col` IS NULL", expr.toSql()); + Assertions.assertEquals("`col` IS NULL", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testIsNotNullPredicate() { Expr e1 = new SlotRef(null, "col"); IsNullPredicate expr = new IsNullPredicate(e1, true); - Assertions.assertEquals("`col` IS NOT NULL", expr.toSql()); + Assertions.assertEquals("`col` IS NOT NULL", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -302,7 +444,7 @@ public void testCompoundPredicateAnd() { Expr e1 = new BoolLiteral(true); Expr e2 = new BoolLiteral(false); CompoundPredicate expr = new CompoundPredicate(CompoundPredicate.Operator.AND, e1, e2); - Assertions.assertEquals("(TRUE AND FALSE)", expr.toSql()); + Assertions.assertEquals("(TRUE AND FALSE)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -310,7 +452,7 @@ public void testCompoundPredicateOr() { Expr e1 = new BoolLiteral(true); Expr e2 = new BoolLiteral(false); CompoundPredicate expr = new CompoundPredicate(CompoundPredicate.Operator.OR, e1, e2); - Assertions.assertEquals("(TRUE OR FALSE)", expr.toSql()); + Assertions.assertEquals("(TRUE OR FALSE)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -318,7 +460,7 @@ public void testCompoundPredicateNotDefault() { // NOT with default SQL: "NOT child" Expr e1 = new BoolLiteral(true); CompoundPredicate expr = new CompoundPredicate(CompoundPredicate.Operator.NOT, e1, null); - Assertions.assertEquals("NOT TRUE", expr.toSql()); + Assertions.assertEquals("(NOT TRUE)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -326,7 +468,7 @@ public void testCompoundPredicateNotExternal() { // NOT with external SQL: "(NOT child)" Expr e1 = new BoolLiteral(true); CompoundPredicate expr = new CompoundPredicate(CompoundPredicate.Operator.NOT, e1, null); - String sql = expr.toSql(true, true, null, null); + String sql = expr.accept(ExprToSqlVisitor.INSTANCE, new ToSqlParams(false, true, null, null)); Assertions.assertEquals("(NOT TRUE)", sql); } @@ -335,7 +477,7 @@ public void testInPredicate() { Expr e1 = new SlotRef(null, "col"); List inList = Arrays.asList(new IntLiteral(1L), new IntLiteral(2L)); InPredicate expr = new InPredicate(e1, inList, false); - Assertions.assertEquals("`col` IN (1, 2)", expr.toSql()); + Assertions.assertEquals("`col` IN (1, 2)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -343,7 +485,7 @@ public void testNotInPredicate() { Expr e1 = new SlotRef(null, "col"); List inList = Arrays.asList(new IntLiteral(1L), new IntLiteral(2L)); InPredicate expr = new InPredicate(e1, inList, true); - Assertions.assertEquals("`col` NOT IN (1, 2)", expr.toSql()); + Assertions.assertEquals("`col` NOT IN (1, 2)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -351,7 +493,7 @@ public void testLikePredicate() { Expr e1 = new SlotRef(null, "name"); Expr e2 = new StringLiteral("foo%"); LikePredicate expr = new LikePredicate(LikePredicate.Operator.LIKE, e1, e2); - Assertions.assertEquals("`name` LIKE 'foo%'", expr.toSql()); + Assertions.assertEquals("`name` LIKE 'foo%'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -359,7 +501,7 @@ public void testRegexpPredicate() { Expr e1 = new SlotRef(null, "name"); Expr e2 = new StringLiteral("^foo"); LikePredicate expr = new LikePredicate(LikePredicate.Operator.REGEXP, e1, e2); - Assertions.assertEquals("`name` REGEXP '^foo'", expr.toSql()); + Assertions.assertEquals("`name` REGEXP '^foo'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -369,7 +511,7 @@ public void testMatchPredicate() { MatchPredicate expr = new MatchPredicate( MatchPredicate.Operator.MATCH_ANY, e1, e2, Type.BOOLEAN, NullableMode.ALWAYS_NULLABLE, null, false); - Assertions.assertEquals("`content` MATCH_ANY 'word'", expr.toSql()); + Assertions.assertEquals("`content` MATCH_ANY 'word'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -392,7 +534,7 @@ public void testBetweenPredicate() throws Exception { expr.addChild(low); expr.addChild(high); - Assertions.assertEquals("`age` BETWEEN 18 AND 65", expr.toSql()); + Assertions.assertEquals("`age` BETWEEN 18 AND 65", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -414,7 +556,7 @@ public void testNotBetweenPredicate() throws Exception { expr.addChild(low); expr.addChild(high); - Assertions.assertEquals("`age` NOT BETWEEN 18 AND 65", expr.toSql()); + Assertions.assertEquals("`age` NOT BETWEEN 18 AND 65", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -428,7 +570,7 @@ public void testArithmeticExprAdd() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.ADD, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(1 + 2)", expr.toSql()); + Assertions.assertEquals("(1 + 2)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -438,33 +580,33 @@ public void testArithmeticExprBitNot() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.BITNOT, e1, null, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("~ 5", expr.toSql()); + Assertions.assertEquals("~ 5", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testCastExprDefault() { CastExpr expr = new CastExpr(Type.BIGINT, new IntLiteral(1L), false); - Assertions.assertEquals("CAST(1 AS bigint)", expr.toSql()); + Assertions.assertEquals("CAST(1 AS bigint)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testCastExprExternal() { // External SQL strips the cast and returns just the child CastExpr expr = new CastExpr(Type.BIGINT, new IntLiteral(1L), false); - String sql = expr.toSql(false, true, null, null); + String sql = expr.accept(ExprToExternalSqlVisitor.INSTANCE, new ToSqlParams(false, true, null, null)); Assertions.assertEquals("1", sql); } @Test public void testTryCastExprDefault() { TryCastExpr expr = new TryCastExpr(Type.INT, new IntLiteral(1L), false, false); - Assertions.assertEquals("TRY_CAST(1 AS int)", expr.toSql()); + Assertions.assertEquals("TRY_CAST(1 AS int)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTryCastExprExternal() { TryCastExpr expr = new TryCastExpr(Type.INT, new IntLiteral(1L), false, false); - String sql = expr.toSql(false, true, null, null); + String sql = expr.accept(ExprToExternalSqlVisitor.INSTANCE, new ToSqlParams(false, true, null, null)); Assertions.assertEquals("1", sql); } @@ -479,7 +621,7 @@ public void testCaseExprSimple() { Expr thenExpr = new IntLiteral(1L); CaseWhenClause clause = new CaseWhenClause(whenExpr, thenExpr); CaseExpr expr = new CaseExpr(Collections.singletonList(clause), null, false); - Assertions.assertEquals("CASE WHEN TRUE THEN 1 END", expr.toSql()); + Assertions.assertEquals("CASE WHEN TRUE THEN 1 END", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -490,39 +632,39 @@ public void testCaseExprWithElse() { Expr elseExpr = new IntLiteral(0L); CaseWhenClause clause = new CaseWhenClause(whenExpr, thenExpr); CaseExpr expr = new CaseExpr(Collections.singletonList(clause), elseExpr, false); - Assertions.assertEquals("CASE WHEN TRUE THEN 1 ELSE 0 END", expr.toSql()); + Assertions.assertEquals("CASE WHEN TRUE THEN 1 ELSE 0 END", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testVariableExprUser() { VariableExpr expr = new VariableExpr("myvar", SetType.USER); - Assertions.assertEquals("@myvar", expr.toSql()); + Assertions.assertEquals("@myvar", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testVariableExprSession() { VariableExpr expr = new VariableExpr("version", SetType.SESSION); - Assertions.assertEquals("@@version", expr.toSql()); + Assertions.assertEquals("@@version", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testVariableExprGlobal() { VariableExpr expr = new VariableExpr("timeout", SetType.GLOBAL); - Assertions.assertEquals("@@GLOBAL.timeout", expr.toSql()); + Assertions.assertEquals("@@GLOBAL.timeout", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testFunctionCallExpr() { FunctionCallExpr expr = new FunctionCallExpr("upper", Arrays.asList(new StringLiteral("hello")), false); - Assertions.assertEquals("upper('hello')", expr.toSql()); + Assertions.assertEquals("upper('hello')", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testFunctionCallExprNoArgs() { FunctionCallExpr expr = new FunctionCallExpr("now", Collections.emptyList(), false); - Assertions.assertEquals("now()", expr.toSql()); + Assertions.assertEquals("now()", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -533,7 +675,7 @@ public void testTimestampArithmeticExprFuncStyle() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "date_add", ArithmeticExpr.Operator.ADD, e1, e2, "YEAR", Type.DATETIMEV2, false); - Assertions.assertEquals("date_add(`dt`, INTERVAL 1 YEAR)", expr.toSql()); + Assertions.assertEquals("date_add(`dt`, INTERVAL 1 YEAR)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -544,7 +686,7 @@ public void testTimestampArithmeticExprTimestampdiff() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "TIMESTAMPDIFF", ArithmeticExpr.Operator.ADD, e1, e2, "YEAR", Type.DATETIMEV2, false); - Assertions.assertEquals("TIMESTAMPDIFF(YEAR, `start_dt`, `end_dt`)", expr.toSql()); + Assertions.assertEquals("TIMESTAMPDIFF(YEAR, `start_dt`, `end_dt`)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -557,7 +699,7 @@ ArithmeticExpr.Operator.ADD, slot, new IntLiteral(1L), LambdaFunctionExpr expr = new LambdaFunctionExpr( body, Collections.singletonList("x"), Collections.singletonList(slot), false); - Assertions.assertEquals("x -> (`x` + 1)", expr.toSql()); + Assertions.assertEquals("x -> (`x` + 1)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -571,7 +713,7 @@ public void testLambdaFunctionExprTwoArgs() { LambdaFunctionExpr expr = new LambdaFunctionExpr( body, Arrays.asList("x", "y"), Arrays.asList(slotX, slotY), false); - Assertions.assertEquals("(x,y) -> (`x` + `y`)", expr.toSql()); + Assertions.assertEquals("(x,y) -> (`x` + `y`)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -585,7 +727,7 @@ public void testArithmeticExprSubtract() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.SUBTRACT, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(10 - 3)", expr.toSql()); + Assertions.assertEquals("(10 - 3)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -595,7 +737,7 @@ public void testArithmeticExprMultiply() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.MULTIPLY, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(4 * 5)", expr.toSql()); + Assertions.assertEquals("(4 * 5)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -605,7 +747,7 @@ public void testArithmeticExprDivide() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.DIVIDE, e1, e2, Type.DOUBLE, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(10 / 2)", expr.toSql()); + Assertions.assertEquals("(10 / 2)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -615,7 +757,7 @@ public void testArithmeticExprMod() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.MOD, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(7 % 3)", expr.toSql()); + Assertions.assertEquals("(7 % 3)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -625,7 +767,7 @@ public void testArithmeticExprIntDivide() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.INT_DIVIDE, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(7 DIV 3)", expr.toSql()); + Assertions.assertEquals("(7 DIV 3)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -635,7 +777,7 @@ public void testArithmeticExprBitAnd() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.BITAND, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(12 & 10)", expr.toSql()); + Assertions.assertEquals("(12 & 10)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -645,7 +787,7 @@ public void testArithmeticExprBitOr() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.BITOR, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(12 | 10)", expr.toSql()); + Assertions.assertEquals("(12 | 10)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -655,7 +797,7 @@ public void testArithmeticExprBitXor() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.BITXOR, e1, e2, Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(12 ^ 10)", expr.toSql()); + Assertions.assertEquals("(12 ^ 10)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -667,7 +809,7 @@ ArithmeticExpr.Operator.ADD, new IntLiteral(1L), new IntLiteral(2L), ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.MULTIPLY, add, new IntLiteral(3L), Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("((1 + 2) * 3)", expr.toSql()); + Assertions.assertEquals("((1 + 2) * 3)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -685,7 +827,7 @@ public void testCaseExprMultipleWhenClauses() { new CaseWhenClause(when2, new StringLiteral("mid"))); CaseExpr expr = new CaseExpr(clauses, new StringLiteral("small"), false); Assertions.assertEquals("CASE WHEN (`col` > 10) THEN 'big' WHEN (`col` > 5) THEN 'mid' ELSE 'small' END", - expr.toSql()); + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -695,7 +837,8 @@ public void testCaseExprNoElse() { new CaseWhenClause(new BoolLiteral(true), new IntLiteral(1L)), new CaseWhenClause(new BoolLiteral(false), new IntLiteral(2L))); CaseExpr expr = new CaseExpr(clauses, null, false); - Assertions.assertEquals("CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 END", expr.toSql()); + Assertions.assertEquals("CASE WHEN TRUE THEN 1 WHEN FALSE THEN 2 END", + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -706,7 +849,8 @@ public void testCaseExprNullElse() { CaseExpr expr = new CaseExpr( Collections.singletonList(new CaseWhenClause(when1, new StringLiteral("null_val"))), col, false); - Assertions.assertEquals("CASE WHEN `val` IS NULL THEN 'null_val' ELSE `val` END", expr.toSql()); + Assertions.assertEquals("CASE WHEN `val` IS NULL THEN 'null_val' ELSE `val` END", + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -718,7 +862,8 @@ public void testCaseExprNestedInArithmetic() { ArithmeticExpr expr = new ArithmeticExpr( ArithmeticExpr.Operator.ADD, caseExpr, new IntLiteral(5L), Type.BIGINT, NullableMode.DEPEND_ON_ARGUMENT, false); - Assertions.assertEquals("(CASE WHEN TRUE THEN 1 ELSE 0 END + 5)", expr.toSql()); + Assertions.assertEquals("(CASE WHEN TRUE THEN 1 ELSE 0 END + 5)", + expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -729,7 +874,7 @@ ArithmeticExpr.Operator.ADD, caseExpr, new IntLiteral(5L), public void testFunctionCallExprMultipleArgs() { FunctionCallExpr expr = new FunctionCallExpr("concat", Arrays.asList(new StringLiteral("a"), new StringLiteral("b"), new StringLiteral("c")), false); - Assertions.assertEquals("concat('a', 'b', 'c')", expr.toSql()); + Assertions.assertEquals("concat('a', 'b', 'c')", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -742,7 +887,7 @@ public void testFunctionCallExprDistinct() throws Exception { java.lang.reflect.Field fnParamsField = FunctionCallExpr.class.getDeclaredField("fnParams"); fnParamsField.setAccessible(true); fnParamsField.set(expr, distinctParams); - Assertions.assertEquals("count(DISTINCT `col`)", expr.toSql()); + Assertions.assertEquals("count(DISTINCT `col`)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -753,7 +898,7 @@ public void testFunctionCallExprStar() throws Exception { java.lang.reflect.Field fnParamsField = FunctionCallExpr.class.getDeclaredField("fnParams"); fnParamsField.setAccessible(true); fnParamsField.set(expr, starParams); - Assertions.assertEquals("count(*)", expr.toSql()); + Assertions.assertEquals("count(*)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -763,7 +908,7 @@ public void testFunctionCallExprNestedFunctions() { Collections.singletonList(new StringLiteral("hello")), false); FunctionCallExpr expr = new FunctionCallExpr("length", Collections.singletonList(inner), false); - Assertions.assertEquals("length(upper('hello'))", expr.toSql()); + Assertions.assertEquals("length(upper('hello'))", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -771,7 +916,7 @@ public void testFunctionCallExprWithSlotRef() { // coalesce(col, 0) FunctionCallExpr expr = new FunctionCallExpr("coalesce", Arrays.asList(new SlotRef(null, "col"), new IntLiteral(0L)), false); - Assertions.assertEquals("coalesce(`col`, 0)", expr.toSql()); + Assertions.assertEquals("coalesce(`col`, 0)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -779,7 +924,7 @@ public void testFunctionCallExprIfNull() { // ifnull(a, b) FunctionCallExpr expr = new FunctionCallExpr("ifnull", Arrays.asList(new SlotRef(null, "a"), new StringLiteral("default")), false); - Assertions.assertEquals("ifnull(`a`, 'default')", expr.toSql()); + Assertions.assertEquals("ifnull(`a`, 'default')", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -794,7 +939,7 @@ public void testTimestampArithmeticExprDateSub() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "date_sub", ArithmeticExpr.Operator.SUBTRACT, e1, e2, "DAY", Type.DATETIMEV2, false); - Assertions.assertEquals("date_sub(`dt`, INTERVAL 7 DAY)", expr.toSql()); + Assertions.assertEquals("date_sub(`dt`, INTERVAL 7 DAY)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -805,7 +950,7 @@ public void testTimestampArithmeticExprDaysAdd() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "days_add", ArithmeticExpr.Operator.ADD, e1, e2, "DAY", Type.DATETIMEV2, false); - Assertions.assertEquals("days_add(`created_at`, INTERVAL 30 DAY)", expr.toSql()); + Assertions.assertEquals("days_add(`created_at`, INTERVAL 30 DAY)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -816,7 +961,7 @@ public void testTimestampArithmeticExprMonthsAdd() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "months_add", ArithmeticExpr.Operator.ADD, e1, e2, "MONTH", Type.DATETIMEV2, false); - Assertions.assertEquals("months_add(`dt`, INTERVAL 3 MONTH)", expr.toSql()); + Assertions.assertEquals("months_add(`dt`, INTERVAL 3 MONTH)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -827,7 +972,7 @@ public void testTimestampArithmeticExprHoursAdd() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "hours_add", ArithmeticExpr.Operator.ADD, e1, e2, "HOUR", Type.DATETIMEV2, false); - Assertions.assertEquals("hours_add(`ts`, INTERVAL 2 HOUR)", expr.toSql()); + Assertions.assertEquals("hours_add(`ts`, INTERVAL 2 HOUR)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -838,7 +983,7 @@ public void testTimestampArithmeticExprMinutesAdd() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "minutes_add", ArithmeticExpr.Operator.ADD, e1, e2, "MINUTE", Type.DATETIMEV2, false); - Assertions.assertEquals("minutes_add(`ts`, INTERVAL 15 MINUTE)", expr.toSql()); + Assertions.assertEquals("minutes_add(`ts`, INTERVAL 15 MINUTE)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -849,7 +994,7 @@ public void testTimestampArithmeticExprSecondsAdd() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "seconds_add", ArithmeticExpr.Operator.ADD, e1, e2, "SECOND", Type.DATETIMEV2, false); - Assertions.assertEquals("seconds_add(`ts`, INTERVAL 30 SECOND)", expr.toSql()); + Assertions.assertEquals("seconds_add(`ts`, INTERVAL 30 SECOND)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -861,7 +1006,7 @@ public void testTimestampArithmeticExprTimestampadd() { "TIMESTAMPADD", ArithmeticExpr.Operator.ADD, e1, e2, "MONTH", Type.DATETIMEV2, false); // TIMESTAMPADD(unit, interval, timestamp) — same layout as TIMESTAMPDIFF - Assertions.assertEquals("TIMESTAMPADD(MONTH, 1, `dt`)", expr.toSql()); + Assertions.assertEquals("TIMESTAMPADD(MONTH, 1, `dt`)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -872,7 +1017,7 @@ public void testTimestampArithmeticExprTimestampdiffDay() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "TIMESTAMPDIFF", ArithmeticExpr.Operator.ADD, e1, e2, "DAY", Type.DATETIMEV2, false); - Assertions.assertEquals("TIMESTAMPDIFF(DAY, `start_date`, `end_date`)", expr.toSql()); + Assertions.assertEquals("TIMESTAMPDIFF(DAY, `start_date`, `end_date`)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -883,7 +1028,7 @@ public void testTimestampArithmeticExprWeekAdd() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "weeks_add", ArithmeticExpr.Operator.ADD, e1, e2, "WEEK", Type.DATETIMEV2, false); - Assertions.assertEquals("weeks_add(`dt`, INTERVAL 2 WEEK)", expr.toSql()); + Assertions.assertEquals("weeks_add(`dt`, INTERVAL 2 WEEK)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -899,7 +1044,7 @@ public void testTimestampArithmeticExprWithLiteral() { TimestampArithmeticExpr expr = new TimestampArithmeticExpr( "date_add", ArithmeticExpr.Operator.ADD, e1, e2, "YEAR", Type.DATETIMEV2, false); - Assertions.assertEquals("date_add('2024-01-01', INTERVAL 1 YEAR)", expr.toSql()); + Assertions.assertEquals("date_add('2024-01-01', INTERVAL 1 YEAR)", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -910,7 +1055,7 @@ public void testTimestampArithmeticExprWithLiteral() { public void testTimeV2LiteralScale0() { // scale=0 → no fractional part: "01:02:03" TimeV2Literal expr = new TimeV2Literal(1, 2, 3, 0, 0, false); - Assertions.assertEquals("\"01:02:03\"", expr.toSql()); + Assertions.assertEquals("\"01:02:03\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -918,7 +1063,7 @@ public void testTimeV2LiteralScale1() { // scale=1 → 1 digit: "01:02:03.1" // microsecond=100000 → scaled: 100000 / 10^(6-1) = 100000/100000 = 1 TimeV2Literal expr = new TimeV2Literal(1, 2, 3, 100000, 1, false); - Assertions.assertEquals("\"01:02:03.1\"", expr.toSql()); + Assertions.assertEquals("\"01:02:03.1\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test @@ -926,35 +1071,35 @@ public void testTimeV2LiteralScale3() { // scale=3 → 3 digits: "01:02:03.123" // microsecond=123000 → scaled: 123000 / 10^(6-3) = 123000/1000 = 123 TimeV2Literal expr = new TimeV2Literal(1, 2, 3, 123000, 3, false); - Assertions.assertEquals("\"01:02:03.123\"", expr.toSql()); + Assertions.assertEquals("\"01:02:03.123\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTimeV2LiteralScale6() { // scale=6 → 6 digits: "01:02:03.123456" TimeV2Literal expr = new TimeV2Literal(1, 2, 3, 123456, 6, false); - Assertions.assertEquals("\"01:02:03.123456\"", expr.toSql()); + Assertions.assertEquals("\"01:02:03.123456\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTimeV2LiteralNegativeWithScale() { // negative, scale=3: "-10:20:30.500" TimeV2Literal expr = new TimeV2Literal(10, 20, 30, 500000, 3, true); - Assertions.assertEquals("\"-10:20:30.500\"", expr.toSql()); + Assertions.assertEquals("\"-10:20:30.500\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTimeV2LiteralLargeHour() { // hour > 99, scale=0: "838:59:59" TimeV2Literal expr = new TimeV2Literal(838, 59, 59, 0, 0, false); - Assertions.assertEquals("\"838:59:59\"", expr.toSql()); + Assertions.assertEquals("\"838:59:59\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testTimeV2LiteralZero() { // 00:00:00, scale=0 TimeV2Literal expr = new TimeV2Literal(0, 0, 0, 0, 0, false); - Assertions.assertEquals("\"00:00:00\"", expr.toSql()); + Assertions.assertEquals("\"00:00:00\"", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } // ----------------------------------------------------------------------- @@ -965,55 +1110,55 @@ public void testTimeV2LiteralZero() { public void testDateLiteralDateV2() throws AnalysisException { // DATE type: 'YYYY-MM-DD' DateLiteral expr = new DateLiteral("2024-03-15", Type.DATEV2); - Assertions.assertEquals("'2024-03-15'", expr.toSql()); + Assertions.assertEquals("'2024-03-15'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDatetime() throws AnalysisException { // DATETIME (v1) type: 'YYYY-MM-DD HH:MM:SS' DateLiteral expr = new DateLiteral("2024-03-15 10:30:00", Type.DATETIME); - Assertions.assertEquals("'2024-03-15 10:30:00'", expr.toSql()); + Assertions.assertEquals("'2024-03-15 10:30:00'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDatetimeV2Scale0() throws AnalysisException { // DATETIMEV2 scale=0: 'YYYY-MM-DD HH:MM:SS' DateLiteral expr = new DateLiteral("2024-03-15 10:30:00", ScalarType.createDatetimeV2Type(0)); - Assertions.assertEquals("'2024-03-15 10:30:00'", expr.toSql()); + Assertions.assertEquals("'2024-03-15 10:30:00'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDatetimeV2Scale3() throws AnalysisException { // DATETIMEV2 scale=3: 'YYYY-MM-DD HH:MM:SS.mmm' DateLiteral expr = new DateLiteral("2024-03-15 10:30:00.123", ScalarType.createDatetimeV2Type(3)); - Assertions.assertEquals("'2024-03-15 10:30:00.123'", expr.toSql()); + Assertions.assertEquals("'2024-03-15 10:30:00.123'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDatetimeV2Scale6() throws AnalysisException { // DATETIMEV2 scale=6: 'YYYY-MM-DD HH:MM:SS.mmmmmm' DateLiteral expr = new DateLiteral("2024-03-15 10:30:00.123456", ScalarType.createDatetimeV2Type(6)); - Assertions.assertEquals("'2024-03-15 10:30:00.123456'", expr.toSql()); + Assertions.assertEquals("'2024-03-15 10:30:00.123456'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDateV2FromLongConstructor() { // Long-based constructor: year=2023, month=12, day=31 DateLiteral expr = new DateLiteral(2023L, 12L, 31L, Type.DATEV2); - Assertions.assertEquals("'2023-12-31'", expr.toSql()); + Assertions.assertEquals("'2023-12-31'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDatetimeFromLongConstructor() { // Long-based constructor with time: 2023-06-01 08:00:00 DateLiteral expr = new DateLiteral(2023L, 6L, 1L, 8L, 0L, 0L, Type.DATETIME); - Assertions.assertEquals("'2023-06-01 08:00:00'", expr.toSql()); + Assertions.assertEquals("'2023-06-01 08:00:00'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test public void testDateLiteralDatetimeV2Scale1() throws AnalysisException { // DATETIMEV2 scale=1: 'YYYY-MM-DD HH:MM:SS.m' DateLiteral expr = new DateLiteral("2024-01-01 00:00:00.5", ScalarType.createDatetimeV2Type(1)); - Assertions.assertEquals("'2024-01-01 00:00:00.5'", expr.toSql()); + Assertions.assertEquals("'2024-01-01 00:00:00.5'", expr.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/SearchPredicateTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/SearchPredicateTest.java index 62c45e9a60da24..c3cac6f691b320 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/SearchPredicateTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/SearchPredicateTest.java @@ -93,7 +93,7 @@ public void testToSqlImpl() { SearchPredicate predicate = new SearchPredicate(dsl, plan, children, true); - String sql = predicate.toSqlImpl(false, false, null, null); + String sql = predicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE); Assertions.assertEquals("search('title:hello')", sql); } @@ -163,8 +163,8 @@ public void testClone() { SearchPredicate cloned = (SearchPredicate) original.clone(); Assertions.assertNotNull(cloned); - Assertions.assertEquals(original.toSqlImpl(false, false, null, null), - cloned.toSqlImpl(false, false, null, null)); + Assertions.assertEquals(original.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), + cloned.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); Assertions.assertEquals(original.getChildren().size(), cloned.getChildren().size()); } diff --git a/fe/fe-core/src/test/java/org/apache/doris/analysis/VarBinaryLiteralAnalysisTest.java b/fe/fe-core/src/test/java/org/apache/doris/analysis/VarBinaryLiteralAnalysisTest.java index 2f870d3eb76b05..5c6cd9e322047e 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/analysis/VarBinaryLiteralAnalysisTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/VarBinaryLiteralAnalysisTest.java @@ -37,7 +37,7 @@ private static byte[] bytes(String s) { @Test public void testToSqlFormat() throws Exception { VarBinaryLiteral lit = new VarBinaryLiteral(bytes("hello")); - Assertions.assertEquals("X'68656C6C6F'", lit.toSql()); + Assertions.assertEquals("X'68656C6C6F'", lit.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); } @Test diff --git a/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergPredicateTest.java b/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergPredicateTest.java index ed280184b49d06..0c0d074dd00443 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergPredicateTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/iceberg/IcebergPredicateTest.java @@ -24,12 +24,14 @@ import org.apache.doris.analysis.DateLiteral; import org.apache.doris.analysis.DecimalLiteral; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.FloatLiteral; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.IntLiteral; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.info.TableNameInfo; @@ -184,7 +186,7 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate orPredicate = new CompoundPredicate(Operator.OR, validExprs.get(i), validExprs.get(j)); Expression expression = IcebergUtils.convertToIcebergExpr(orPredicate, schema); - Assert.assertNotNull("pred: " + orPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + orPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // both invalid @@ -193,7 +195,7 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate orPredicate = new CompoundPredicate(Operator.OR, invalidExprs.get(i), invalidExprs.get(j)); Expression expression = IcebergUtils.convertToIcebergExpr(orPredicate, schema); - Assert.assertNull("pred: " + orPredicate.toSql(), expression); + Assert.assertNull("pred: " + orPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // valid or invalid @@ -202,7 +204,7 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate orPredicate = new CompoundPredicate(Operator.OR, validExprs.get(i), invalidExprs.get(j)); Expression expression = IcebergUtils.convertToIcebergExpr(orPredicate, schema); - Assert.assertNull("pred: " + orPredicate.toSql(), expression); + Assert.assertNull("pred: " + orPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } @@ -213,7 +215,7 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate andPredicate = new CompoundPredicate(Operator.AND, validExprs.get(i), validExprs.get(j)); Expression expression = IcebergUtils.convertToIcebergExpr(andPredicate, schema); - Assert.assertNotNull("pred: " + andPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + andPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // both invalid @@ -222,7 +224,7 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate andPredicate = new CompoundPredicate(Operator.AND, invalidExprs.get(i), invalidExprs.get(j)); Expression expression = IcebergUtils.convertToIcebergExpr(andPredicate, schema); - Assert.assertNull("pred: " + andPredicate.toSql(), expression); + Assert.assertNull("pred: " + andPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // valid and invalid @@ -231,7 +233,7 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate andPredicate = new CompoundPredicate(Operator.AND, validExprs.get(i), invalidExprs.get(j)); Expression expression = IcebergUtils.convertToIcebergExpr(andPredicate, schema); - Assert.assertNotNull("pred: " + andPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + andPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); Assert.assertEquals(IcebergUtils.convertToIcebergExpr(validExprs.get(i), schema).toString(), expression.toString()); } @@ -243,14 +245,14 @@ public void testBinaryPredicate() throws AnalysisException { CompoundPredicate notPredicate = new CompoundPredicate(Operator.NOT, validExprs.get(i), null); Expression expression = IcebergUtils.convertToIcebergExpr(notPredicate, schema); - Assert.assertNotNull("pred: " + notPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + notPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } // invalid for (int i = 0; i < invalidExprs.size(); i++) { CompoundPredicate notPredicate = new CompoundPredicate(Operator.NOT, invalidExprs.get(i), null); Expression expression = IcebergUtils.convertToIcebergExpr(notPredicate, schema); - Assert.assertNull("pred: " + notPredicate.toSql(), expression); + Assert.assertNull("pred: " + notPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/datasource/lakesoul/LakeSoulPredicateTest.java b/fe/fe-core/src/test/java/org/apache/doris/datasource/lakesoul/LakeSoulPredicateTest.java index ed36b54546c651..369157b78dc7c8 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/datasource/lakesoul/LakeSoulPredicateTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/datasource/lakesoul/LakeSoulPredicateTest.java @@ -24,12 +24,14 @@ import org.apache.doris.analysis.DateLiteral; import org.apache.doris.analysis.DecimalLiteral; import org.apache.doris.analysis.Expr; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.FloatLiteral; import org.apache.doris.analysis.InPredicate; import org.apache.doris.analysis.IntLiteral; import org.apache.doris.analysis.LiteralExpr; import org.apache.doris.analysis.SlotRef; import org.apache.doris.analysis.StringLiteral; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.catalog.Type; import org.apache.doris.common.AnalysisException; import org.apache.doris.info.TableNameInfo; @@ -208,7 +210,7 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate orPredicate = new CompoundPredicate(Operator.OR, validExprs.get(i), validExprs.get(j)); Expression expression = LakeSoulUtils.convertToSubstraitExpr(orPredicate, schema); - Assert.assertNotNull("pred: " + orPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + orPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // both invalid @@ -217,7 +219,7 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate orPredicate = new CompoundPredicate(Operator.OR, invalidExprs.get(i), invalidExprs.get(j)); Expression expression = LakeSoulUtils.convertToSubstraitExpr(orPredicate, schema); - Assert.assertNull("pred: " + orPredicate.toSql(), expression); + Assert.assertNull("pred: " + orPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // valid or invalid @@ -226,7 +228,7 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate orPredicate = new CompoundPredicate(Operator.OR, validExprs.get(i), invalidExprs.get(j)); Expression expression = LakeSoulUtils.convertToSubstraitExpr(orPredicate, schema); - Assert.assertNull("pred: " + orPredicate.toSql(), expression); + Assert.assertNull("pred: " + orPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } @@ -237,7 +239,7 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate andPredicate = new CompoundPredicate(Operator.AND, validExprs.get(i), validExprs.get(j)); Expression expression = LakeSoulUtils.convertToSubstraitExpr(andPredicate, schema); - Assert.assertNotNull("pred: " + andPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + andPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // both invalid @@ -246,7 +248,7 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate andPredicate = new CompoundPredicate(Operator.AND, invalidExprs.get(i), invalidExprs.get(j)); Expression expression = LakeSoulUtils.convertToSubstraitExpr(andPredicate, schema); - Assert.assertNull("pred: " + andPredicate.toSql(), expression); + Assert.assertNull("pred: " + andPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } // valid and invalid @@ -255,7 +257,7 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate andPredicate = new CompoundPredicate(Operator.AND, validExprs.get(i), invalidExprs.get(j)); Expression expression = LakeSoulUtils.convertToSubstraitExpr(andPredicate, schema); - Assert.assertNotNull("pred: " + andPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + andPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); Assert.assertEquals(SubstraitUtil.substraitExprToProto(LakeSoulUtils.convertToSubstraitExpr(validExprs.get(i), schema), "table"), SubstraitUtil.substraitExprToProto(expression, "table")); } @@ -267,14 +269,14 @@ public void testBinaryPredicate() throws AnalysisException, IOException { CompoundPredicate notPredicate = new CompoundPredicate(Operator.NOT, validExprs.get(i), null); Expression expression = LakeSoulUtils.convertToSubstraitExpr(notPredicate, schema); - Assert.assertNotNull("pred: " + notPredicate.toSql(), expression); + Assert.assertNotNull("pred: " + notPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } // invalid for (int i = 0; i < invalidExprs.size(); i++) { CompoundPredicate notPredicate = new CompoundPredicate(Operator.NOT, invalidExprs.get(i), null); Expression expression = LakeSoulUtils.convertToSubstraitExpr(notPredicate, schema); - Assert.assertNull("pred: " + notPredicate.toSql(), expression); + Assert.assertNull("pred: " + notPredicate.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE), expression); } } } diff --git a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/VarBinaryLiteralTest.java b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/VarBinaryLiteralTest.java index 504c8f11d9ddfc..8ef5ee24353607 100644 --- a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/VarBinaryLiteralTest.java +++ b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/VarBinaryLiteralTest.java @@ -17,7 +17,9 @@ package org.apache.doris.nereids.trees.expressions; +import org.apache.doris.analysis.ExprToSqlVisitor; import org.apache.doris.analysis.NullLiteral; +import org.apache.doris.analysis.ToSqlParams; import org.apache.doris.analysis.VarBinaryLiteral; import org.apache.doris.common.FormatOptions; import org.apache.doris.thrift.TExprNode; @@ -40,11 +42,11 @@ private static byte[] bytes(String s) { public void testToSqlAndGetStringValue() throws Exception { VarBinaryLiteral lit = new VarBinaryLiteral(bytes("hello")); // toSql should output hex literal format X'HEX' - Assertions.assertEquals("X'68656C6C6F'", lit.toSql()); + Assertions.assertEquals("X'68656C6C6F'", lit.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE)); // getStringValue returns ISO_8859_1 decoded string (ascii here) Assertions.assertEquals("hello", lit.getStringValue()); // also verify hex (via toSql without prefix/suffix extraction) - Assertions.assertTrue(lit.toSql().contains("68656C6C6F")); + Assertions.assertTrue(lit.accept(ExprToSqlVisitor.INSTANCE, ToSqlParams.WITH_TABLE).contains("68656C6C6F")); // nested string wrapper behavior (still wraps the plain string value) FormatOptions opts = FormatOptions.getDefault();