This is an automated email from the ASF dual-hosted git repository.
CalvinKirs 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 d07e97bbb62 [fix](generated column) Preserve generated column sessions
in CREATE TABLE LIKE (#67809)
d07e97bbb62 is described below
commit d07e97bbb6293bd1d9e729e86537c0de2eb489b4
Author: feiniaofeiafei <[email protected]>
AuthorDate: Fri Sep 18 17:12:15 2026 +0800
[fix](generated column) Preserve generated column sessions in CREATE TABLE
LIKE (#67809)
### What problem does this PR solve?
Problem Summary:
CREATE TABLE LIKE reconstructs generated columns from SQL using the
caller's session settings, losing the expression settings saved in the
source columns. For a generated expression `a * b` over `DECIMAL(20,5)`
and `DECIMAL(21,6)`, a source created with `enable_decimal256=true`
produces `1.26212529751`, but a clone created with the option disabled
produces `1.26212530000` for the same input. SQL mode also affects
parsing: a source expression `a || 'x'` created with `PIPES_AS_CONCAT`
produces `ax`, while its clone can produce NULL under a different SQL
mode.
Snapshot each generated column's session settings under the source
table's read lock and carry them through `GeneratedColumnDesc`. Restore
these settings temporarily when parsing and analyzing the cloned
expression, then persist them in the new `Column`. The caller's session
is restored after analysis, including on exceptions. Ordinary CREATE
TABLE retains its existing session behavior.
Existing incorrectly created clones and stored data are not
automatically repaired.
### Release note
Fix CREATE TABLE LIKE changing generated column results when the
caller's expression-related session settings differ from the source
table's settings.
### Check List (For Author)
- Test
- [x] Regression test
- Passed `test_generated_column_like_session`, `test_generated_column`,
and `test_generated_column_fault_tolerance_nereids` on the final
branch's FE.
- New coverage includes both decimal256 setting directions, repeated
LIKE, SQL mode, NULL values, and preservation of the caller's session.
Expected output was generated by `run-regression-test.sh` and verified
in subsequent runs.
- [x] Unit Test
- All 11 `CreateTableLikeTest` tests passed via `run-fe-ut.sh` on the
initial validation baseline with the same repair and test files.
- The final upstream baseline has an unrelated test-compilation error in
`IvmNormalizeMTMVJoinTest` (an outdated `IvmRewriteContext` constructor
call). Final FE packaging therefore used `DISABLE_BUILD_UI=ON
MVN_OPT=-Dmaven.test.skip=true ./build.sh --fe`. No unrelated test code
was changed. Checkstyle passed.
- [x] Manual test (add detailed scripts or steps below)
- Reproduced both precision and SQL mode differences before replacing FE
libraries; verified correct results after replacement.
- Restarted the final FE and cloned previously created fixed tables
again, verifying persisted session settings and unchanged caller
settings.
- The test FE used `be_exec_version=13` to match its existing BE.
- [ ] No need to test or manual test. Explain why:
- Behavior changed:
- [ ] No.
- [x] Yes. Generated columns created through LIKE preserve the source
columns' expression semantics.
---
.../main/java/org/apache/doris/catalog/Column.java | 8 +-
.../main/java/org/apache/doris/catalog/Env.java | 2 +-
.../plans/commands/CreateTableLikeCommand.java | 22 ++++
.../plans/commands/info/ColumnDefinition.java | 12 ++-
.../trees/plans/commands/info/CreateTableInfo.java | 40 ++++----
.../plans/commands/info/GeneratedColumnDesc.java | 21 +++-
.../apache/doris/catalog/CreateTableLikeTest.java | 112 +++++++++++++++++++++
.../test_generated_column_like_session.out | 25 +++++
.../test_generated_column_like_session.groovy | 83 +++++++++++++++
9 files changed, 300 insertions(+), 25 deletions(-)
diff --git a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
index e7a22663d48..eefee5b729c 100644
--- a/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-catalog/src/main/java/org/apache/doris/catalog/Column.java
@@ -884,6 +884,11 @@ public class Column implements GsonPostProcessable {
}
public String toSql(boolean isUniqueTable, boolean isCompatible) {
+ return toSql(isUniqueTable, isCompatible, false);
+ }
+
+ /** Use a placeholder only for internal CREATE TABLE LIKE parsing; restore
the expression before analysis. */
+ public String toSql(boolean isUniqueTable, boolean isCompatible, boolean
useGeneratedColumnPlaceholder) {
StringBuilder sb = new StringBuilder();
sb.append("`").append(name).append("` ");
String typeStr = type.toSql();
@@ -899,7 +904,8 @@ public class Column implements GsonPostProcessable {
sb.append(" ").append(aggregationType.toSql());
}
if (generatedColumnInfo != null) {
- sb.append(" AS
(").append(generatedColumnInfo.getExprSql()).append(")");
+ sb.append(" AS (").append(useGeneratedColumnPlaceholder ? "NULL" :
generatedColumnInfo.getExprSql())
+ .append(")");
}
if (isAllowNull) {
sb.append(" NULL");
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index c8a6210415d..63c3bf15ec3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -4338,7 +4338,7 @@ public class Env {
// sqlalchemy requires this to parse SHOW CREATE TABLE stmt.
if (table.isManagedTable()) {
sb.append(" ").append(
- column.toSql(((OlapTable) table).getKeysType() ==
KeysType.UNIQUE_KEYS, true));
+ column.toSql(((OlapTable) table).getKeysType() ==
KeysType.UNIQUE_KEYS, true, true));
} else {
sb.append(" ").append(column.toSql());
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateTableLikeCommand.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateTableLikeCommand.java
index d8dda48d19b..f17a8df0a91 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateTableLikeCommand.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/CreateTableLikeCommand.java
@@ -18,6 +18,7 @@
package org.apache.doris.nereids.trees.plans.commands;
import org.apache.doris.analysis.StmtType;
+import org.apache.doris.catalog.Column;
import org.apache.doris.catalog.DatabaseIf;
import org.apache.doris.catalog.Env;
import org.apache.doris.catalog.OlapTable;
@@ -28,8 +29,10 @@ import org.apache.doris.common.ErrorReport;
import org.apache.doris.common.UserException;
import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.trees.plans.PlanType;
+import org.apache.doris.nereids.trees.plans.commands.info.ColumnDefinition;
import org.apache.doris.nereids.trees.plans.commands.info.CreateTableInfo;
import org.apache.doris.nereids.trees.plans.commands.info.CreateTableLikeInfo;
+import org.apache.doris.nereids.trees.plans.commands.info.GeneratedColumnDesc;
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.StmtExecutor;
@@ -37,7 +40,10 @@ import org.apache.doris.qe.StmtExecutor;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
/** CreateTableLikeCommand */
public class CreateTableLikeCommand extends Command implements ForwardWithSync
{
@@ -76,6 +82,7 @@ public class CreateTableLikeCommand extends Command
implements ForwardWithSync {
}
List<String> createTableStmt = Lists.newArrayList();
+ Map<String, GeneratedColumnDesc> generatedColumns = new
HashMap<>();
table.readLock();
try {
if (table.isManagedTable()) {
@@ -93,6 +100,16 @@ public class CreateTableLikeCommand extends Command
implements ForwardWithSync {
throw new DdlException("Table[" + table.getName() + "] is
external, not support rollup copy");
}
+ for (Column column : table.getBaseSchema()) {
+ if (column.isGeneratedColumn()) {
+ GeneratedColumnDesc desc = new GeneratedColumnDesc(
+ column.getGeneratedColumnInfo().getExprSql());
+ desc.setSessionVariables(
+
Optional.ofNullable(column.getSessionVariables()).map(HashMap::new).orElse(null));
+ generatedColumns.put(column.getName(), desc);
+ }
+ }
+
Env.getCreateTableLikeStmt(createTableLikeInfo,
createTableLikeInfo.getDbName(), table, createTableStmt,
null, null, false, false, true, -1L,
false, false);
@@ -115,6 +132,11 @@ public class CreateTableLikeCommand extends Command
implements ForwardWithSync {
createTableCommand = new
CreateTableCommand(createTableCommand.getCtasQuery(),
createTableInfo.withTableNameAndIfNotExists(createTableLikeInfo.getTableName(),
createTableLikeInfo.isIfNotExists()));
+ for (ColumnDefinition column :
createTableInfo.getColumnDefinitions()) {
+ // The synthetic DDL contains AS (NULL); restore the
source before any analysis.
+ column.getGeneratedColumnDesc().ifPresent(desc ->
+
column.setGeneratedColumnDesc(generatedColumns.get(column.getName())));
+ }
createTableCommand.run(ctx, executor);
} finally {
ctx.setSkipAuth(false);
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
index 4ccc685539a..f10d9c517a0 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
@@ -631,8 +631,8 @@ public class ColumnDefinition {
onUpdateDefaultValue.map(DefaultValue::getDefaultValueExprDef).orElse(null),
clusterKeyId,
generatedColumnDesc.map(GeneratedColumnDesc::translateToInfo).orElse(null),
generatedColumnsThatReferToThis,
- generatedColumnDesc.map(desc ->
-
ConnectContextUtil.getAffectQueryResultInPlanVariables(ConnectContext.get()))
+ generatedColumnDesc.map(desc ->
desc.getSessionVariables().orElseGet(() ->
+
ConnectContextUtil.getAffectQueryResultInPlanVariables(ConnectContext.get())))
.orElse(null)
);
column.setAggregationTypeImplicit(aggTypeImplicit);
@@ -650,8 +650,8 @@ public class ColumnDefinition {
onUpdateDefaultValue.map(DefaultValue::getDefaultValueExprDef).orElse(null),
clusterKeyId,
generatedColumnDesc.map(GeneratedColumnDesc::translateToInfo).orElse(null),
generatedColumnsThatReferToThis,
- generatedColumnDesc.map(desc ->
-
ConnectContextUtil.getAffectQueryResultInPlanVariables(ConnectContext.get()))
+ generatedColumnDesc.map(desc ->
desc.getSessionVariables().orElseGet(() ->
+
ConnectContextUtil.getAffectQueryResultInPlanVariables(ConnectContext.get())))
.orElse(null));
column.setNullableSpecified(nullableSpecified);
column.setCommentSpecified(commentSpecified);
@@ -773,6 +773,10 @@ public class ColumnDefinition {
return generatedColumnDesc;
}
+ public void setGeneratedColumnDesc(GeneratedColumnDesc
generatedColumnDesc) {
+ this.generatedColumnDesc = Optional.of(generatedColumnDesc);
+ }
+
public long getAutoIncInitValue() {
return autoIncInitValue;
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
index 6c5e728e84f..8307f965bf8 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
@@ -80,6 +80,7 @@ import org.apache.doris.nereids.types.VariantField;
import org.apache.doris.nereids.types.VariantType;
import org.apache.doris.nereids.util.TypeCoercionUtils;
import org.apache.doris.nereids.util.Utils;
+import org.apache.doris.qe.AutoCloseSessionVariable;
import org.apache.doris.qe.ConnectContext;
import org.apache.doris.qe.SessionVariable;
import org.apache.doris.thrift.TInvertedIndexFileStorageFormat;
@@ -1140,24 +1141,27 @@ public class CreateTableInfo {
if (!info.isPresent()) {
continue;
}
- Expression parsedExpression = info.get().getExpression();
- checkParsedExpressionInGeneratedColumn(parsedExpression);
- Expression boundSlotExpression =
SlotReplacer.INSTANCE.replace(parsedExpression, columnToSlotReference);
- Scope scope = new Scope(slots);
- ExpressionAnalyzer analyzer = new ExpressionAnalyzer(null, scope,
cascadesContext, false, false);
- Expression expr;
- try {
- expr = analyzer.analyze(boundSlotExpression, new
ExpressionRewriteContext(cascadesContext));
- } catch (AnalysisException e) {
- throw new AnalysisException("In generated column '" +
column.getName() + "', "
- + Utils.convertFirstChar(e.getMessage()));
- }
- checkExpressionInGeneratedColumn(expr, column,
nameToColumnDefinition);
- TypeCoercionUtils.checkCanCastTo(expr.getDataType(),
column.getType());
- ExpressionToExpr translator = new ExpressionToExpr(i,
translateMap);
- Expr e = expr.accept(translator, planTranslatorContext);
- info.get().setExpr(e);
- exprAndNames.add(new ExprAndName(e.clone(), column.getName()));
+ try (AutoCloseSessionVariable autoClose = new
AutoCloseSessionVariable(ctx,
+ info.get().getSessionVariables().orElse(null))) {
+ Expression parsedExpression = info.get().getExpression();
+ checkParsedExpressionInGeneratedColumn(parsedExpression);
+ Expression boundSlotExpression =
SlotReplacer.INSTANCE.replace(parsedExpression, columnToSlotReference);
+ Scope scope = new Scope(slots);
+ ExpressionAnalyzer analyzer = new ExpressionAnalyzer(null,
scope, cascadesContext, false, false);
+ Expression expr;
+ try {
+ expr = analyzer.analyze(boundSlotExpression, new
ExpressionRewriteContext(cascadesContext));
+ } catch (AnalysisException e) {
+ throw new AnalysisException("In generated column '" +
column.getName() + "', "
+ + Utils.convertFirstChar(e.getMessage()));
+ }
+ checkExpressionInGeneratedColumn(expr, column,
nameToColumnDefinition);
+ TypeCoercionUtils.checkCanCastTo(expr.getDataType(),
column.getType());
+ ExpressionToExpr translator = new ExpressionToExpr(i,
translateMap);
+ Expr e = expr.accept(translator, planTranslatorContext);
+ info.get().setExpr(e);
+ exprAndNames.add(new ExprAndName(e.clone(), column.getName()));
+ }
}
// for alter drop column
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/GeneratedColumnDesc.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/GeneratedColumnDesc.java
index 5639859bbd7..7b75e0cc00c 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/GeneratedColumnDesc.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/GeneratedColumnDesc.java
@@ -19,8 +19,12 @@ package org.apache.doris.nereids.trees.plans.commands.info;
import org.apache.doris.analysis.Expr;
import org.apache.doris.catalog.GeneratedColumnInfo;
+import org.apache.doris.nereids.parser.NereidsParser;
import org.apache.doris.nereids.trees.expressions.Expression;
+import java.util.Map;
+import java.util.Optional;
+
/**GeneratedColumnDesc for nereids*/
public class GeneratedColumnDesc {
/**GeneratedColumnType*/
@@ -33,6 +37,7 @@ public class GeneratedColumnDesc {
private final String exprSql;
private Expr expr;
private final Expression expression;
+ private Optional<Map<String, String>> sessionVariables = Optional.empty();
/** constructor */
public GeneratedColumnDesc(String exprSql, Expression expression) {
@@ -41,6 +46,11 @@ public class GeneratedColumnDesc {
this.type = GeneratedColumnType.STORED;
}
+ /** Defer parsing a copied expression until the source column's session
settings are active. */
+ public GeneratedColumnDesc(String exprSql) {
+ this(exprSql, null);
+ }
+
public Expr getExpr() {
return expr;
}
@@ -50,7 +60,16 @@ public class GeneratedColumnDesc {
}
public Expression getExpression() {
- return expression;
+ // CREATE TABLE LIKE must also parse the expression under its original
session settings.
+ return expression == null ? new
NereidsParser().parseExpression(exprSql) : expression;
+ }
+
+ public void setSessionVariables(Map<String, String> sessionVariables) {
+ this.sessionVariables = Optional.ofNullable(sessionVariables);
+ }
+
+ public Optional<Map<String, String>> getSessionVariables() {
+ return sessionVariables;
}
public GeneratedColumnInfo translateToInfo() {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
index 15c2fa5e30e..9080e514d13 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/CreateTableLikeTest.java
@@ -17,11 +17,17 @@
package org.apache.doris.catalog;
+import org.apache.doris.analysis.ExprToSqlVisitor;
+import org.apache.doris.analysis.ToSqlParams;
import org.apache.doris.common.DdlException;
import org.apache.doris.common.ExceptionChecker;
import org.apache.doris.common.FeConstants;
import org.apache.doris.nereids.parser.NereidsParser;
+import org.apache.doris.nereids.trees.plans.commands.CreateTableCommand;
import org.apache.doris.nereids.trees.plans.commands.CreateTableLikeCommand;
+import org.apache.doris.nereids.trees.plans.commands.info.GeneratedColumnDesc;
+import org.apache.doris.qe.SessionVariable;
+import org.apache.doris.qe.SqlModeHelper;
import org.apache.doris.qe.StmtExecutor;
import org.apache.doris.utframe.TestWithFeService;
@@ -49,6 +55,112 @@ public class CreateTableLikeTest extends TestWithFeService {
createDatabase("test2");
}
+ @Test
+ public void testGeneratedColumnSessionVariables() throws Exception {
+ SessionVariable original = connectContext.getSessionVariable();
+ boolean originalDecimal256 = original.enableDecimal256;
+ try {
+ for (boolean decimal256 : new boolean[] {true, false}) {
+ String sourceName = "generated_session_src_" + decimal256;
+ String targetName = "generated_session_dst_" + decimal256;
+ original.enableDecimal256 = decimal256;
+ createTable("CREATE TABLE test." + sourceName + " ("
+ + "a DECIMAL(20,5), b DECIMAL(21,6), "
+ + "c DECIMAL(38,11) GENERATED ALWAYS AS (a * b) NOT
NULL) "
+ + "DISTRIBUTED BY HASH(a) BUCKETS 1
PROPERTIES(\"replication_num\"=\"1\")");
+ original.enableDecimal256 = !decimal256;
+ createTableLike("CREATE TABLE test." + targetName + " LIKE
test." + sourceName);
+
+ Database db =
Env.getCurrentInternalCatalog().getDbOrDdlException("test");
+ Column source =
db.getTableOrDdlException(sourceName).getColumn("c");
+ Column target =
db.getTableOrDdlException(targetName).getColumn("c");
+ Assertions.assertEquals(source.getSessionVariables(),
target.getSessionVariables());
+
Assertions.assertEquals(source.getGeneratedColumnInfo().getExpr().getType(),
+ target.getGeneratedColumnInfo().getExpr().getType());
+
Assertions.assertEquals(source.getGeneratedColumnInfo().getExpr()
+ .accept(ExprToSqlVisitor.INSTANCE,
ToSqlParams.WITHOUT_TABLE),
+ target.getGeneratedColumnInfo().getExpr()
+ .accept(ExprToSqlVisitor.INSTANCE,
ToSqlParams.WITHOUT_TABLE));
+ Assertions.assertSame(original,
connectContext.getSessionVariable());
+ Assertions.assertEquals(!decimal256,
original.enableDecimal256);
+ }
+ } finally {
+ original.enableDecimal256 = originalDecimal256;
+ }
+ }
+
+ @Test
+ public void testGeneratedColumnLikeBackslashModes() throws Exception {
+ SessionVariable original = connectContext.getSessionVariable();
+ long originalSqlMode = original.getSqlMode();
+ try {
+ for (boolean noBackslashEscapes : new boolean[] {true, false}) {
+ String sourceName = "generated_backslash_src_" +
noBackslashEscapes;
+ long sourceMode = noBackslashEscapes ?
SqlModeHelper.MODE_NO_BACKSLASH_ESCAPES : 0;
+ long callerMode = noBackslashEscapes ? 0 :
SqlModeHelper.MODE_NO_BACKSLASH_ESCAPES;
+ String expression = noBackslashEscapes ? "concat(a, 'C:\\')" :
"concat(a, 'C:\\\\')";
+ original.setSqlMode(sourceMode);
+ createTable("CREATE TABLE test." + sourceName + " ("
+ + "a VARCHAR(10), c VARCHAR(30) AS (" + expression +
"), "
+ + "d VARCHAR(40) AS (concat(c, 'x'))) "
+ + "DISTRIBUTED BY HASH(a) BUCKETS 1
PROPERTIES(\"replication_num\"=\"1\")");
+ Database db =
Env.getCurrentInternalCatalog().getDbOrDdlException("test");
+ Table source = db.getTableOrDdlException(sourceName);
+ String sourceDdl = getCreateTableStmt(source);
+ original.setSqlMode(callerMode);
+ String previousName = sourceName;
+ for (int copy = 0; copy < 2; copy++) {
+ String targetName = sourceName + "_copy_" + copy;
+ createTableLike("CREATE TABLE test." + targetName + " LIKE
test." + previousName);
+ Table target = db.getTableOrDdlException(targetName);
+ for (String columnName : new String[] {"c", "d"}) {
+ Column sourceColumn = source.getColumn(columnName);
+ Column targetColumn = target.getColumn(columnName);
+
Assertions.assertEquals(sourceColumn.getSessionVariables(),
targetColumn.getSessionVariables());
+
Assertions.assertEquals(sourceColumn.getGeneratedColumnInfo().getExprSql(),
+
targetColumn.getGeneratedColumnInfo().getExprSql());
+
Assertions.assertEquals(sourceColumn.getGeneratedColumnInfo().getExpr()
+ .accept(ExprToSqlVisitor.INSTANCE,
ToSqlParams.WITHOUT_TABLE),
+ targetColumn.getGeneratedColumnInfo().getExpr()
+ .accept(ExprToSqlVisitor.INSTANCE,
ToSqlParams.WITHOUT_TABLE));
+ }
+ Assertions.assertSame(original,
connectContext.getSessionVariable());
+ Assertions.assertEquals(callerMode, original.getSqlMode());
+ Assertions.assertEquals(sourceDdl,
getCreateTableStmt(source));
+ Assertions.assertEquals(sourceDdl.replace(sourceName,
targetName), getCreateTableStmt(target));
+ previousName = targetName;
+ }
+ }
+ } finally {
+ original.setSqlMode(originalSqlMode);
+ }
+ }
+
+ @Test
+ public void testDeferredGeneratedColumnRestoresSessionOnFailure() throws
Exception {
+ SessionVariable original = connectContext.getSessionVariable();
+ long originalSqlMode = original.getSqlMode();
+ try {
+ original.setSqlMode(SqlModeHelper.MODE_NO_BACKSLASH_ESCAPES);
+ GeneratedColumnDesc desc = new
GeneratedColumnDesc("missing_generated_function(a, 'C:\\')");
+
desc.setSessionVariables(original.getAffectQueryResultInPlanVariables());
+ original.setSqlMode(0);
+ String sql = "CREATE TABLE test.generated_deferred_failure (a
VARCHAR(10), c VARCHAR(30) AS (NULL)) "
+ + "DISTRIBUTED BY HASH(a) BUCKETS 1
PROPERTIES(\"replication_num\"=\"1\")";
+ CreateTableCommand command = (CreateTableCommand) new
NereidsParser().parseSingle(sql);
+
command.getCreateTableInfo().getColumnDefinitions().get(1).setGeneratedColumnDesc(desc);
+ Exception failure = Assertions.assertThrows(Exception.class,
+ () -> command.run(connectContext, new
StmtExecutor(connectContext, sql)));
+
Assertions.assertTrue(failure.getMessage().contains("missing_generated_function"));
+ Assertions.assertSame(original,
connectContext.getSessionVariable());
+ Assertions.assertEquals(0, original.getSqlMode());
+
Assertions.assertNull(Env.getCurrentInternalCatalog().getDbOrDdlException("test")
+ .getTableNullable("generated_deferred_failure"));
+ } finally {
+ original.setSqlMode(originalSqlMode);
+ }
+ }
+
private void createTableLike(String sql) throws Exception {
NereidsParser nereidsParser = new NereidsParser();
CreateTableLikeCommand command = (CreateTableLikeCommand)
nereidsParser.parseSingle(sql);
diff --git
a/regression-test/data/ddl_p0/test_create_table_generated_column/test_generated_column_like_session.out
b/regression-test/data/ddl_p0/test_create_table_generated_column/test_generated_column_like_session.out
new file mode 100644
index 00000000000..1e68fd30be0
--- /dev/null
+++
b/regression-test/data/ddl_p0/test_create_table_generated_column/test_generated_column_like_session.out
@@ -0,0 +1,25 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !session_after_like --
+false
+
+-- !decimal_true --
+copy 1.12343 1.123457 1.26212529751
+dst 1.12343 1.123457 1.26212529751
+src 1.12343 1.123457 1.26212529751
+
+-- !session_after_reverse_like --
+true
+
+-- !decimal_false --
+dst 1.12343 1.123457 1.26212530000
+src 1.12343 1.123457 1.26212530000
+
+-- !sql_mode_after_like --
+
+
+-- !sql_mode --
+dst \N \N
+dst a ax
+src \N \N
+src a ax
+
diff --git
a/regression-test/suites/ddl_p0/test_create_table_generated_column/test_generated_column_like_session.groovy
b/regression-test/suites/ddl_p0/test_create_table_generated_column/test_generated_column_like_session.groovy
new file mode 100644
index 00000000000..7d96b0c2491
--- /dev/null
+++
b/regression-test/suites/ddl_p0/test_create_table_generated_column/test_generated_column_like_session.groovy
@@ -0,0 +1,83 @@
+// 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_generated_column_like_session") {
+ sql "DROP TABLE IF EXISTS test_gencol_like_decimal_src"
+ sql "DROP TABLE IF EXISTS test_gencol_like_decimal_dst"
+ sql "DROP TABLE IF EXISTS test_gencol_like_decimal_copy"
+ sql "SET enable_decimal256 = true"
+ sql """
+ CREATE TABLE test_gencol_like_decimal_src (
+ a DECIMAL(20,5), b DECIMAL(21,6),
+ c DECIMAL(38,11) GENERATED ALWAYS AS (a * b) NOT NULL
+ )
+ DISTRIBUTED BY HASH(a) BUCKETS 1
+ PROPERTIES("replication_num" = "1")
+ """
+ sql "SET enable_decimal256 = false"
+ sql "CREATE TABLE test_gencol_like_decimal_dst LIKE
test_gencol_like_decimal_src"
+ qt_session_after_like "SELECT @@enable_decimal256"
+ sql "CREATE TABLE test_gencol_like_decimal_copy LIKE
test_gencol_like_decimal_dst"
+ sql "INSERT INTO test_gencol_like_decimal_src VALUES (1.12343, 1.123457,
DEFAULT)"
+ sql "INSERT INTO test_gencol_like_decimal_dst VALUES (1.12343, 1.123457,
DEFAULT)"
+ sql "INSERT INTO test_gencol_like_decimal_copy VALUES (1.12343, 1.123457,
DEFAULT)"
+ order_qt_decimal_true """
+ SELECT 'src', a, b, c FROM test_gencol_like_decimal_src
+ UNION ALL SELECT 'dst', a, b, c FROM test_gencol_like_decimal_dst
+ UNION ALL SELECT 'copy', a, b, c FROM test_gencol_like_decimal_copy
+ """
+
+ sql "DROP TABLE IF EXISTS test_gencol_like_decimal_false_src"
+ sql "DROP TABLE IF EXISTS test_gencol_like_decimal_false_dst"
+ sql """
+ CREATE TABLE test_gencol_like_decimal_false_src (
+ a DECIMAL(20,5), b DECIMAL(21,6),
+ c DECIMAL(38,11) GENERATED ALWAYS AS (a * b) NOT NULL
+ )
+ DISTRIBUTED BY HASH(a) BUCKETS 1
+ PROPERTIES("replication_num" = "1")
+ """
+ sql "SET enable_decimal256 = true"
+ sql "CREATE TABLE test_gencol_like_decimal_false_dst LIKE
test_gencol_like_decimal_false_src"
+ qt_session_after_reverse_like "SELECT @@enable_decimal256"
+ sql "INSERT INTO test_gencol_like_decimal_false_src VALUES (1.12343,
1.123457, DEFAULT)"
+ sql "INSERT INTO test_gencol_like_decimal_false_dst VALUES (1.12343,
1.123457, DEFAULT)"
+ order_qt_decimal_false """
+ SELECT 'src', a, b, c FROM test_gencol_like_decimal_false_src
+ UNION ALL SELECT 'dst', a, b, c FROM test_gencol_like_decimal_false_dst
+ """
+
+ sql "DROP TABLE IF EXISTS test_gencol_like_sql_mode_src"
+ sql "DROP TABLE IF EXISTS test_gencol_like_sql_mode_dst"
+ sql "SET sql_mode = 'PIPES_AS_CONCAT'"
+ sql """
+ CREATE TABLE test_gencol_like_sql_mode_src (
+ a VARCHAR(10), c VARCHAR(20) GENERATED ALWAYS AS (a || 'x')
+ )
+ DISTRIBUTED BY HASH(a) BUCKETS 1
+ PROPERTIES("replication_num" = "1")
+ """
+ sql "SET sql_mode = ''"
+ sql "CREATE TABLE test_gencol_like_sql_mode_dst LIKE
test_gencol_like_sql_mode_src"
+ qt_sql_mode_after_like "SELECT @@sql_mode"
+ sql "INSERT INTO test_gencol_like_sql_mode_src VALUES ('a', DEFAULT),
(NULL, DEFAULT)"
+ sql "INSERT INTO test_gencol_like_sql_mode_dst VALUES ('a', DEFAULT),
(NULL, DEFAULT)"
+ order_qt_sql_mode """
+ SELECT 'src', a, c FROM test_gencol_like_sql_mode_src
+ UNION ALL SELECT 'dst', a, c FROM test_gencol_like_sql_mode_dst
+ """
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]