This is an automated email from the ASF dual-hosted git repository.
morrysnow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new f314d968a3f [refactor](Expr) Extract getString* methods to
ExprToStringValueVisitor (#61304)
f314d968a3f is described below
commit f314d968a3f06bdd49897794e622103cd019ba4e
Author: morrySnow <[email protected]>
AuthorDate: Tue Mar 17 19:36:46 2026 +0800
[refactor](Expr) Extract getString* methods to ExprToStringValueVisitor
(#61304)
Move getStringValueForQuery, getStringValueInComplexTypeForQuery, and
getStringValueForStreamLoad logic from 17 Expr subclasses into a
centralized ExprToStringValueVisitor, following the same visitor pattern
as ExprToSqlVisitor and ExprToThriftVisitor.
New classes:
- ExprToStringValueVisitor: visitor with visit methods for DateLiteral,
FloatLiteral, BoolLiteral, NullLiteral, DecimalLiteral, ArrayLiteral,
MapLiteral, StructLiteral, CastExpr, StringLiteral, IPv4Literal,
IPv6Literal, VarBinaryLiteral, PlaceHolderExpr, JsonLiteral, MaxLiteral
- StringValueContext: carries FormatOptions and mode flags
(forStreamLoad, inComplexType)
Expr base class methods now delegate to the visitor. Subclass overrides
are removed. Also fixes pre-existing local variable naming in
DateLiteral static block (DATE_KEY_FORMATTER -> dateKeyFmt) and makes
convertToString private (no external callers).
Co-authored-by: Copilot <[email protected]>
---
.../org/apache/doris/analysis/ArrayLiteral.java | 12 -
.../org/apache/doris/analysis/BoolLiteral.java | 10 -
.../java/org/apache/doris/analysis/CastExpr.java | 10 -
.../org/apache/doris/analysis/DateLiteral.java | 58 +--
.../org/apache/doris/analysis/DecimalLiteral.java | 6 -
.../main/java/org/apache/doris/analysis/Expr.java | 30 --
.../doris/analysis/ExprToStringValueVisitor.java | 254 ++++++++++
.../org/apache/doris/analysis/FloatLiteral.java | 33 --
.../org/apache/doris/analysis/IPv4Literal.java | 5 -
.../org/apache/doris/analysis/IPv6Literal.java | 5 -
.../org/apache/doris/analysis/JsonLiteral.java | 6 -
.../org/apache/doris/analysis/LiteralExpr.java | 5 -
.../java/org/apache/doris/analysis/MapLiteral.java | 18 -
.../java/org/apache/doris/analysis/MaxLiteral.java | 6 -
.../org/apache/doris/analysis/NullLiteral.java | 19 -
.../org/apache/doris/analysis/PlaceHolderExpr.java | 5 -
.../org/apache/doris/analysis/StringLiteral.java | 6 -
.../apache/doris/analysis/StringValueContext.java | 70 +++
.../org/apache/doris/analysis/StructLiteral.java | 29 --
.../apache/doris/analysis/VarBinaryLiteral.java | 5 -
.../trees/plans/commands/insert/InsertUtils.java | 5 +-
.../plans/physical/PhysicalOneRowRelation.java | 9 +-
.../java/org/apache/doris/qe/StmtExecutor.java | 5 +-
.../org/apache/doris/analysis/DateLiteralTest.java | 5 +-
.../analysis/ExprToStringValueVisitorTest.java | 536 +++++++++++++++++++++
.../apache/doris/analysis/FloatLiteralTest.java | 141 +++---
.../analysis/VarBinaryLiteralAnalysisTest.java | 4 +-
.../trees/expressions/VarBinaryLiteralTest.java | 10 +-
28 files changed, 975 insertions(+), 332 deletions(-)
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 00a6d83d6be..e625e897414 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
@@ -20,7 +20,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.ArrayType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import org.apache.commons.lang3.StringUtils;
@@ -75,17 +74,6 @@ public class ArrayLiteral extends LiteralExpr {
return "[" + StringUtils.join(list, ", ") + "]";
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- List<String> list = new ArrayList<>(children.size());
- ++options.level;
- children.forEach(v -> {
- list.add(v.getStringValueInComplexTypeForQuery(options));
- });
- --options.level;
- return "[" + StringUtils.join(list, options.getCollectionDelim()) +
"]";
- }
-
@Override
public int hashCode() {
return Objects.hashCode(children);
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 501b3289f95..15fb1e0a1f0 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
@@ -23,7 +23,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.gson.annotations.SerializedName;
@@ -108,15 +107,6 @@ public class BoolLiteral extends LiteralExpr {
return value ? "1" : "0";
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- if (options.level > 0) {
- return options.isBoolValueNum() ? getStringValue() : (value ?
"true" : "false");
- } else {
- return getStringValue();
- }
- }
-
@Override
public ByteBuffer getHashValue(PrimitiveType type) {
byte v = (byte) (value ? 1 : 0);
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 c12cec7811a..1aad243b1f2 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
@@ -21,7 +21,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.gson.annotations.SerializedName;
@@ -108,13 +107,4 @@ public class CastExpr extends Expr {
return false;
}
- @Override
- public String getStringValueForStreamLoad(FormatOptions options) {
- return children.get(0).getStringValueForStreamLoad(options);
- }
-
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return children.get(0).getStringValueInComplexTypeForQuery(options);
- }
}
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 6d1f0224d6e..bc012f8a0ec 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
@@ -25,7 +25,6 @@ import org.apache.doris.catalog.ScalarType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.InvalidFormatException;
-import org.apache.doris.foundation.format.FormatOptions;
import org.apache.doris.nereids.util.DateUtils;
import com.google.common.base.Preconditions;
@@ -90,29 +89,27 @@ public class DateLiteral extends LiteralExpr {
private static final int MAX_MICROSECOND = 999999;
private static List<DateTimeFormatter> formatterList = null;
- /*
- * The datekey type is widely used in data warehouses
- * For example, 20121229 means '2012-12-29'
- * and data in the form of 'yyyymmdd' is generally called the datekey
type.
- */
- private static DateTimeFormatter DATEKEY_FORMATTER = null;
- // 'yyyymmddHHMMss'
- private static DateTimeFormatter DATETIMEKEY_FORMATTER = null;
-
- private static Map<String, Integer> MONTH_NAME_DICT = Maps.newHashMap();
- private static Map<String, Integer> MONTH_ABBR_NAME_DICT =
Maps.newHashMap();
- private static Map<String, Integer> WEEK_DAY_NAME_DICT = Maps.newHashMap();
+
+ private static final Map<String, Integer> MONTH_NAME_DICT =
Maps.newHashMap();
+ private static final Map<String, Integer> MONTH_ABBR_NAME_DICT =
Maps.newHashMap();
+ private static final Map<String, Integer> WEEK_DAY_NAME_DICT =
Maps.newHashMap();
private static Set<Character> TIME_PART_SET = Sets.newHashSet();
- private static String MICRO_SECOND_FORMATTER = "%f";
+ private static final String MICRO_SECOND_FORMATTER = "%f";
private static final int[] DAYS_IN_MONTH = new int[]{0, 31, 28, 31, 30,
31, 30, 31, 31, 30, 31, 30, 31};
private static final WeekFields weekFields =
WeekFields.of(DayOfWeek.SUNDAY, 7);
static {
try {
- DATEKEY_FORMATTER = formatBuilder("%Y%m%d").toFormatter()
- .withResolverStyle(ResolverStyle.STRICT);
- DATETIMEKEY_FORMATTER = formatBuilder("%Y%m%d%H%i%s").toFormatter()
- .withResolverStyle(ResolverStyle.STRICT);
+ /*
+ * The datekey type is widely used in data warehouses
+ * For example, 20121229 means '2012-12-29'
+ * and data in the form of 'yyyymmdd' is generally called the
datekey type.
+ */
+ DateTimeFormatter dateKeyFmt =
formatBuilder("%Y%m%d").toFormatter()
+ .withResolverStyle(ResolverStyle.STRICT);
+ // 'yyyymmddHHMMss'
+ DateTimeFormatter datetimeKeyFmt =
formatBuilder("%Y%m%d%H%i%s").toFormatter()
+ .withResolverStyle(ResolverStyle.STRICT);
formatterList = Lists.newArrayList(
formatBuilder("%Y%m%d").appendLiteral('T').appendPattern("HHmmss")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, true)
@@ -126,7 +123,7 @@ public class DateLiteral extends LiteralExpr {
formatBuilder("%Y%m%d%H%i%s")
.appendFraction(ChronoField.MICRO_OF_SECOND, 0, 6, false)
.toFormatter().withResolverStyle(ResolverStyle.STRICT),
- DATETIMEKEY_FORMATTER, DATEKEY_FORMATTER);
+ datetimeKeyFmt, dateKeyFmt);
TIME_PART_SET = "HhIiklrSsTp".chars().mapToObj(c -> (char)
c).collect(Collectors.toSet());
} catch (AnalysisException e) {
LOG.error("invalid date format", e);
@@ -633,22 +630,6 @@ public class DateLiteral extends LiteralExpr {
return this.type.isDate() || this.type.isDateV2();
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- if (!type.isTimeStampTz()) {
- return getStringValue();
- }
- try {
- String offset =
DateUtils.getTimeZone().getRules().getOffset(java.time.Instant.now()).toString();
- DateLiteral dateLiteral = new DateLiteral(getStringValue(),
- ScalarType.createDatetimeV2Type(((ScalarType)
type).getScalarScale()));
- return dateLiteral.getStringValue() + offset;
- } catch (Exception e) {
- LOG.warn("generate timestamptz({})'s string value for query
failed. ", getStringValue(), e);
- return getStringValue();
- }
- }
-
@Override
public String getStringValue() {
char[] dateTimeChars = new char[26]; // Enough to hold "YYYY-MM-DD
HH:MM:SS.mmmmmm"
@@ -728,17 +709,12 @@ public class DateLiteral extends LiteralExpr {
return new String(dateTimeChars, 0, 19);
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return options.getNestedStringWrapper() +
getStringValueForQuery(options) + options.getNestedStringWrapper();
- }
-
public void roundFloor(int newScale) {
microsecond = Double.valueOf(microsecond / (int) (Math.pow(10, 6 -
newScale))
* (Math.pow(10, 6 - newScale))).longValue();
}
- public String convertToString(PrimitiveType type) {
+ private String convertToString(PrimitiveType type) {
if (type == PrimitiveType.DATE || type == PrimitiveType.DATEV2) {
return String.format("%04d-%02d-%02d", year, month, day);
} else if (type == PrimitiveType.DATETIMEV2 || type ==
PrimitiveType.TIMESTAMPTZ) {
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 e86cf01577d..b723d0be8b3 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
@@ -22,7 +22,6 @@ import org.apache.doris.catalog.ScalarType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.Config;
-import org.apache.doris.foundation.format.FormatOptions;
import org.apache.doris.qe.SessionVariable;
import com.google.common.base.Preconditions;
@@ -239,11 +238,6 @@ public class DecimalLiteral extends NumericLiteralExpr {
}
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- return value.toPlainString();
- }
-
@Override
public <R, C> R accept(ExprVisitor<R, C> visitor, C context) {
return visitor.visitDecimalLiteral(this, context);
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 6015724a60f..46cff0a9657 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
@@ -26,7 +26,6 @@ import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
import org.apache.doris.common.NameFormatUtils;
import org.apache.doris.common.TreeNode;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
@@ -392,35 +391,6 @@ public abstract class Expr extends TreeNode<Expr>
implements Cloneable {
return "";
}
- /**
- * This method is used for constant fold of query in FE,
- * for different serde dialect(hive, presto, doris).
- */
- public String getStringValueForQuery(FormatOptions options) {
- return getStringValue();
- }
-
- /**
- * This method is to return the string value of this expr in a complex
type for query
- * It is only used for "getStringValueForQuery()"
- * For most of the integer types, it is same as getStringValueForQuery().
- * But for others like StringLiteral and DateLiteral, it should be wrapped
with quotations.
- * eg: 1,2,abc,[1,2,3],["abc","def"],{10:20},{"abc":20}
- */
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return getStringValueForQuery(options);
- }
-
- /**
- * This method is to return the string value of this expr for stream load.
- * so there is a little different from "getStringValueForQuery()".
- * eg, for NullLiteral, it should be "\N" for stream load, but "null" for
FE constant
- * for StructLiteral, the value should not contain sub column's name.
- */
- public String getStringValueForStreamLoad(FormatOptions options) {
- return getStringValueForQuery(options);
- }
-
/**
* For excute expr the result is nullable
*/
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java
new file mode 100644
index 00000000000..13ca35f5510
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ExprToStringValueVisitor.java
@@ -0,0 +1,254 @@
+// 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.ScalarType;
+import org.apache.doris.catalog.StructType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.FractionalFormat;
+import org.apache.doris.foundation.format.FormatOptions;
+import org.apache.doris.nereids.util.DateUtils;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.time.ZoneId;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Visitor that generates string values for Expr instances, handling different
+ * output modes (query, stream load) and complex type nesting.
+ *
+ * <p>This visitor extracts the logic previously in {@code
getStringValueForQuery},
+ * {@code getStringValueInComplexTypeForQuery}, and {@code
getStringValueForStreamLoad}
+ * from Expr subclasses, following the same visitor pattern as {@link
ExprToSqlVisitor}.
+ */
+public class ExprToStringValueVisitor extends ExprVisitor<String,
StringValueContext> {
+ private static final Logger LOG =
LogManager.getLogger(ExprToStringValueVisitor.class);
+
+ public static final ExprToStringValueVisitor INSTANCE = new
ExprToStringValueVisitor();
+
+ @Override
+ public String visit(Expr expr, StringValueContext ctx) {
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitDateLiteral(DateLiteral expr, StringValueContext ctx) {
+ String value;
+ if (expr.getType().isTimeStampTz()) {
+ try {
+ ZoneId dorisZone = DateUtils.getTimeZone();
+ String offset =
dorisZone.getRules().getOffset(java.time.Instant.now()).toString();
+ DateLiteral dateLiteral = new
DateLiteral(expr.getStringValue(),
+ ScalarType.createDatetimeV2Type(((ScalarType)
expr.getType()).getScalarScale()));
+ value = dateLiteral.getStringValue() + offset;
+ } catch (Exception e) {
+ LOG.warn("generate timestamptz({})'s string value for query
failed. ",
+ expr.getStringValue(), e);
+ value = expr.getStringValue();
+ }
+ } else {
+ value = expr.getStringValue();
+ }
+ if (ctx.isInComplexType()) {
+ return wrapWithQuotes(value, ctx);
+ }
+ return value;
+ }
+
+ @Override
+ public String visitFloatLiteral(FloatLiteral expr, StringValueContext ctx)
{
+ String value;
+ if (expr.getType() == Type.TIMEV2) {
+ String timeStr = expr.getStringValue();
+ value = timeStr.substring(1, timeStr.length() - 1);
+ } else {
+ double dValue = expr.getValue();
+ if (expr.getType() == Type.FLOAT) {
+ Float fValue = (float) dValue;
+ if (fValue.equals(Float.POSITIVE_INFINITY)) {
+ dValue = Double.POSITIVE_INFINITY;
+ }
+ if (fValue.equals(Float.NEGATIVE_INFINITY)) {
+ dValue = Double.NEGATIVE_INFINITY;
+ }
+ }
+ value = FractionalFormat.getFormatStringValue(dValue,
+ expr.getType() == Type.DOUBLE ? 16 : 7,
+ expr.getType() == Type.DOUBLE ? "%.15E" : "%.6E");
+ }
+ if (ctx.isInComplexType() && expr.getType() == Type.TIMEV2) {
+ return wrapWithQuotes(value, ctx);
+ }
+ return value;
+ }
+
+ @Override
+ public String visitBoolLiteral(BoolLiteral expr, StringValueContext ctx) {
+ FormatOptions options = ctx.getFormatOptions();
+ if (options.level > 0) {
+ return options.isBoolValueNum() ? expr.getStringValue() :
(expr.getValue() ? "true" : "false");
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitNullLiteral(NullLiteral expr, StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return ctx.getFormatOptions().getNullFormat();
+ }
+ if (ctx.isForStreamLoad()) {
+ return FeConstants.null_string;
+ }
+ return null;
+ }
+
+ @Override
+ public String visitDecimalLiteral(DecimalLiteral expr, StringValueContext
ctx) {
+ return expr.getValue().toPlainString();
+ }
+
+ @Override
+ public String visitArrayLiteral(ArrayLiteral expr, StringValueContext ctx)
{
+ FormatOptions options = ctx.getFormatOptions();
+ List<String> list = new ArrayList<>(expr.getChildren().size());
+ ++options.level;
+ for (Expr child : expr.getChildren()) {
+ list.add(child.accept(this, ctx.asComplexType()));
+ }
+ --options.level;
+ return "[" + StringUtils.join(list, options.getCollectionDelim()) +
"]";
+ }
+
+ @Override
+ public String visitMapLiteral(MapLiteral expr, StringValueContext ctx) {
+ FormatOptions options = ctx.getFormatOptions();
+ List<Expr> children = expr.getChildren();
+ List<String> list = new ArrayList<>(children.size());
+ ++options.level;
+ StringValueContext childCtx = ctx.asComplexType();
+ for (int i = 0; i < children.size() && i + 1 < children.size(); i +=
2) {
+ if (children.get(i).getType().isComplexType()) {
+ throw new UnsupportedOperationException(
+ "Unsupported key type for MAP: " +
children.get(i).getType());
+ }
+ list.add(children.get(i).accept(this, childCtx)
+ + options.getMapKeyDelim()
+ + children.get(i + 1).accept(this, childCtx));
+ }
+ --options.level;
+ return "{" + StringUtils.join(list, options.getCollectionDelim()) +
"}";
+ }
+
+ @Override
+ public String visitStructLiteral(StructLiteral expr, StringValueContext
ctx) {
+ FormatOptions options = ctx.getFormatOptions();
+ List<Expr> children = expr.getChildren();
+ List<String> list = new ArrayList<>(children.size());
+ if (ctx.isForStreamLoad()) {
+ for (int i = 0; i < children.size(); i++) {
+ list.add(children.get(i).accept(this,
ctx.asQueryComplexType()));
+ }
+ } else {
+ ++options.level;
+ StringValueContext childCtx = ctx.asComplexType();
+ for (int i = 0; i < children.size(); i++) {
+ list.add(options.getNestedStringWrapper()
+ + ((StructType)
expr.getType()).getFields().get(i).getName()
+ + options.getNestedStringWrapper()
+ + options.getMapKeyDelim()
+ + children.get(i).accept(this, childCtx));
+ }
+ --options.level;
+ }
+ return "{" + StringUtils.join(list, options.getCollectionDelim()) +
"}";
+ }
+
+ @Override
+ public String visitCastExpr(CastExpr expr, StringValueContext ctx) {
+ if (ctx.isInComplexType() || ctx.isForStreamLoad()) {
+ return expr.getChildren().get(0).accept(this, ctx);
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitStringLiteral(StringLiteral expr, StringValueContext
ctx) {
+ if (ctx.isInComplexType()) {
+ return wrapWithQuotes(expr.getStringValue(), ctx);
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitIPv4Literal(IPv4Literal expr, StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return wrapWithQuotes(expr.getStringValue(), ctx);
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitIPv6Literal(IPv6Literal expr, StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return wrapWithQuotes(expr.getStringValue(), ctx);
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitVarBinaryLiteral(VarBinaryLiteral expr,
StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return wrapWithQuotes(expr.getStringValue(), ctx);
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitPlaceHolderExpr(PlaceHolderExpr expr,
StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return wrapWithQuotes(expr.getStringValue(), ctx);
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitJsonLiteral(JsonLiteral expr, StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return null;
+ }
+ return expr.getStringValue();
+ }
+
+ @Override
+ public String visitMaxLiteral(MaxLiteral expr, StringValueContext ctx) {
+ if (ctx.isInComplexType()) {
+ return null;
+ }
+ return expr.getStringValue();
+ }
+
+ private String wrapWithQuotes(String value, StringValueContext ctx) {
+ String wrapper = ctx.getFormatOptions().getNestedStringWrapper();
+ return wrapper + value + wrapper;
+ }
+}
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 437bfc463a3..f511a8ddb10 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
@@ -20,8 +20,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.FractionalFormat;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.gson.annotations.SerializedName;
@@ -148,37 +146,6 @@ public class FloatLiteral extends NumericLiteralExpr {
return nf.format(value);
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- if (type == Type.TIMEV2) {
- // FloatLiteral used to represent TIME type, here we need to
remove apostrophe from timeStr
- // for example '11:22:33' -> 11:22:33
- String timeStr = getStringValue();
- return timeStr.substring(1, timeStr.length() - 1);
- } else {
- if (type == Type.FLOAT) {
- Float fValue = (float) value;
- if (fValue.equals(Float.POSITIVE_INFINITY)) {
- value = Double.POSITIVE_INFINITY;
- }
- if (fValue.equals(Float.NEGATIVE_INFINITY)) {
- value = Double.NEGATIVE_INFINITY;
- }
- }
- return FractionalFormat.getFormatStringValue(value, type ==
Type.DOUBLE ? 16 : 7,
- type == Type.DOUBLE ? "%.15E" : "%.6E");
- }
- }
-
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- String ret = this.getStringValueForQuery(options);
- if (type == Type.TIMEV2) {
- ret = options.getNestedStringWrapper() + ret +
options.getNestedStringWrapper();
- }
- return ret;
- }
-
@Override
public long getLongValue() {
return (long) value;
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 9240ce66085..3348c982733 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
@@ -19,7 +19,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.gson.annotations.SerializedName;
@@ -121,8 +120,4 @@ public class IPv4Literal extends LiteralExpr {
return value;
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return options.getNestedStringWrapper() +
getStringValueForQuery(options) + options.getNestedStringWrapper();
- }
}
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 d1149608da6..7a46f74368a 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
@@ -19,7 +19,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.gson.annotations.SerializedName;
@@ -103,8 +102,4 @@ public class IPv6Literal extends LiteralExpr {
return value;
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return options.getNestedStringWrapper() +
getStringValueForQuery(options) + options.getNestedStringWrapper();
- }
}
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 199c8502657..01b64495b23 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
@@ -19,7 +19,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
@@ -89,11 +88,6 @@ public class JsonLiteral extends LiteralExpr {
return value;
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return null;
- }
-
public String getUnescapedValue() {
// Unescape string exactly like Hive does. Hive's method assumes
// quotes so we add them here to reuse Hive's code.
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
index ba3a13b35b8..bb140cdcdfd 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/LiteralExpr.java
@@ -23,7 +23,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.common.base.Preconditions;
@@ -150,10 +149,6 @@ public abstract class LiteralExpr extends Expr implements
Comparable<LiteralExpr
@Override
public abstract String getStringValue();
- public String getStringValueForQuery(FormatOptions options) {
- return getStringValue();
- }
-
public long getLongValue() {
return 0;
}
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 59d751c6738..2ffa94a8df0 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
@@ -20,7 +20,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.MapType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
@@ -79,23 +78,6 @@ public class MapLiteral extends LiteralExpr {
return expr.getStringValue();
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- List<String> list = new ArrayList<>(children.size());
- ++options.level;
- for (int i = 0; i < children.size() && i + 1 < children.size(); i +=
2) {
- // we should use type to decide we output array is suitable for
json format
- if (children.get(i).getType().isComplexType()) {
- // map key type do not support complex type
- throw new UnsupportedOperationException("Unsupported key type
for MAP: " + children.get(i).getType());
- }
-
list.add(children.get(i).getStringValueInComplexTypeForQuery(options)
- + options.getMapKeyDelim() + children.get(i +
1).getStringValueInComplexTypeForQuery(options));
- }
- --options.level;
- return "{" + StringUtils.join(list, options.getCollectionDelim()) +
"}";
- }
-
@Override
public <R, C> R accept(ExprVisitor<R, C> visitor, C context) {
return visitor.visitMapLiteral(this, context);
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 3ea986dfa69..989003ddc09 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.foundation.format.FormatOptions;
-
public final class MaxLiteral extends LiteralExpr {
public static final MaxLiteral MAX_VALUE = new MaxLiteral();
@@ -60,8 +58,4 @@ public final class MaxLiteral extends LiteralExpr {
return null;
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return null;
- }
}
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 d5698141700..1a2737ba298 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
@@ -23,8 +23,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.common.FeConstants;
-import org.apache.doris.foundation.format.FormatOptions;
import java.nio.ByteBuffer;
@@ -94,23 +92,6 @@ public class NullLiteral extends LiteralExpr {
return "NULL";
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- return null;
- }
-
- @Override
- public String getStringValueForStreamLoad(FormatOptions options) {
- return FeConstants.null_string;
- }
-
- // the null value inside an array is represented as "null", for exampe:
- // [null, null]. Not same as other primitive type to represent as \N.
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return options.getNullFormat();
- }
-
@Override
public long getLongValue() {
return 0;
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 53bc9af9239..fa276cd66b2 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
@@ -21,7 +21,6 @@ import org.apache.doris.catalog.MysqlColType;
import org.apache.doris.catalog.PrimitiveType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.common.base.Preconditions;
@@ -119,9 +118,5 @@ public class PlaceHolderExpr extends LiteralExpr {
return visitor.visitPlaceHolderExpr(this, context);
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return options.getNestedStringWrapper() +
getStringValueForQuery(options) + options.getNestedStringWrapper();
- }
}
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 c7fa50b6cf8..371d39aa6b6 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
@@ -21,7 +21,6 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.common.base.Preconditions;
import com.google.gson.annotations.SerializedName;
@@ -121,11 +120,6 @@ public class StringLiteral extends LiteralExpr {
return value;
}
- @Override
- protected String getStringValueInComplexTypeForQuery(FormatOptions
options) {
- return options.getNestedStringWrapper() +
getStringValueForQuery(options) + options.getNestedStringWrapper();
- }
-
@Override
public long getLongValue() {
return Long.valueOf(value);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/analysis/StringValueContext.java
b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringValueContext.java
new file mode 100644
index 00000000000..5c0830bb938
--- /dev/null
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/StringValueContext.java
@@ -0,0 +1,70 @@
+// 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.foundation.format.FormatOptions;
+
+/**
+ * Context for {@link ExprToStringValueVisitor}, carrying format options and
mode information.
+ */
+public class StringValueContext {
+ private final FormatOptions formatOptions;
+ private final boolean forStreamLoad;
+ private final boolean inComplexType;
+
+ private StringValueContext(FormatOptions formatOptions, boolean
forStreamLoad, boolean inComplexType) {
+ this.formatOptions = formatOptions;
+ this.forStreamLoad = forStreamLoad;
+ this.inComplexType = inComplexType;
+ }
+
+ public static StringValueContext forQuery(FormatOptions options) {
+ return new StringValueContext(options, false, false);
+ }
+
+ public static StringValueContext forStreamLoad(FormatOptions options) {
+ return new StringValueContext(options, true, false);
+ }
+
+ public StringValueContext asComplexType() {
+ if (inComplexType) {
+ return this;
+ }
+ return new StringValueContext(formatOptions, forStreamLoad, true);
+ }
+
+ /**
+ * Returns a context in query + complex-type mode, regardless of the
current mode.
+ * Used by StructLiteral's stream-load path where children are rendered in
query-complex mode.
+ */
+ public StringValueContext asQueryComplexType() {
+ return new StringValueContext(formatOptions, false, true);
+ }
+
+ public FormatOptions getFormatOptions() {
+ return formatOptions;
+ }
+
+ public boolean isForStreamLoad() {
+ return forStreamLoad;
+ }
+
+ public boolean isInComplexType() {
+ return inComplexType;
+ }
+}
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 bdf09dfb6df..8476f446417 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
@@ -20,7 +20,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.StructType;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import org.apache.commons.lang3.StringUtils;
@@ -77,34 +76,6 @@ public class StructLiteral extends LiteralExpr {
return "{" + StringUtils.join(list, ", ") + "}";
}
- @Override
- public String getStringValueForQuery(FormatOptions options) {
- List<String> list = new ArrayList<>(children.size());
- ++options.level;
- // same with be default field index start with 1
- for (int i = 0; i < children.size(); i++) {
- Expr child = children.get(i);
- list.add(options.getNestedStringWrapper()
- + ((StructType) type).getFields().get(i).getName()
- + options.getNestedStringWrapper()
- + options.getMapKeyDelim()
- + child.getStringValueInComplexTypeForQuery(options));
- }
- --options.level;
- return "{" + StringUtils.join(list, options.getCollectionDelim()) +
"}";
- }
-
- @Override
- public String getStringValueForStreamLoad(FormatOptions options) {
- List<String> list = new ArrayList<>(children.size());
- // same with be default field index start with 1
- for (int i = 0; i < children.size(); i++) {
- Expr child = children.get(i);
- list.add(child.getStringValueInComplexTypeForQuery(options));
- }
- return "{" + StringUtils.join(list, options.getCollectionDelim()) +
"}";
- }
-
@Override
public Expr clone() {
return new StructLiteral(this);
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 dd0e890150c..b081e7be17f 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
@@ -19,7 +19,6 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
import org.apache.doris.common.AnalysisException;
-import org.apache.doris.foundation.format.FormatOptions;
import com.google.common.io.BaseEncoding;
import com.google.gson.annotations.SerializedName;
@@ -121,8 +120,4 @@ public class VarBinaryLiteral extends LiteralExpr {
return new String(value, StandardCharsets.ISO_8859_1);
}
- @Override
- public String getStringValueInComplexTypeForQuery(FormatOptions options) {
- return options.getNestedStringWrapper() +
getStringValueForQuery(options) + options.getNestedStringWrapper();
- }
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java
index 663c8e57d8b..12d0ddd859a 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/insert/InsertUtils.java
@@ -17,6 +17,8 @@
package org.apache.doris.nereids.trees.plans.commands.insert;
+import org.apache.doris.analysis.ExprToStringValueVisitor;
+import org.apache.doris.analysis.StringValueContext;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Database;
import org.apache.doris.catalog.Env;
@@ -182,7 +184,8 @@ public class InsertUtils {
throw new AnalysisException(
"do not support non-literal expr in transactional
insert operation: " + expr.toSql());
}
- row.addColBuilder().setValue(((Literal)
expr).toLegacyLiteral().getStringValueForStreamLoad(options));
+ row.addColBuilder().setValue(((Literal)
expr).toLegacyLiteral().accept(
+ ExprToStringValueVisitor.INSTANCE,
StringValueContext.forStreamLoad(options)));
}
return row.build();
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOneRowRelation.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOneRowRelation.java
index ad811526a54..44a067829a1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOneRowRelation.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/physical/PhysicalOneRowRelation.java
@@ -17,7 +17,9 @@
package org.apache.doris.nereids.trees.plans.physical;
+import org.apache.doris.analysis.ExprToStringValueVisitor;
import org.apache.doris.analysis.LiteralExpr;
+import org.apache.doris.analysis.StringValueContext;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.Env;
import org.apache.doris.nereids.CascadesContext;
@@ -177,7 +179,7 @@ public class PhysicalOneRowRelation extends
PhysicalRelation implements OneRowRe
columns.add(new Column(output.getName(),
output.getDataType().toCatalogDataType()));
if
(output.getDataType().toCatalogDataType().isVarbinaryType()) {
// The FE (computeResultInFe) can currently only build
a ResultSet<List<List<String>>>.
- // If we materialize a VARBINARY literal via
legacyExpr.getStringValueForQuery():
+ // If we materialize a VARBINARY literal via
ExprToStringValueVisitor:
// 1) We first wrap the raw bytes in a Java String.
// 2) Later StmtExecutor.sendTextResultRow
re-encodes that String as UTF-8 when
// writing the MySQL wire protocol. This may
expand bytes (e.g. 0xAB becomes
@@ -188,8 +190,9 @@ public class PhysicalOneRowRelation extends
PhysicalRelation implements OneRowRe
// so we can VARBINARY safely and remove this early
return.
return Optional.empty();
}
- data.add(legacyExpr.getStringValueForQuery(
-
cascadesContext.getStatementContext().getFormatOptions()));
+
data.add(legacyExpr.accept(ExprToStringValueVisitor.INSTANCE,
+ StringValueContext.forQuery(
+
cascadesContext.getStatementContext().getFormatOptions())));
} else {
return Optional.empty();
}
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 3a42505ba50..e3cc5ea106c 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
@@ -19,6 +19,7 @@ package org.apache.doris.qe;
import org.apache.doris.analysis.Expr;
import org.apache.doris.analysis.ExprToSqlVisitor;
+import org.apache.doris.analysis.ExprToStringValueVisitor;
import org.apache.doris.analysis.OutFileClause;
import org.apache.doris.analysis.PlaceHolderExpr;
import org.apache.doris.analysis.Queriable;
@@ -26,6 +27,7 @@ import org.apache.doris.analysis.RedirectStatus;
import org.apache.doris.analysis.StatementBase;
import org.apache.doris.analysis.StorageBackend;
import org.apache.doris.analysis.StorageBackend.StorageType;
+import org.apache.doris.analysis.StringValueContext;
import org.apache.doris.analysis.ToSqlParams;
import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DatabaseIf;
@@ -287,7 +289,8 @@ public class StmtExecutor {
"do not support non-literal expr in transactional
insert operation: "
+ expr.accept(ExprToSqlVisitor.INSTANCE,
ToSqlParams.WITH_TABLE));
}
-
row.addColBuilder().setValue(expr.getStringValueForStreamLoad(options));
+
row.addColBuilder().setValue(expr.accept(ExprToStringValueVisitor.INSTANCE,
+ StringValueContext.forStreamLoad(options)));
}
return row.build();
}
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 7d797e21b5b..f1be4f4d9b5 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
@@ -19,6 +19,7 @@ package org.apache.doris.analysis;
import org.apache.doris.catalog.ScalarType;
import org.apache.doris.common.AnalysisException;
+import org.apache.doris.foundation.format.FormatOptions;
import org.apache.doris.qe.ConnectContext;
import org.junit.jupiter.api.Assertions;
@@ -51,12 +52,12 @@ public class DateLiteralTest {
timeZone = "+08:00";
context.getSessionVariable().setTimeZone(timeZone);
expected = "2020-02-02 20:00:03.123456+08:00";
- Assertions.assertEquals(expected,
dateLiteral.getStringValueForQuery(null));
+ Assertions.assertEquals(expected,
dateLiteral.accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
timeZone = "-08:00";
context.getSessionVariable().setTimeZone(timeZone);
expected = "2020-02-02 04:00:03.123456-08:00";
- Assertions.assertEquals(expected,
dateLiteral.getStringValueForQuery(null));
+ Assertions.assertEquals(expected,
dateLiteral.accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
} finally {
ConnectContext.remove();
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java
b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java
new file mode 100644
index 00000000000..439d9d97aa4
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/analysis/ExprToStringValueVisitorTest.java
@@ -0,0 +1,536 @@
+// 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.ArrayType;
+import org.apache.doris.catalog.MapType;
+import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.catalog.StructField;
+import org.apache.doris.catalog.StructType;
+import org.apache.doris.catalog.Type;
+import org.apache.doris.common.FeConstants;
+import org.apache.doris.foundation.format.FormatOptions;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+
+public class ExprToStringValueVisitorTest {
+
+ private static final ExprToStringValueVisitor V =
ExprToStringValueVisitor.INSTANCE;
+
+ // ======================== BoolLiteral ========================
+
+ @Test
+ public void testBoolLiteralQueryTopLevel() {
+ BoolLiteral t = new BoolLiteral(true);
+ BoolLiteral f = new BoolLiteral(false);
+ FormatOptions opts = FormatOptions.getDefault();
+ // level=0: uses getStringValue() which returns "1"/"0"
+ Assertions.assertEquals("1", V.visitBoolLiteral(t,
StringValueContext.forQuery(opts)));
+ Assertions.assertEquals("0", V.visitBoolLiteral(f,
StringValueContext.forQuery(opts)));
+ }
+
+ @Test
+ public void testBoolLiteralNestedDefaultFormat() {
+ BoolLiteral t = new BoolLiteral(true);
+ BoolLiteral f = new BoolLiteral(false);
+ FormatOptions opts = FormatOptions.getDefault();
+ // Default: isBoolValueNum=true, so nested returns "1"/"0"
+ opts.level = 1;
+ Assertions.assertEquals("1", V.visitBoolLiteral(t,
StringValueContext.forQuery(opts)));
+ Assertions.assertEquals("0", V.visitBoolLiteral(f,
StringValueContext.forQuery(opts)));
+ }
+
+ @Test
+ public void testBoolLiteralNestedHiveFormat() {
+ BoolLiteral t = new BoolLiteral(true);
+ BoolLiteral f = new BoolLiteral(false);
+ FormatOptions opts = FormatOptions.getForHive();
+ // Hive: isBoolValueNum=false, nested returns "true"/"false"
+ opts.level = 1;
+ Assertions.assertEquals("true", V.visitBoolLiteral(t,
StringValueContext.forQuery(opts)));
+ Assertions.assertEquals("false", V.visitBoolLiteral(f,
StringValueContext.forQuery(opts)));
+ }
+
+ // ======================== NullLiteral ========================
+
+ @Test
+ public void testNullLiteralQueryTopLevel() {
+ NullLiteral n = new NullLiteral();
+ Assertions.assertNull(V.visitNullLiteral(n,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testNullLiteralStreamLoad() {
+ NullLiteral n = new NullLiteral();
+ Assertions.assertEquals(FeConstants.null_string,
+ V.visitNullLiteral(n,
StringValueContext.forStreamLoad(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testNullLiteralInComplexTypeDefault() {
+ NullLiteral n = new NullLiteral();
+ // Default nullFormat = "null"
+ Assertions.assertEquals("null",
+ V.visitNullLiteral(n,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ @Test
+ public void testNullLiteralInComplexTypePresto() {
+ NullLiteral n = new NullLiteral();
+ // Presto nullFormat = "NULL"
+ Assertions.assertEquals("NULL",
+ V.visitNullLiteral(n,
StringValueContext.forQuery(FormatOptions.getForPresto()).asComplexType()));
+ }
+
+ @Test
+ public void testNullLiteralInComplexTypeStreamLoad() {
+ NullLiteral n = new NullLiteral();
+ // Inside a complex type during stream load, inComplexType takes
precedence over forStreamLoad.
+ // Old behavior: ArrayLiteral.getStringValueForStreamLoad ->
getStringValueForQuery
+ // -> child.getStringValueInComplexTypeForQuery -> getNullFormat() =
"null"
+ Assertions.assertEquals("null",
+ V.visitNullLiteral(n,
+
StringValueContext.forStreamLoad(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== DecimalLiteral ========================
+
+ @Test
+ public void testDecimalLiteralPlainString() throws Exception {
+ DecimalLiteral d = new DecimalLiteral("123.45");
+ Assertions.assertEquals("123.45", V.visitDecimalLiteral(d,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testDecimalLiteralNoScientificNotation() throws Exception {
+ DecimalLiteral d = new DecimalLiteral("100000000000000000.123");
+ // toPlainString avoids scientific notation
+ Assertions.assertFalse(V.visitDecimalLiteral(d,
+
StringValueContext.forQuery(FormatOptions.getDefault())).contains("E"));
+ }
+
+ // ======================== StringLiteral ========================
+
+ @Test
+ public void testStringLiteralQueryTopLevel() {
+ StringLiteral s = new StringLiteral("hello");
+ Assertions.assertEquals("hello",
+ V.visitStringLiteral(s,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testStringLiteralInComplexType() {
+ StringLiteral s = new StringLiteral("hello");
+ // Default wrapper = "
+ Assertions.assertEquals("\"hello\"",
+ V.visitStringLiteral(s,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ @Test
+ public void testStringLiteralInComplexTypePresto() {
+ StringLiteral s = new StringLiteral("hello");
+ // Presto wrapper = "" (empty)
+ Assertions.assertEquals("hello",
+ V.visitStringLiteral(s,
StringValueContext.forQuery(FormatOptions.getForPresto()).asComplexType()));
+ }
+
+ // ======================== IPv4Literal ========================
+
+ @Test
+ public void testIPv4LiteralQuery() throws Exception {
+ IPv4Literal ip = new IPv4Literal("192.168.1.1");
+ Assertions.assertEquals("192.168.1.1",
+ V.visitIPv4Literal(ip,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testIPv4LiteralInComplexType() throws Exception {
+ IPv4Literal ip = new IPv4Literal("10.0.0.1");
+ Assertions.assertEquals("\"10.0.0.1\"",
+ V.visitIPv4Literal(ip,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== IPv6Literal ========================
+
+ @Test
+ public void testIPv6LiteralQuery() throws Exception {
+ IPv6Literal ip = new IPv6Literal("::1");
+ Assertions.assertEquals("::1",
+ V.visitIPv6Literal(ip,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testIPv6LiteralInComplexType() throws Exception {
+ IPv6Literal ip = new IPv6Literal("fe80::1");
+ Assertions.assertEquals("\"fe80::1\"",
+ V.visitIPv6Literal(ip,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== VarBinaryLiteral ========================
+
+ @Test
+ public void testVarBinaryLiteralQuery() throws Exception {
+ VarBinaryLiteral vb = new VarBinaryLiteral("hello".getBytes());
+ Assertions.assertEquals("hello",
+ V.visitVarBinaryLiteral(vb,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testVarBinaryLiteralInComplexType() throws Exception {
+ VarBinaryLiteral vb = new VarBinaryLiteral("test".getBytes());
+ Assertions.assertEquals("\"test\"",
+ V.visitVarBinaryLiteral(vb,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== PlaceHolderExpr ========================
+
+ @Test
+ public void testPlaceHolderExprInComplexType() {
+ PlaceHolderExpr ph = new PlaceHolderExpr();
+ // PlaceHolderExpr.getStringValue() returns ""
+ Assertions.assertEquals("\"\"",
+ V.visitPlaceHolderExpr(ph,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== JsonLiteral ========================
+
+ @Test
+ public void testJsonLiteralQuery() throws Exception {
+ JsonLiteral j = new JsonLiteral("{\"a\":1}");
+ Assertions.assertEquals("{\"a\":1}",
+ V.visitJsonLiteral(j,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testJsonLiteralInComplexTypeReturnsNull() throws Exception {
+ JsonLiteral j = new JsonLiteral("{\"a\":1}");
+ Assertions.assertNull(
+ V.visitJsonLiteral(j,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== MaxLiteral ========================
+
+ @Test
+ public void testMaxLiteralQuery() {
+ Assertions.assertNull(
+ V.visitMaxLiteral(MaxLiteral.MAX_VALUE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testMaxLiteralInComplexTypeReturnsNull() {
+ Assertions.assertNull(
+ V.visitMaxLiteral(MaxLiteral.MAX_VALUE,
+
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== FloatLiteral ========================
+
+ @Test
+ public void testFloatLiteralDouble() {
+ FloatLiteral f = new FloatLiteral(3.14, Type.DOUBLE);
+ String result = V.visitFloatLiteral(f,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ // FractionalFormat should produce a numeric string
+ Assertions.assertNotNull(result);
+ Assertions.assertTrue(result.contains("3.14"));
+ }
+
+ @Test
+ public void testFloatLiteralFloat() {
+ FloatLiteral f = new FloatLiteral(2.5, Type.FLOAT);
+ String result = V.visitFloatLiteral(f,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertNotNull(result);
+ Assertions.assertTrue(result.contains("2.5"));
+ }
+
+ @Test
+ public void testFloatLiteralPositiveInfinity() {
+ FloatLiteral f = new FloatLiteral(Double.POSITIVE_INFINITY,
Type.DOUBLE);
+ String result = V.visitFloatLiteral(f,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("Infinity", result);
+ }
+
+ @Test
+ public void testFloatLiteralNegativeInfinity() {
+ FloatLiteral f = new FloatLiteral(Double.NEGATIVE_INFINITY,
Type.DOUBLE);
+ String result = V.visitFloatLiteral(f,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("-Infinity", result);
+ }
+
+ @Test
+ public void testFloatLiteralNaN() {
+ FloatLiteral f = new FloatLiteral(Double.NaN, Type.DOUBLE);
+ String result = V.visitFloatLiteral(f,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("NaN", result);
+ }
+
+ @Test
+ public void testFloatLiteralFloatTypePositiveInfinity() {
+ // FLOAT infinity gets promoted to DOUBLE infinity
+ FloatLiteral f = new FloatLiteral((double) Float.POSITIVE_INFINITY,
Type.FLOAT);
+ String result = V.visitFloatLiteral(f,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("Infinity", result);
+ }
+
+ // ======================== DateLiteral ========================
+
+ @Test
+ public void testDateLiteralDateType() throws Exception {
+ DateLiteral d = new DateLiteral("2024-01-15", Type.DATEV2);
+ Assertions.assertEquals("2024-01-15",
+ V.visitDateLiteral(d,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ }
+
+ @Test
+ public void testDateLiteralDatetimeType() throws Exception {
+ DateLiteral d = new DateLiteral("2024-01-15 10:30:00",
+ ScalarType.createDatetimeV2Type(0));
+ String result = V.visitDateLiteral(d,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("2024-01-15 10:30:00", result);
+ }
+
+ @Test
+ public void testDateLiteralInComplexType() throws Exception {
+ DateLiteral d = new DateLiteral("2024-01-15", Type.DATEV2);
+ Assertions.assertEquals("\"2024-01-15\"",
+ V.visitDateLiteral(d,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType()));
+ }
+
+ // ======================== CastExpr ========================
+
+ @Test
+ public void testCastExprQueryTopLevel() {
+ StringLiteral child = new StringLiteral("42");
+ CastExpr cast = new CastExpr(Type.BIGINT, child, false);
+ // Top-level query: returns getStringValue() of cast (empty string for
CastExpr)
+ String result = V.visitCastExpr(cast,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals(cast.getStringValue(), result);
+ }
+
+ @Test
+ public void testCastExprInComplexType() {
+ StringLiteral child = new StringLiteral("42");
+ CastExpr cast = new CastExpr(Type.BIGINT, child, false);
+ // In complex type: delegates to child
+ String result = V.visitCastExpr(cast,
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType());
+ Assertions.assertEquals("\"42\"", result);
+ }
+
+ @Test
+ public void testCastExprStreamLoad() {
+ StringLiteral child = new StringLiteral("42");
+ CastExpr cast = new CastExpr(Type.BIGINT, child, false);
+ // Stream load: delegates to child
+ String result = V.visitCastExpr(cast,
StringValueContext.forStreamLoad(FormatOptions.getDefault()));
+ Assertions.assertEquals("42", result);
+ }
+
+ // ======================== ArrayLiteral ========================
+
+ @Test
+ public void testArrayLiteralDefault() {
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(Type.INT),
+ new IntLiteral(1), new IntLiteral(2), new IntLiteral(3));
+ String result = V.visitArrayLiteral(arr,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ // Default collectionDelim = ", "
+ Assertions.assertEquals("[1, 2, 3]", result);
+ }
+
+ @Test
+ public void testArrayLiteralHive() {
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(Type.INT),
+ new IntLiteral(10), new IntLiteral(20));
+ String result = V.visitArrayLiteral(arr,
StringValueContext.forQuery(FormatOptions.getForHive()));
+ // Hive collectionDelim = ","
+ Assertions.assertEquals("[10,20]", result);
+ }
+
+ @Test
+ public void testArrayLiteralWithStrings() {
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(Type.VARCHAR),
+ new StringLiteral("abc"), new StringLiteral("def"));
+ String result = V.visitArrayLiteral(arr,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ // Strings get wrapped with nestedStringWrapper in complex context
+ Assertions.assertEquals("[\"abc\", \"def\"]", result);
+ }
+
+ @Test
+ public void testArrayLiteralWithNulls() {
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(Type.INT),
+ new IntLiteral(1), new NullLiteral());
+ String result = V.visitArrayLiteral(arr,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ // NullLiteral in complex type returns nullFormat = "null"
+ Assertions.assertEquals("[1, null]", result);
+ }
+
+ @Test
+ public void testArrayLiteralEmpty() {
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(Type.INT));
+ String result = V.visitArrayLiteral(arr,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("[]", result);
+ }
+
+ // ======================== MapLiteral ========================
+
+ @Test
+ public void testMapLiteralDefault() {
+ MapLiteral map = new MapLiteral(new MapType(Type.VARCHAR, Type.INT),
+ Arrays.asList(new StringLiteral("a"), new StringLiteral("b")),
+ Arrays.asList(new IntLiteral(1), new IntLiteral(2)));
+ String result = V.visitMapLiteral(map,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ // Default mapKeyDelim = ":", collectionDelim = ", ", strings wrapped
+ Assertions.assertEquals("{\"a\":1, \"b\":2}", result);
+ }
+
+ @Test
+ public void testMapLiteralPresto() {
+ MapLiteral map = new MapLiteral(new MapType(Type.VARCHAR, Type.INT),
+ Arrays.asList(new StringLiteral("x")),
+ Arrays.asList(new IntLiteral(42)));
+ String result = V.visitMapLiteral(map,
StringValueContext.forQuery(FormatOptions.getForPresto()));
+ // Presto: mapKeyDelim = "=", wrapper = "" (empty)
+ Assertions.assertEquals("{x=42}", result);
+ }
+
+ // ======================== StructLiteral ========================
+
+ @Test
+ public void testStructLiteralQuery() throws Exception {
+ StructType structType = new StructType(
+ new StructField("name", Type.VARCHAR),
+ new StructField("age", Type.INT));
+ StructLiteral s = new StructLiteral(structType,
+ new StringLiteral("Alice"), new IntLiteral(30));
+ FormatOptions opts = FormatOptions.getDefault();
+ String result = V.visitStructLiteral(s,
StringValueContext.forQuery(opts));
+ // Query mode: includes field names, mapKeyDelim=":"
+ Assertions.assertEquals("{\"name\":\"Alice\", \"age\":30}", result);
+ }
+
+ @Test
+ public void testStructLiteralStreamLoad() throws Exception {
+ StructType structType = new StructType(
+ new StructField("name", Type.VARCHAR),
+ new StructField("age", Type.INT));
+ StructLiteral s = new StructLiteral(structType,
+ new StringLiteral("Bob"), new IntLiteral(25));
+ FormatOptions opts = FormatOptions.getDefault();
+ String result = V.visitStructLiteral(s,
StringValueContext.forStreamLoad(opts));
+ // Stream load mode: NO field names, children use query+complex context
+ Assertions.assertEquals("{\"Bob\", 25}", result);
+ }
+
+ // ======================== Default visitor (unoverridden Expr)
========================
+
+ @Test
+ public void testDefaultVisitFallsBackToGetStringValue() {
+ IntLiteral i = new IntLiteral(42);
+ // IntLiteral has no specific visit method, falls through to default
visit()
+ String result = V.visit(i,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("42", result);
+ }
+
+ // ======================== Context behavior ========================
+
+ @Test
+ public void testAsComplexTypeIdempotent() {
+ StringValueContext ctx =
StringValueContext.forQuery(FormatOptions.getDefault()).asComplexType();
+ StringValueContext ctx2 = ctx.asComplexType();
+ // asComplexType on already-complex context returns same instance
+ Assertions.assertSame(ctx, ctx2);
+ }
+
+ @Test
+ public void testContextModeFlags() {
+ StringValueContext query =
StringValueContext.forQuery(FormatOptions.getDefault());
+ Assertions.assertFalse(query.isForStreamLoad());
+ Assertions.assertFalse(query.isInComplexType());
+
+ StringValueContext stream =
StringValueContext.forStreamLoad(FormatOptions.getDefault());
+ Assertions.assertTrue(stream.isForStreamLoad());
+ Assertions.assertFalse(stream.isInComplexType());
+
+ StringValueContext complex = query.asComplexType();
+ Assertions.assertFalse(complex.isForStreamLoad());
+ Assertions.assertTrue(complex.isInComplexType());
+ }
+
+ @Test
+ public void testAsQueryComplexType() {
+ StringValueContext streamCtx =
StringValueContext.forStreamLoad(FormatOptions.getDefault());
+ StringValueContext queryComplex = streamCtx.asQueryComplexType();
+ // asQueryComplexType: forces query mode + complex type
+ Assertions.assertFalse(queryComplex.isForStreamLoad());
+ Assertions.assertTrue(queryComplex.isInComplexType());
+ }
+
+ // ======================== Nested collections ========================
+
+ @Test
+ public void testNestedArrayInArray() {
+ ArrayLiteral inner = new ArrayLiteral(new ArrayType(Type.INT),
+ new IntLiteral(1), new IntLiteral(2));
+ ArrayLiteral outer = new ArrayLiteral(new ArrayType(new
ArrayType(Type.INT)), inner);
+ String result = V.visitArrayLiteral(outer,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("[[1, 2]]", result);
+ }
+
+ @Test
+ public void testArrayWithMapValues() {
+ MapLiteral map = new MapLiteral(new MapType(Type.VARCHAR, Type.INT),
+ Arrays.asList(new StringLiteral("k")),
+ Arrays.asList(new IntLiteral(1)));
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(new
MapType(Type.VARCHAR, Type.INT)), map);
+ String result = V.visitArrayLiteral(arr,
StringValueContext.forQuery(FormatOptions.getDefault()));
+ Assertions.assertEquals("[{\"k\":1}]", result);
+ }
+
+ // ======================== Level tracking ========================
+
+ @Test
+ public void testLevelResetAfterArray() {
+ FormatOptions opts = FormatOptions.getDefault();
+ Assertions.assertEquals(0, opts.level);
+ ArrayLiteral arr = new ArrayLiteral(new ArrayType(Type.INT), new
IntLiteral(1));
+ V.visitArrayLiteral(arr, StringValueContext.forQuery(opts));
+ // level should be restored to 0 after visit
+ Assertions.assertEquals(0, opts.level);
+ }
+
+ @Test
+ public void testLevelResetAfterMap() {
+ FormatOptions opts = FormatOptions.getDefault();
+ MapLiteral map = new MapLiteral(new MapType(Type.VARCHAR, Type.INT),
+ Arrays.asList(new StringLiteral("k")),
+ Arrays.asList(new IntLiteral(1)));
+ V.visitMapLiteral(map, StringValueContext.forQuery(opts));
+ Assertions.assertEquals(0, opts.level);
+ }
+
+ @Test
+ public void testLevelResetAfterStruct() throws Exception {
+ FormatOptions opts = FormatOptions.getDefault();
+ StructType st = new StructType(new StructField("f", Type.INT));
+ StructLiteral s = new StructLiteral(st, new IntLiteral(1));
+ V.visitStructLiteral(s, StringValueContext.forQuery(opts));
+ Assertions.assertEquals(0, opts.level);
+ }
+
+}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/analysis/FloatLiteralTest.java
b/fe/fe-core/src/test/java/org/apache/doris/analysis/FloatLiteralTest.java
index 8d0ef45fdf5..14a12ed4b75 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/analysis/FloatLiteralTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/analysis/FloatLiteralTest.java
@@ -18,6 +18,7 @@
package org.apache.doris.analysis;
import org.apache.doris.catalog.Type;
+import org.apache.doris.foundation.format.FormatOptions;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -26,79 +27,79 @@ public class FloatLiteralTest {
@Test
public void testDoubleGetStringValue() {
- Assertions.assertEquals("0", new FloatLiteral(0d,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("0", new FloatLiteral(0.0,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-0", new FloatLiteral(-0d,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1", new FloatLiteral(1d,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1", new FloatLiteral(1.0,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1", new FloatLiteral(-1d,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1.554", new FloatLiteral(1.554,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("0.338", new FloatLiteral(0.338,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1", new FloatLiteral(-1.0,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1e+100", new FloatLiteral(1e100,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1e-100", new FloatLiteral(1e-100,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1000000000000000", new FloatLiteral(1.0E15,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1000000000000000", new FloatLiteral(-1.0E15,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1e+16", new FloatLiteral(1.0E16,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1e+16", new FloatLiteral(-1.0E16,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("0.0001", new FloatLiteral(0.0001,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1e-05", new FloatLiteral(0.00001,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1e+308", new FloatLiteral(1e308,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1e+308", new FloatLiteral(-1e308,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("Infinity", new
FloatLiteral(Double.POSITIVE_INFINITY,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-Infinity", new
FloatLiteral(Double.NEGATIVE_INFINITY,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("NaN", new FloatLiteral(Double.NaN,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1234567890123456", new
FloatLiteral(1234567890123456.12345, Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1.234567890123457e+16", new
FloatLiteral(12345678901234567.12345,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("0.0001234567890123457", new
FloatLiteral(0.0001234567890123456789,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("1.234567890123456e-15", new
FloatLiteral(0.000000000000001234567890123456,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("123.456", new FloatLiteral(123.456000,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("123", new FloatLiteral(123.000,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1234567890123456", new
FloatLiteral(-1234567890123456.12345,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1.234567890123457e+16", new
FloatLiteral(-12345678901234567.12345,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-0.0001234567890123457", new
FloatLiteral(-0.0001234567890123456789,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-1.234567890123456e-15", new
FloatLiteral(-0.000000000000001234567890123456,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-123.456", new FloatLiteral(-123.456000,
Type.DOUBLE).getStringValueForQuery(null));
- Assertions.assertEquals("-123", new FloatLiteral(-123.000,
Type.DOUBLE).getStringValueForQuery(null));
+ Assertions.assertEquals("0", new FloatLiteral(0d,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0", new FloatLiteral(0.0,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-0", new FloatLiteral(-0d,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1", new FloatLiteral(1d,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1", new FloatLiteral(1.0,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1", new FloatLiteral(-1d,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1.554", new FloatLiteral(1.554,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0.338", new FloatLiteral(0.338,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1", new FloatLiteral(-1.0,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e+100", new FloatLiteral(1e100,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e-100", new FloatLiteral(1e-100,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1000000000000000", new FloatLiteral(1.0E15,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1000000000000000", new FloatLiteral(-1.0E15,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e+16", new FloatLiteral(1.0E16,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1e+16", new FloatLiteral(-1.0E16,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0.0001", new FloatLiteral(0.0001,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e-05", new FloatLiteral(0.00001,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e+308", new FloatLiteral(1e308,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1e+308", new FloatLiteral(-1e308,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("Infinity", new
FloatLiteral(Double.POSITIVE_INFINITY,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-Infinity", new
FloatLiteral(Double.NEGATIVE_INFINITY,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("NaN", new FloatLiteral(Double.NaN,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1234567890123456", new
FloatLiteral(1234567890123456.12345,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1.234567890123457e+16", new
FloatLiteral(12345678901234567.12345,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0.0001234567890123457", new
FloatLiteral(0.0001234567890123456789,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1.234567890123456e-15", new
FloatLiteral(0.000000000000001234567890123456,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("123.456", new FloatLiteral(123.456000,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("123", new FloatLiteral(123.000,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1234567890123456", new
FloatLiteral(-1234567890123456.12345,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1.234567890123457e+16", new
FloatLiteral(-12345678901234567.12345,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-0.0001234567890123457", new
FloatLiteral(-0.0001234567890123456789,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1.234567890123456e-15", new
FloatLiteral(-0.000000000000001234567890123456,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-123.456", new FloatLiteral(-123.456000,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-123", new FloatLiteral(-123.000,
Type.DOUBLE).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
}
@Test
public void testFloatGetStringValue() {
- Assertions.assertEquals("0", new FloatLiteral(0d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("0", new FloatLiteral(0.0,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-0", new FloatLiteral(-0d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1", new FloatLiteral(1d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1", new FloatLiteral(1.0d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-1", new FloatLiteral(-1d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1.554", new FloatLiteral(1.554d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("0.338", new FloatLiteral(0.338d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-1", new FloatLiteral(-1.0d,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1e+38", new FloatLiteral(1e38,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1e-38", new FloatLiteral(1e-38,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1000000", new
FloatLiteral(1.0E6).getStringValueForQuery(null));
- Assertions.assertEquals("-1000000", new FloatLiteral(-1.0E6,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1e+07", new FloatLiteral(1.0E7,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-1e+07", new FloatLiteral(-1.0E7,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("0.0001", new FloatLiteral(0.0001,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1e-05", new FloatLiteral(0.00001,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("3.402823e+38", new FloatLiteral((double)
Float.MAX_VALUE, Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("Infinity", new FloatLiteral(1e39,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-Infinity", new FloatLiteral(-1e39,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("Infinity", new
FloatLiteral(Double.POSITIVE_INFINITY,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-Infinity", new
FloatLiteral(Double.NEGATIVE_INFINITY,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("NaN", new FloatLiteral(Double.NaN,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("123456.1", new FloatLiteral(123456.12345,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1234567", new FloatLiteral(1234567.12345,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1.234568e+07", new
FloatLiteral(12345678.12345, Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("0.0001234568", new
FloatLiteral(0.0001234567890123456789,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("1.234568e-15", new
FloatLiteral(0.000000000000001234567890123456,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("123.456", new FloatLiteral(123.456000,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("123", new FloatLiteral(123.000,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-1234567", new FloatLiteral(-1234567.12345,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-1.234568e+07", new
FloatLiteral(-12345678.12345, Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-0.0001234568", new
FloatLiteral(-0.0001234567890123456789,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-1.234568e-15", new
FloatLiteral(-0.000000000000001234567890123456,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-123.456", new FloatLiteral(-123.456000,
Type.FLOAT).getStringValueForQuery(null));
- Assertions.assertEquals("-123", new FloatLiteral(-123.000,
Type.FLOAT).getStringValueForQuery(null));
+ Assertions.assertEquals("0", new FloatLiteral(0d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0", new FloatLiteral(0.0,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-0", new FloatLiteral(-0d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1", new FloatLiteral(1d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1", new FloatLiteral(1.0d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1", new FloatLiteral(-1d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1.554", new FloatLiteral(1.554d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0.338", new FloatLiteral(0.338d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1", new FloatLiteral(-1.0d,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e+38", new FloatLiteral(1e38,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e-38", new FloatLiteral(1e-38,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1000000", new
FloatLiteral(1.0E6).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1000000", new FloatLiteral(-1.0E6,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e+07", new FloatLiteral(1.0E7,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1e+07", new FloatLiteral(-1.0E7,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0.0001", new FloatLiteral(0.0001,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1e-05", new FloatLiteral(0.00001,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("3.402823e+38", new FloatLiteral((double)
Float.MAX_VALUE, Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("Infinity", new FloatLiteral(1e39,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-Infinity", new FloatLiteral(-1e39,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("Infinity", new
FloatLiteral(Double.POSITIVE_INFINITY,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-Infinity", new
FloatLiteral(Double.NEGATIVE_INFINITY,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("NaN", new FloatLiteral(Double.NaN,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("123456.1", new FloatLiteral(123456.12345,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1234567", new FloatLiteral(1234567.12345,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1.234568e+07", new
FloatLiteral(12345678.12345,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("0.0001234568", new
FloatLiteral(0.0001234567890123456789,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("1.234568e-15", new
FloatLiteral(0.000000000000001234567890123456,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("123.456", new FloatLiteral(123.456000,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("123", new FloatLiteral(123.000,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1234567", new FloatLiteral(-1234567.12345,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1.234568e+07", new
FloatLiteral(-12345678.12345,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-0.0001234568", new
FloatLiteral(-0.0001234567890123456789,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-1.234568e-15", new
FloatLiteral(-0.000000000000001234567890123456,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-123.456", new FloatLiteral(-123.456000,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
+ Assertions.assertEquals("-123", new FloatLiteral(-123.000,
Type.FLOAT).accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(FormatOptions.getDefault())));
}
}
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 c42a652e23b..5eae96bd964 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
@@ -46,9 +46,9 @@ public class VarBinaryLiteralAnalysisTest {
Assertions.assertEquals("abc", lit.getStringValue());
FormatOptions opts = FormatOptions.getDefault();
- Assertions.assertEquals("\"abc\"",
lit.getStringValueInComplexTypeForQuery(opts));
+ Assertions.assertEquals("\"abc\"",
lit.accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(opts).asComplexType()));
FormatOptions hive = FormatOptions.getForHive();
- Assertions.assertEquals("\"abc\"",
lit.getStringValueInComplexTypeForQuery(hive));
+ Assertions.assertEquals("\"abc\"",
lit.accept(ExprToStringValueVisitor.INSTANCE,
StringValueContext.forQuery(hive).asComplexType()));
}
@Test
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 f584cc36c9f..01a03ad93f2 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
@@ -18,8 +18,10 @@
package org.apache.doris.nereids.trees.expressions;
import org.apache.doris.analysis.ExprToSqlVisitor;
+import org.apache.doris.analysis.ExprToStringValueVisitor;
import org.apache.doris.analysis.ExprToThriftVisitor;
import org.apache.doris.analysis.NullLiteral;
+import org.apache.doris.analysis.StringValueContext;
import org.apache.doris.analysis.ToSqlParams;
import org.apache.doris.analysis.VarBinaryLiteral;
import org.apache.doris.foundation.format.FormatOptions;
@@ -51,11 +53,15 @@ public class VarBinaryLiteralTest {
// nested string wrapper behavior (still wraps the plain string value)
FormatOptions opts = FormatOptions.getDefault();
- Assertions.assertEquals("\"hello\"",
lit.getStringValueInComplexTypeForQuery(opts));
+ Assertions.assertEquals("\"hello\"",
+ lit.accept(ExprToStringValueVisitor.INSTANCE,
+ StringValueContext.forQuery(opts).asComplexType()));
// hive option uses same wrapper for nested by default
FormatOptions hive = FormatOptions.getForHive();
- Assertions.assertEquals("\"hello\"",
lit.getStringValueInComplexTypeForQuery(hive));
+ Assertions.assertEquals("\"hello\"",
+ lit.accept(ExprToStringValueVisitor.INSTANCE,
+ StringValueContext.forQuery(hive).asComplexType()));
}
@Test
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]