This is an automated email from the ASF dual-hosted git repository.
zclll 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 8c5b9aeb003 [Feature](function) Support function DEFAULT (#57531)
8c5b9aeb003 is described below
commit 8c5b9aeb003858ae4366ede5cf253ed92ff1554d
Author: linrrarity <[email protected]>
AuthorDate: Sat Jan 24 01:12:55 2026 +0800
[Feature](function) Support function DEFAULT (#57531)
Return the default value of column
```sql
CREATE TABLE test_default_scalar (
c_id INT,
c_bool BOOLEAN NULL
DEFAULT 1,
c_tinyint TINYINT NULL
DEFAULT 7,
c_smallint SMALLINT NULL
DEFAULT 32000,
c_int INT NULL
DEFAULT 2147483647,
c_bigint BIGINT NULL
DEFAULT 9223372036854775807,
c_largeint LARGEINT NULL
DEFAULT '170141183460469231731687303715884105727',
c_float FLOAT NULL
DEFAULT 3.125,
c_double DOUBLE NULL
DEFAULT 2.718281828,
c_decimal DECIMAL(27, 9) NULL
DEFAULT '123456789.123456789',
c_decimal_compact DECIMAL(18, 4) NULL
DEFAULT '99999.1234',
c_pi DOUBLE NULL
DEFAULT PI,
c_e DOUBLE NULL
DEFAULT E,
c_char CHAR(8) NULL
DEFAULT 'charDemo',
c_varchar VARCHAR(32) NULL
DEFAULT '',
c_string STRING NULL
DEFAULT 'plain string',
c_datetime DATETIME NULL
DEFAULT '2025-10-25 11:22:33',
c_date DATE NULL
DEFAULT '2025-10-31',
c_json JSON NULL,
c_ipv4 IPV4 NULL
DEFAULT '192.168.1.1',
c_ipv6 IPV6 NULL
DEFAULT '2001:db8::1',
c_array_int ARRAY<INT> NULL
DEFAULT '[]',
c_array_string ARRAY<STRING> NULL,
c_map_str_int MAP<STRING, INT> NULL,
c_struct STRUCT<f1:INT,f2:STRING,f3:BOOLEAN> NULL,
c_variant VARIANT NULL
) PROPERTIES ( 'replication_num' = '1');
SELECT
default(c_id) AS default_id,
default(c_bool) AS default_c_bool,
default(c_tinyint) AS default_c_tinyint,
default(c_smallint) AS default_c_smallint,
default(c_int) AS default_c_int,
default(c_bigint) AS default_c_bigint,
default(c_largeint) AS default_c_largeint,
default(c_float) AS default_c_float,
default(c_double) AS default_c_double,
default(c_decimal) AS default_c_decimal,
default(c_decimal_compact) AS default_c_decimal_compact,
default(c_char) AS default_c_char,
default(c_varchar) AS default_c_varchar,
default(c_string) AS default_c_string,
default(c_datetime) AS default_datetime,
default(c_date) AS defaut_time,
default(c_json) AS default_c_json,
default(c_ipv4) AS default_c_ipv4,
default(c_ipv6) AS default_c_ipv6,
default(c_array_int) AS default_c_array_int,
default(c_array_string) AS default_c_array_string,
default(c_map_str_int) AS default_c_map_str_int,
default(c_struct) AS default_c_struct,
default(c_variant) AS default_c_variant
FROM test_default_scalar
LIMIT 1;
```
```text
+------------+----------------+-------------------+--------------------+---------------+---------------------+-----------------------------------------+-----------------+------------------+---------------------+---------------------------+----------------+-------------------+------------------+---------------------+-------------+----------------+----------------+----------------+---------------------+------------------------+-----------------------+------------------+-------------------+
| default_id | default_c_bool | default_c_tinyint | default_c_smallint |
default_c_int | default_c_bigint | default_c_largeint |
default_c_float | default_c_double | default_c_decimal |
default_c_decimal_compact | default_c_char | default_c_varchar |
default_c_string | default_datetime | defaut_time | default_c_json |
default_c_ipv4 | default_c_ipv6 | default_c_array_int | default_c_array_string
| default_c_map_str_int | default_c_struct | default_c_variant |
+------------+----------------+-------------------+--------------------+---------------+---------------------+-----------------------------------------+-----------------+------------------+---------------------+---------------------------+----------------+-------------------+------------------+---------------------+-------------+----------------+----------------+----------------+---------------------+------------------------+-----------------------+------------------+-------------------+
| NULL | 1 | 7 | 32000 |
2147483647 | 9223372036854775807 | 170141183460469231731687303715884105727 |
3.125 | 2.718281828 | 123456789.123456789 |
99999.1234 | charDemo | | plain string | 2025-10-25
11:22:33 | 2025-10-31 | NULL | 192.168.1.1 | 2001:db8::1 | []
| NULL | NULL | NULL
| NULL |
+------------+----------------+-------------------+--------------------+---------------+---------------------+-----------------------------------------+-----------------+------------------+---------------------+---------------------------+----------------+-------------------+------------------+---------------------+-------------+----------------+----------------+----------------+---------------------+------------------------+-----------------------+------------------+-------------------+
```
---
.../antlr4/org/apache/doris/nereids/DorisParser.g4 | 1 +
.../doris/nereids/parser/LogicalPlanBuilder.java | 12 +
.../rules/expression/ExpressionNormalization.java | 2 +
.../rules/expression/ExpressionRuleType.java | 1 +
.../expression/rules/RewriteDefaultExpression.java | 104 +++
.../doris/nereids/trees/expressions/Default.java | 76 +++
.../expressions/visitor/ExpressionVisitor.java | 5 +
.../nereids_p0/expression/test_default_expr.out | 32 +
.../nereids_p0/expression/test_default_expr.groovy | 738 +++++++++++++++++++++
9 files changed, 971 insertions(+)
diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
index 54f33361907..f1a2f37a7fa 100644
--- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
+++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4
@@ -1629,6 +1629,7 @@ primaryExpression
| CASE value=expression whenClause+ (ELSE elseExpression=expression)? END
#simpleCase
| name=CAST LEFT_PAREN expression AS castDataType RIGHT_PAREN
#cast
| name=TRY_CAST LEFT_PAREN expression AS castDataType RIGHT_PAREN
#tryCast
+ | DEFAULT LEFT_PAREN qualifiedName RIGHT_PAREN
#defaultValue
| constant
#constantDefault
| interval
#intervalLiteral
| ASTERISK (exceptOrReplace)*
#star
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
index af86d18d494..5c48122262c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/parser/LogicalPlanBuilder.java
@@ -521,6 +521,7 @@ import org.apache.doris.nereids.trees.expressions.BitOr;
import org.apache.doris.nereids.trees.expressions.BitXor;
import org.apache.doris.nereids.trees.expressions.CaseWhen;
import org.apache.doris.nereids.trees.expressions.Cast;
+import org.apache.doris.nereids.trees.expressions.Default;
import org.apache.doris.nereids.trees.expressions.DefaultValueSlot;
import org.apache.doris.nereids.trees.expressions.DereferenceExpression;
import org.apache.doris.nereids.trees.expressions.Divide;
@@ -3222,6 +3223,17 @@ public class LogicalPlanBuilder extends
DorisParserBaseVisitor<Object> {
return ParserUtils.withOrigin(ctx, () ->
processTryCast(getExpression(ctx.expression()), ctx.castDataType()));
}
+ @Override
+ public Expression visitDefaultValue(DorisParser.DefaultValueContext ctx) {
+ return ParserUtils.withOrigin(ctx, () -> {
+ List<String> nameParts = ctx.qualifiedName().identifier()
+ .stream()
+ .map(RuleContext::getText)
+ .collect(ImmutableList.toImmutableList());
+ return new Default(new UnboundSlot(nameParts));
+ });
+ }
+
@Override
public UnboundFunction visitExtract(DorisParser.ExtractContext ctx) {
return ParserUtils.withOrigin(ctx, () -> {
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
index e4823347d94..e133303a2c1 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionNormalization.java
@@ -30,6 +30,7 @@ import
org.apache.doris.nereids.rules.expression.rules.MedianConvert;
import org.apache.doris.nereids.rules.expression.rules.MergeDateTrunc;
import
org.apache.doris.nereids.rules.expression.rules.NormalizeBinaryPredicatesRule;
import org.apache.doris.nereids.rules.expression.rules.NormalizeStructElement;
+import
org.apache.doris.nereids.rules.expression.rules.RewriteDefaultExpression;
import
org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticComparisonRule;
import org.apache.doris.nereids.rules.expression.rules.SimplifyArithmeticRule;
import org.apache.doris.nereids.rules.expression.rules.SimplifyCastRule;
@@ -55,6 +56,7 @@ public class ExpressionNormalization extends
ExpressionRewrite {
public static final List<ExpressionRewriteRule<ExpressionRewriteContext>>
NORMALIZE_REWRITE_RULES
= ImmutableList.of(
bottomUp(
+ RewriteDefaultExpression.INSTANCE,
SupportJavaDateFormatter.INSTANCE,
NormalizeBinaryPredicatesRule.INSTANCE,
InPredicateDedup.INSTANCE,
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
index 4c6bf16f227..57d65fad365 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/ExpressionRuleType.java
@@ -67,6 +67,7 @@ public enum ExpressionRuleType {
NORMALIZE_STRUCT_ELEMENT,
TIMESTAMP_TO_ADD_TIME,
TOPN_TO_MAX,
+ REWRITE_DEFAULT_EXPRESSION,
ADD_SESSION_VAR_GUARD;
public int type() {
return ordinal();
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java
new file mode 100644
index 00000000000..6dc8ab7c72c
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/expression/rules/RewriteDefaultExpression.java
@@ -0,0 +1,104 @@
+// 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.nereids.rules.expression.rules;
+
+import org.apache.doris.catalog.Column;
+import org.apache.doris.nereids.CascadesContext;
+import org.apache.doris.nereids.analyzer.UnboundFunction;
+import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.parser.NereidsParser;
+import org.apache.doris.nereids.rules.analysis.ExpressionAnalyzer;
+import org.apache.doris.nereids.rules.expression.ExpressionMatchingContext;
+import org.apache.doris.nereids.rules.expression.ExpressionPatternMatcher;
+import org.apache.doris.nereids.rules.expression.ExpressionPatternRuleFactory;
+import org.apache.doris.nereids.rules.expression.ExpressionRuleType;
+import org.apache.doris.nereids.trees.expressions.Default;
+import org.apache.doris.nereids.trees.expressions.Expression;
+import org.apache.doris.nereids.trees.expressions.SlotReference;
+import org.apache.doris.nereids.trees.expressions.literal.NullLiteral;
+import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
+import org.apache.doris.nereids.types.DataType;
+import org.apache.doris.nereids.util.TypeCoercionUtils;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Rewrite DEFAULT(column) expression to the actual default value of the
column.
+ * This rule transforms:
+ * 1. DEFAULT(column) with default value -> the actual default value expression
+ * 2. DEFAULT(column) with no default value but nullable -> NULL
+ * 3. DEFAULT(column) with no default value and not nullable -> error
+ */
+public class RewriteDefaultExpression implements ExpressionPatternRuleFactory {
+
+ public static final RewriteDefaultExpression INSTANCE = new
RewriteDefaultExpression();
+
+ @Override
+ public List<ExpressionPatternMatcher<? extends Expression>> buildRules() {
+ return ImmutableList.of(
+ matchesType(Default.class)
+ .thenApply(RewriteDefaultExpression::rewrite)
+ .toRule(ExpressionRuleType.REWRITE_DEFAULT_EXPRESSION)
+ );
+ }
+
+ private static Expression rewrite(ExpressionMatchingContext<Default>
context) {
+ Default defaultExpr = context.expr;
+ Expression child = defaultExpr.child();
+
+ if (!(child instanceof SlotReference)) {
+ throw new AnalysisException("DEFAULT requires a column reference,
but got: " + child.toSql());
+ }
+
+ SlotReference slotRef = (SlotReference) child;
+ Optional<Column> columnOpt = slotRef.getOriginalColumn();
+ if (!columnOpt.isPresent()) {
+ throw new AnalysisException("Cannot find column information for
DEFAULT("
+ + slotRef.getName() + ")");
+ }
+
+ Column column = columnOpt.get();
+ DataType targetType = DataType.fromCatalogType(column.getType());
+ if (column.isGeneratedColumn()) {
+ throw new AnalysisException("DEFAULT cannot be used on generated
column '"
+ + column.getName() + "'");
+ }
+
+ String defaultValueSql = column.getDefaultValueSql();
+ if (defaultValueSql == null) {
+ if (column.isAllowNull()) {
+ return new NullLiteral(targetType);
+ } else {
+ throw new AnalysisException("Column '" + column.getName()
+ + "' has no default value and does not allow NULL or
column is auto-increment");
+ }
+ }
+
+ Expression defaultValueExpr = new
NereidsParser().parseExpression(defaultValueSql);
+ if (defaultValueExpr instanceof UnboundFunction) {
+ CascadesContext cascadesContext = context.cascadesContext;
+ LogicalPlan plan = (LogicalPlan)
context.rewriteContext.plan.orElse(null);
+ defaultValueExpr = ExpressionAnalyzer.analyzeFunction(plan,
cascadesContext, defaultValueExpr);
+ }
+
+ return TypeCoercionUtils.castIfNotSameType(defaultValueExpr,
targetType);
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Default.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Default.java
new file mode 100644
index 00000000000..918bf6710df
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/Default.java
@@ -0,0 +1,76 @@
+// 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.nereids.trees.expressions;
+
+import org.apache.doris.nereids.exceptions.AnalysisException;
+import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
+import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression;
+import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
+import org.apache.doris.nereids.types.DataType;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.List;
+
+/**
+ * Default value expression.
+ */
+public class Default extends Expression
+ implements UnaryExpression, AlwaysNullable {
+
+ public Default(Expression child) {
+ super(ImmutableList.of(child));
+ }
+
+ /**
+ * constructor with 1 argument.
+ */
+ public Default(Expression arg, DataType targetType) {
+ super(ImmutableList.of(arg));
+ }
+
+ @Override
+ public Default withChildren(List<Expression> children) {
+ Preconditions.checkArgument(children.size() == 1);
+ return new Default(children.get(0));
+ }
+
+ @Override
+ public DataType getDataType() {
+ return child().getDataType();
+ }
+
+ @Override
+ public void checkLegalityBeforeTypeCoercion() {
+ Expression arg = child();
+ if (!(arg instanceof SlotReference)) {
+ throw new AnalysisException("DEFAULT requires a column reference");
+ }
+ }
+
+ @Override
+ public void checkLegalityAfterRewrite() {
+ checkLegalityBeforeTypeCoercion();
+ }
+
+ @Override
+ public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
+ return visitor.visitDefault(this, context);
+ }
+}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java
index 0b0c85d34c5..aeaea2e8db2 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ExpressionVisitor.java
@@ -40,6 +40,7 @@ import org.apache.doris.nereids.trees.expressions.CaseWhen;
import org.apache.doris.nereids.trees.expressions.Cast;
import org.apache.doris.nereids.trees.expressions.ComparisonPredicate;
import org.apache.doris.nereids.trees.expressions.CompoundPredicate;
+import org.apache.doris.nereids.trees.expressions.Default;
import org.apache.doris.nereids.trees.expressions.DefaultValueSlot;
import org.apache.doris.nereids.trees.expressions.DereferenceExpression;
import org.apache.doris.nereids.trees.expressions.Divide;
@@ -238,6 +239,10 @@ public abstract class ExpressionVisitor<R, C>
return visitSlot(slotReference, context);
}
+ public R visitDefault(Default defaultExpr, C context) {
+ return visit(defaultExpr, context);
+ }
+
public R visitDefaultValue(DefaultValueSlot defaultValueSlot, C context) {
return visitSlot(defaultValueSlot, context);
}
diff --git a/regression-test/data/nereids_p0/expression/test_default_expr.out
b/regression-test/data/nereids_p0/expression/test_default_expr.out
new file mode 100644
index 00000000000..4bbce02744f
--- /dev/null
+++ b/regression-test/data/nereids_p0/expression/test_default_expr.out
@@ -0,0 +1,32 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !scalar_defaults --
+true 7 32000 2147483647 9223372036854775807
170141183460469231731687303715884105727 3.125 2.718281828
123456789.123456789 99999.1234 charDemo plain string
2025-10-25 11:22:33.666777+08:00 2025-10-25T11:22:33 2025-10-31
\N 192.168.1.1 2001:db8::1 [] \N \N \N \N
+
+-- !null_column_default --
+\N
+
+-- !boundary_defaults --
+-128 127 -32768 32767 -2147483648 2147483647
-9223372036854775808 9223372036854775807 0.0 0 0.00
\N
+
+-- !complex_defaults --
+[] \N \N \N \N \N
+
+-- !datetime_format_defaults --
+2025-01-01 2025-01-01T12:30:45
+
+-- !ip_defaults --
+127.0.0.1 10.0.0.1 ::1 2001:db8:85a3::8a2e:370:7334
+
+-- !string_defaults --
+fixed variable length string very long string that can be much longer than
varchar
+
+-- !pi_e_defaults --
+3.141592653589793 2.718281828459045
+
+-- !empty_table_defaults --
+
+-- !same_col_name --
+hello 2026-01-13 3.141592653589793 2023-12-31T23:59:59
+hello 2026-01-13 3.141592653589793 2023-12-31T23:59:59
+hello 2026-01-13 3.141592653589793 2023-12-31T23:59:59
+
diff --git
a/regression-test/suites/nereids_p0/expression/test_default_expr.groovy
b/regression-test/suites/nereids_p0/expression/test_default_expr.groovy
new file mode 100644
index 00000000000..56de490f581
--- /dev/null
+++ b/regression-test/suites/nereids_p0/expression/test_default_expr.groovy
@@ -0,0 +1,738 @@
+// 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.
+
+suite("test_default_expr") {
+
+ def testConstantFoldingConsistency = { String querySql ->
+ def baseRes = sql querySql
+
+ sql "SET debug_skip_fold_constant = true;"
+ def skipFoldConstantRes = sql querySql
+ assertTrue(skipFoldConstantRes == baseRes,
+ "Results differ with debug_skip_fold_constant=true for query:
${querySql}")
+
+ sql "SET debug_skip_fold_constant = false;"
+ sql "SET enable_fold_constant_by_be = true;"
+ def beFoldConstantRes = sql querySql
+ assertTrue(beFoldConstantRes == baseRes,
+ "Results differ with enable_fold_constant_by_be=true for query:
${querySql}")
+
+ sql "SET debug_skip_fold_constant = default;"
+ sql "SET enable_fold_constant_by_be = default;"
+ }
+
+ def tableName = "test_default_scalar"
+ def aggTableName = "test_default_agg"
+ def notNullTableName = "test_default_not_null"
+
+
+ // Test 1: Scalar type constant default value test
+ sql "DROP TABLE IF EXISTS ${tableName}"
+ sql """
+ CREATE TABLE ${tableName} (
+ c_bool BOOLEAN
NULL DEFAULT 1,
+ c_tinyint TINYINT
NULL DEFAULT 7,
+ c_smallint SMALLINT
NULL DEFAULT 32000,
+ c_int INT
NULL DEFAULT 2147483647,
+ c_bigint BIGINT
NULL DEFAULT 9223372036854775807,
+ c_largeint LARGEINT
NULL DEFAULT '170141183460469231731687303715884105727',
+ c_float FLOAT
NULL DEFAULT 3.125,
+ c_double DOUBLE
NULL DEFAULT 2.718281828,
+ c_decimal DECIMAL(27, 9)
NULL DEFAULT '123456789.123456789',
+ c_decimal_compact DECIMAL(18, 4)
NULL DEFAULT '99999.1234',
+ c_char CHAR(8)
NULL DEFAULT 'charDemo',
+ c_varchar VARCHAR(32)
NULL DEFAULT '',
+ c_string STRING
NULL DEFAULT 'plain string',
+ c_tz TIMESTAMPTZ(6)
NULL DEFAULT '2025-10-25 11:22:33.666777+08:00',
+ c_datetime DATETIME
NULL DEFAULT '2025-10-25 11:22:33',
+ c_date DATE
NULL DEFAULT '2025-10-31',
+ c_json JSON
NULL,
+ c_ipv4 IPV4
NULL DEFAULT '192.168.1.1',
+ c_ipv6 IPV6
NULL DEFAULT '2001:db8::1',
+ c_array_int ARRAY<INT>
NULL DEFAULT '[]',
+ c_array_string ARRAY<STRING>
NULL,
+ c_map_str_int MAP<STRING, INT>
NULL,
+ c_struct STRUCT<f1:INT,f2:STRING,f3:BOOLEAN>
NULL,
+ c_variant VARIANT NULL
+ ) PROPERTIES ( 'replication_num' = '1')
+ """
+ sql "INSERT INTO ${tableName} (c_bool) VALUES (0)"
+ sql "INSERT INTO ${tableName} (c_bool) VALUES (1)"
+ sql "INSERT INTO ${tableName} (c_bool) VALUES (0)"
+
+ qt_scalar_defaults """
+ SELECT
+ DEFAULT(c_bool),
+ DEFAULT(c_tinyint),
+ DEFAULT(c_smallint),
+ DEFAULT(c_int),
+ DEFAULT(c_bigint),
+ DEFAULT(c_largeint),
+ DEFAULT(c_float),
+ DEFAULT(c_double),
+ DEFAULT(c_decimal),
+ DEFAULT(c_decimal_compact),
+ DEFAULT(c_char),
+ DEFAULT(c_varchar),
+ DEFAULT(c_string),
+ DEFAULT(c_tz),
+ DEFAULT(c_datetime),
+ DEFAULT(c_date),
+ DEFAULT(c_json),
+ DEFAULT(c_ipv4),
+ DEFAULT(c_ipv6),
+ DEFAULT(c_array_int),
+ DEFAULT(c_array_string),
+ DEFAULT(c_map_str_int),
+ DEFAULT(c_struct),
+ DEFAULT(c_variant)
+ FROM ${tableName}
+ LIMIT 1
+ """
+
+ def result = sql """
+ SELECT
+ DEFAULT(c_bool),
+ DEFAULT(c_tinyint),
+ DEFAULT(c_smallint),
+ DEFAULT(c_int),
+ DEFAULT(c_bigint),
+ DEFAULT(c_largeint),
+ DEFAULT(c_float),
+ DEFAULT(c_double),
+ DEFAULT(c_decimal),
+ DEFAULT(c_decimal_compact),
+ DEFAULT(c_char),
+ DEFAULT(c_varchar),
+ DEFAULT(c_string),
+ DEFAULT(c_datetime),
+ DEFAULT(c_date),
+ DEFAULT(c_json),
+ DEFAULT(c_ipv4),
+ DEFAULT(c_ipv6),
+ DEFAULT(c_array_int),
+ DEFAULT(c_array_string),
+ DEFAULT(c_map_str_int),
+ DEFAULT(c_struct),
+ DEFAULT(c_variant)
+ FROM ${tableName}
+ """
+ def firstRow = result[0]
+ for (int i = 1; i < result.size(); i++) {
+ assertTrue(result[i] == firstRow, "Row ${i} should equal first row")
+ }
+
+ // Test 2: Aggregate type default value test
+ sql "DROP TABLE IF EXISTS ${aggTableName}"
+ sql """
+ CREATE TABLE ${aggTableName} (
+ k_id INT NOT NULL COMMENT 'Aggregate key',
+ bitmap_col BITMAP BITMAP_UNION,
+ hll_col HLL HLL_UNION
+ ) AGGREGATE KEY(k_id)
+ PROPERTIES ( 'replication_num' = '1' )
+ """
+ sql "INSERT INTO ${aggTableName} (k_id) VALUES (1)"
+ sql "INSERT INTO ${aggTableName} (k_id) VALUES (2)"
+ sql "INSERT INTO ${aggTableName} (k_id) VALUES (3)"
+
+ test {
+ sql "SELECT DEFAULT(bitmap_col) FROM ${aggTableName} LIMIT 1"
+ exception "Cannot find column information"
+
+ sql """ SELECT DEFAULT(hll_col) FROM ${aggTableName} LIMIT 1 """
+ exception "Cannot find column information"
+ }
+
+ // Test 3: Non-constant default value test (CURRENT_TIMESTAMP,
CURRENT_DATE)
+ sql "DROP TABLE IF EXISTS test_default_time"
+ sql """
+ CREATE TABLE test_default_time(
+ tm DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ dt DATE DEFAULT CURRENT_DATE,
+ tznn TIMESTAMPTZ(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
+ tzn TIMESTAMPTZ(6) NULL DEFAULT CURRENT_TIMESTAMP(4)
+ ) PROPERTIES( 'replication_num' = '1' );
+ """
+
+ sql """
+ INSERT INTO test_default_time (tm, tznn) VALUES
+ ('2025-10-10 12:13:14', '2025-10-10 12:13:14'),
+ ('2025-10-10 12:13:14', '2025-10-10 12:13:14');
+ """
+
+ def curTimeResult = sql """
+ SELECT
+ CAST(DEFAULT(tm) AS DATETIME(6)),
+ DEFAULT(dt),
+ CAST(DEFAULT(tznn) AS DATETIME(6)),
+ CAST(DEFAULT(tzn) AS DATETIME(4))
+ FROM test_default_time;
+ """
+ firstRow = curTimeResult[0]
+ for (int i = 0; i < firstRow.size(); i++) {
+ assertTrue(curTimeResult[1][i] == firstRow[i], "Row ${i} should equal
first row")
+ }
+ // assertTrue(curTimeResult[0][0] == curTimeResult[0][1])
+
+ // qt_non_const_defaults """
+ // SELECT DEFAULT(tm), DEFAULT(dt), DEFAULT(tznn), DEFAULT(tzn) FROM
test_default_time;
+ // """
+
+ // Test 4: NOT NULL column has no default value error test
+ sql "DROP TABLE IF EXISTS ${notNullTableName}"
+ sql """
+ CREATE TABLE ${notNullTableName} (
+ id INT NOT NULL,
+ required_col VARCHAR(50) NOT NULL,
+ optional_col VARCHAR(50) NULL
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+ sql "INSERT INTO ${notNullTableName} (id, required_col) VALUES (1, 'test')"
+ sql "INSERT INTO ${notNullTableName} (id, required_col) VALUES (2,
'test2')"
+ sql "INSERT INTO ${notNullTableName} (id, required_col) VALUES (3,
'test3')"
+
+ test {
+ sql "SELECT DEFAULT(required_col) FROM ${notNullTableName} LIMIT 1"
+ exception "has no default value and does not allow NULL or column is
auto-increment"
+ }
+
+ qt_null_column_default """
+ SELECT DEFAULT(optional_col) FROM ${notNullTableName} LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT DEFAULT(optional_col) FROM ${notNullTableName} LIMIT 1
+ """
+
+ def nullColResult = sql """
+ SELECT DEFAULT(optional_col) FROM ${notNullTableName}
+ """
+ def nullColFirstRow = nullColResult[0]
+ for (int i = 1; i < nullColResult.size(); i++) {
+ assertTrue(nullColResult[i] == nullColFirstRow, "Row ${i} should equal
first row")
+ }
+
+ // Test 5: Numeric type boundary default value test
+ def boundaryTableName = "test_default_boundary"
+ sql "DROP TABLE IF EXISTS ${boundaryTableName}"
+
+ sql """
+ CREATE TABLE ${boundaryTableName} (
+ c_tinyint_min TINYINT NULL DEFAULT -128,
+ c_tinyint_max TINYINT NULL DEFAULT 127,
+ c_smallint_min SMALLINT NULL DEFAULT -32768,
+ c_smallint_max SMALLINT NULL DEFAULT 32767,
+ c_int_min INT NULL DEFAULT -2147483648,
+ c_int_max INT NULL DEFAULT 2147483647,
+ c_bigint_min BIGINT NULL DEFAULT -9223372036854775808,
+ c_bigint_max BIGINT NULL DEFAULT 9223372036854775807,
+ c_float_zero FLOAT NULL DEFAULT 0.0,
+ c_double_zero DOUBLE NULL DEFAULT 0.0,
+ c_decimal_zero DECIMAL(10,2) NULL DEFAULT 0.00,
+ c_empty_string STRING NULL DEFAULT '',
+ c_null_default STRING NULL DEFAULT NULL
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+
+ sql "INSERT INTO ${boundaryTableName} (c_tinyint_min) VALUES (-1)"
+ sql "INSERT INTO ${boundaryTableName} (c_tinyint_min) VALUES (0)"
+ sql "INSERT INTO ${boundaryTableName} (c_tinyint_min) VALUES (1)"
+
+ qt_boundary_defaults """
+ SELECT
+ DEFAULT(c_tinyint_min),
+ DEFAULT(c_tinyint_max),
+ DEFAULT(c_smallint_min),
+ DEFAULT(c_smallint_max),
+ DEFAULT(c_int_min),
+ DEFAULT(c_int_max),
+ DEFAULT(c_bigint_min),
+ DEFAULT(c_bigint_max),
+ DEFAULT(c_float_zero),
+ DEFAULT(c_double_zero),
+ DEFAULT(c_decimal_zero),
+ DEFAULT(c_empty_string),
+ DEFAULT(c_null_default)
+ FROM ${boundaryTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_tinyint_min),
+ DEFAULT(c_tinyint_max),
+ DEFAULT(c_smallint_min),
+ DEFAULT(c_smallint_max),
+ DEFAULT(c_int_min),
+ DEFAULT(c_int_max),
+ DEFAULT(c_bigint_min),
+ DEFAULT(c_bigint_max),
+ DEFAULT(c_float_zero),
+ DEFAULT(c_double_zero),
+ DEFAULT(c_decimal_zero),
+ DEFAULT(c_empty_string),
+ DEFAULT(c_null_default)
+ FROM ${boundaryTableName}
+ LIMIT 1
+ """
+
+ def boundaryResult = sql """
+ SELECT
+ DEFAULT(c_tinyint_min),
+ DEFAULT(c_tinyint_max),
+ DEFAULT(c_smallint_min),
+ DEFAULT(c_smallint_max),
+ DEFAULT(c_int_min),
+ DEFAULT(c_int_max),
+ DEFAULT(c_bigint_min),
+ DEFAULT(c_bigint_max),
+ DEFAULT(c_float_zero),
+ DEFAULT(c_double_zero),
+ DEFAULT(c_decimal_zero),
+ DEFAULT(c_empty_string),
+ DEFAULT(c_null_default)
+ FROM ${boundaryTableName}
+ """
+ def boundaryFirstRow = boundaryResult[0]
+ for (int i = 1; i < boundaryResult.size(); i++) {
+ assertTrue(boundaryResult[i] == boundaryFirstRow, "Row ${i} should
equal first row")
+ }
+
+ // Test 6: Complex type default value test
+ def complexTableName = "test_default_complex"
+ sql "DROP TABLE IF EXISTS ${complexTableName}"
+
+ sql """
+ CREATE TABLE ${complexTableName} (
+ id INT NOT NULL,
+ c_array_empty ARRAY<INT> NULL DEFAULT '[]',
+ c_array_null ARRAY<STRING> NULL,
+ c_map_null MAP<STRING, INT> NULL,
+ c_struct_null STRUCT<id:INT,name:STRING> NULL,
+ c_json_null JSON NULL,
+ c_variant_null VARIANT NULL
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+
+ sql "INSERT INTO ${complexTableName} (id) VALUES (1)"
+ sql "INSERT INTO ${complexTableName} (id) VALUES (2)"
+ sql "INSERT INTO ${complexTableName} (id) VALUES (3)"
+
+ qt_complex_defaults """
+ SELECT
+ DEFAULT(c_array_empty),
+ DEFAULT(c_array_null),
+ DEFAULT(c_map_null),
+ DEFAULT(c_struct_null),
+ DEFAULT(c_json_null),
+ DEFAULT(c_variant_null)
+ FROM ${complexTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_array_empty),
+ DEFAULT(c_array_null),
+ DEFAULT(c_map_null),
+ DEFAULT(c_struct_null),
+ DEFAULT(c_json_null),
+ DEFAULT(c_variant_null)
+ FROM ${complexTableName}
+ LIMIT 1
+ """
+
+ def complexResult = sql """
+ SELECT
+ DEFAULT(c_array_empty),
+ DEFAULT(c_array_null),
+ DEFAULT(c_map_null),
+ DEFAULT(c_struct_null),
+ DEFAULT(c_json_null),
+ DEFAULT(c_variant_null)
+ FROM ${complexTableName}
+ """
+ def complexFirstRow = complexResult[0]
+ for (int i = 1; i < complexResult.size(); i++) {
+ assertTrue(complexResult[i] == complexFirstRow, "Row ${i} should equal
first row")
+ }
+
+ // Test 7: Error case test - illegal parameter
+ test {
+ sql "SELECT DEFAULT(123)"
+ exception "mismatched input"
+ }
+
+ test {
+ sql "SELECT DEFAULT('literal_string')"
+ exception "mismatched input"
+ }
+
+ test {
+ sql "SELECT DEFAULT(c_bool + 1) FROM ${tableName} LIMIT 1"
+ exception "missing ')' at '+'"
+ }
+
+ def baseDefault = sql """
+ SELECT DEFAULT(c_bool)
+ FROM ${tableName}
+ LIMIT 1
+ """
+ def tableAliasDefault = sql """
+ SELECT DEFAULT(t.c_bool)
+ FROM ${tableName} t
+ LIMIT 1
+ """
+ def aliasDefault = sql """
+ SELECT DEFAULT(x)
+ FROM (
+ SELECT c_bool AS x
+ FROM ${tableName}
+ ) t
+ LIMIT 1
+ """
+ def nestedAliasDefault = sql """
+ SELECT DEFAULT(x)
+ FROM (
+ SELECT x
+ FROM (
+ SELECT c_bool AS x
+ FROM ${tableName}
+ ) inner_view
+ ) outer_view
+ LIMIT 1
+ """
+ def cteAliasDefault = sql """
+ WITH cte AS (
+ SELECT c_bool AS x
+ FROM ${tableName}
+ )
+ SELECT DEFAULT(x)
+ FROM cte
+ LIMIT 1
+ """
+ assertTrue(aliasDefault == baseDefault,
+ "DEFAULT() should return the same value for aliased columns in
subqueries")
+ assertTrue(tableAliasDefault == baseDefault,
+ "DEFAULT() should return the same value when referenced through a
table alias")
+ assertTrue(nestedAliasDefault == baseDefault,
+ "DEFAULT() should return the same value for nested aliased
subqueries")
+ assertTrue(cteAliasDefault == baseDefault,
+ "DEFAULT() should return the same value when alias comes from a
CTE")
+
+ sql "SET enable_fold_constant_by_be = false;"
+ test {
+ sql "SELECT DEFAULT(c_bool, c_int) FROM ${tableName} LIMIT 1"
+ exception "missing ')' at ','"
+ }
+
+ sql "SET enable_fold_constant_by_be = true;"
+ test {
+ sql "SELECT DEFAULT(c_bool, c_int) FROM ${tableName} LIMIT 1"
+ exception "missing ')' at ','"
+ }
+ sql "SET enable_fold_constant_by_be = default;"
+
+ // Test 8: Date and time format default value test
+ def dateTimeTableName = "test_default_datetime_formats"
+ sql "DROP TABLE IF EXISTS ${dateTimeTableName}"
+
+ sql """
+ CREATE TABLE ${dateTimeTableName} (
+ c_date_std DATE NULL DEFAULT '2025-01-01',
+ c_datetime_std DATETIME NULL DEFAULT '2025-01-01 12:30:45'
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+
+ sql "INSERT INTO ${dateTimeTableName} (c_date_std) VALUES ('2024-01-01')"
+ sql "INSERT INTO ${dateTimeTableName} (c_date_std) VALUES ('2024-02-01')"
+ sql "INSERT INTO ${dateTimeTableName} (c_date_std) VALUES ('2024-03-01')"
+
+ qt_datetime_format_defaults """
+ SELECT
+ DEFAULT(c_date_std),
+ DEFAULT(c_datetime_std)
+ FROM ${dateTimeTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_date_std),
+ DEFAULT(c_datetime_std)
+ FROM ${dateTimeTableName}
+ LIMIT 1
+ """
+
+ def dateTimeResult = sql """
+ SELECT
+ DEFAULT(c_date_std),
+ DEFAULT(c_datetime_std)
+ FROM ${dateTimeTableName}
+ """
+ def dateTimeFirstRow = dateTimeResult[0]
+ for (int i = 1; i < dateTimeResult.size(); i++) {
+ assertTrue(dateTimeResult[i] == dateTimeFirstRow, "Row ${i} should
equal first row")
+ }
+
+ // Test 9: IP address type default value test
+ def ipTableName = "test_default_ip"
+ sql "DROP TABLE IF EXISTS ${ipTableName}"
+ sql """
+ CREATE TABLE ${ipTableName} (
+ c_ipv4_localhost IPV4 NULL DEFAULT '127.0.0.1',
+ c_ipv4_private IPV4 NULL DEFAULT '10.0.0.1',
+ c_ipv6_localhost IPV6 NULL DEFAULT '::1',
+ c_ipv6_example IPV6 NULL DEFAULT
'2001:db8:85a3::8a2e:370:7334'
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+
+ sql "INSERT INTO ${ipTableName} (c_ipv4_localhost) VALUES ('192.168.1.1')"
+ sql "INSERT INTO ${ipTableName} (c_ipv4_localhost) VALUES ('10.0.0.1')"
+ sql "INSERT INTO ${ipTableName} (c_ipv4_localhost) VALUES ('172.16.0.1')"
+
+ qt_ip_defaults """
+ SELECT
+ DEFAULT(c_ipv4_localhost),
+ DEFAULT(c_ipv4_private),
+ DEFAULT(c_ipv6_localhost),
+ DEFAULT(c_ipv6_example)
+ FROM ${ipTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_ipv4_localhost),
+ DEFAULT(c_ipv4_private),
+ DEFAULT(c_ipv6_localhost),
+ DEFAULT(c_ipv6_example)
+ FROM ${ipTableName}
+ LIMIT 1
+ """
+
+ def ipResult = sql """
+ SELECT
+ DEFAULT(c_ipv4_localhost),
+ DEFAULT(c_ipv4_private),
+ DEFAULT(c_ipv6_localhost),
+ DEFAULT(c_ipv6_example)
+ FROM ${ipTableName}
+ """
+ def ipFirstRow = ipResult[0]
+ for (int i = 1; i < ipResult.size(); i++) {
+ assertTrue(ipResult[i] == ipFirstRow, "Row ${i} should equal first
row")
+ }
+
+ // Test 10: String type length test
+ def stringTableName = "test_default_strings"
+ sql "DROP TABLE IF EXISTS ${stringTableName}"
+ sql """
+ CREATE TABLE ${stringTableName} (
+ c_char_fixed CHAR(10) NULL DEFAULT 'fixed',
+ c_varchar_var VARCHAR(100) NULL DEFAULT 'variable length string',
+ c_string_long STRING NULL DEFAULT 'very long string that
can be much longer than varchar',
+ c_char_empty CHAR(5) NULL DEFAULT '',
+ c_varchar_empty VARCHAR(20) NULL DEFAULT ''
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+
+ sql "INSERT INTO ${stringTableName} (c_char_fixed) VALUES ('test')"
+ sql "INSERT INTO ${stringTableName} (c_char_fixed) VALUES ('hello')"
+ sql "INSERT INTO ${stringTableName} (c_char_fixed) VALUES ('world')"
+
+ qt_string_defaults """
+ SELECT
+ DEFAULT(c_char_fixed),
+ DEFAULT(c_varchar_var),
+ DEFAULT(c_string_long),
+ DEFAULT(c_char_empty),
+ DEFAULT(c_varchar_empty)
+ FROM ${stringTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_char_fixed),
+ DEFAULT(c_varchar_var),
+ DEFAULT(c_string_long),
+ DEFAULT(c_char_empty),
+ DEFAULT(c_varchar_empty)
+ FROM ${stringTableName}
+ LIMIT 1
+ """
+
+ def stringResult = sql """
+ SELECT
+ DEFAULT(c_char_fixed),
+ DEFAULT(c_varchar_var),
+ DEFAULT(c_string_long),
+ DEFAULT(c_char_empty),
+ DEFAULT(c_varchar_empty)
+ FROM ${stringTableName}
+ """
+ def stringFirstRow = stringResult[0]
+ for (int i = 1; i < stringResult.size(); i++) {
+ assertTrue(stringResult[i] == stringFirstRow, "Row ${i} should equal
first row")
+ }
+
+ // Test11: PI and E test
+ def pieTableName = "test_default_pi_e"
+ sql "DROP TABLE IF EXISTS ${pieTableName}"
+ sql """
+ CREATE TABLE ${pieTableName} (
+ id INT NOT NULL,
+ c_pi DOUBLE NULL DEFAULT PI,
+ c_e DOUBLE NULL DEFAULT E
+ ) PROPERTIES ( 'replication_num' = '1' )
+ """
+ sql "INSERT INTO ${pieTableName} VALUES (1, NULL, NULL)"
+ sql "INSERT INTO ${pieTableName} VALUES (2, NULL, NULL)"
+ sql "INSERT INTO ${pieTableName} VALUES (3, NULL, NULL)"
+ qt_pi_e_defaults """
+ SELECT
+ DEFAULT(c_pi),
+ DEFAULT(c_e)
+ FROM ${pieTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_pi),
+ DEFAULT(c_e)
+ FROM ${pieTableName}
+ LIMIT 1
+ """
+
+ def pieResult = sql """
+ SELECT
+ DEFAULT(c_pi),
+ DEFAULT(c_e)
+ FROM ${pieTableName}
+ """
+ def pieFirstRow = pieResult[0]
+ for (int i = 1; i < pieResult.size(); i++) {
+ assertTrue(pieResult[i] == pieFirstRow, "Row ${i} should equal first
row")
+ }
+
+ // Test 12: Empty table test
+ def emptyTableName = "test_default_empty_table"
+ sql "DROP TABLE IF EXISTS ${emptyTableName}"
+ sql """
+ CREATE TABLE ${emptyTableName} (
+ c_int INT NULL DEFAULT 100,
+ c_string STRING NULL DEFAULT 'empty table test'
+ ) PROPERTIES ( 'replication_num' = '1' );
+ """
+
+ qt_empty_table_defaults """
+ SELECT
+ DEFAULT(c_int),
+ DEFAULT(c_string)
+ FROM ${emptyTableName}
+ LIMIT 1
+ """
+
+ testConstantFoldingConsistency """
+ SELECT
+ DEFAULT(c_int),
+ DEFAULT(c_string)
+ FROM ${emptyTableName}
+ LIMIT 1
+ """
+
+ sql "INSERT INTO ${emptyTableName} (c_int) VALUES (1)"
+ sql "INSERT INTO ${emptyTableName} (c_int) VALUES (2)"
+ sql "INSERT INTO ${emptyTableName} (c_int) VALUES (3)"
+
+ def emptyResult = sql """
+ SELECT
+ DEFAULT(c_int),
+ DEFAULT(c_string)
+ FROM ${emptyTableName}
+ """
+ def emptyFirstRow = emptyResult[0]
+ for (int i = 1; i < emptyResult.size(); i++) {
+ assertTrue(emptyResult[i] == emptyFirstRow, "Row ${i} should equal
first row")
+ }
+
+ // Test 13: Same col_name in different tables
+ def tableA = "test_default_table_a"
+ def tableB = "test_default_table_b"
+ sql "DROP TABLE IF EXISTS ${tableA}"
+ sql "DROP TABLE IF EXISTS ${tableB}"
+ sql """
+ CREATE TABLE ${tableA} (
+ id INT NOT NULL DEFAULT '1',
+ val VARCHAR(20) NOT NULL DEFAULT 'hello',
+ dt DATE NOT NULL DEFAULT '2026-01-13'
+ ) PROPERTIES ('replication_num' = '1' )
+ """
+ sql """
+ CREATE TABLE ${tableB} (
+ id BIGINT NOT NULL DEFAULT '1',
+ val DOUBLE NOT NULL DEFAULT PI,
+ dt DATETIME NOT NULL DEFAULT '2023-12-31 23:59:59'
+ ) PROPERTIES ('replication_num' = '1' )
+ """
+ sql "INSERT INTO ${tableA}(id) VALUES (1), (2), (3);"
+ sql "INSERT INTO ${tableB}(id) VALUES (1), (2), (3);"
+ qt_same_col_name """SELECT
+ DEFAULT(a.val), DEFAULT(a.dt),
+ DEFAULT(b.val), DEFAULT(b.dt)
+ FROM ${tableA} AS a
+ JOIN ${tableB} AS b
+ ON a.id = b.id;"""
+
+ testConstantFoldingConsistency """SELECT
+ DEFAULT(a.val), DEFAULT(a.dt),
+ DEFAULT(b.val), DEFAULT(b.dt)
+ FROM ${tableA} AS a
+ JOIN ${tableB} AS b
+ ON a.id = b.id;"""
+
+ // aotu-increment column
+ sql """ DROP TABLE IF EXISTS test_auto_inc """
+ sql """
+ CREATE TABLE test_auto_inc (
+ id BIGINT NOT NULL AUTO_INCREMENT,
+ value BIGINT NOT NULL
+ ) PROPERTIES ('replication_num' = '1' );
+ """
+ sql """ INSERT INTO test_auto_inc(value) VALUES (1); """
+ test {
+ sql """ SELECT DEFAULT(id) FROM test_auto_inc; """
+ exception "has no default value and does not allow NULL or column is
auto-increment"
+ }
+
+ // generate column
+ sql """ DROP TABLE IF EXISTS test_gen_col """
+ sql """
+ CREATE TABLE test_gen_col (
+ a INT,
+ b INT AS (a + 10)
+ ) PROPERTIES ('replication_num' = '1' );
+ """
+ sql """ INSERT INTO test_gen_col(a) VALUES (1); """
+ test {
+ sql """ SELECT DEFAULT(b) FROM test_gen_col; """
+ exception "DEFAULT cannot be used on generated column"
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]