Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion pkg/planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -975,11 +975,18 @@ func (b *PlanBuilder) buildSelection(ctx context.Context, p base.LogicalPlan, wh
}
cnfExpres := make([]expression.Expression, 0)
useCache := b.ctx.GetSessionVars().StmtCtx.UseCache()
foldEvalCtx := b.ctx.GetExprCtx().GetEvalCtx()
if b.ignoreTruncateErrForViewPredicateFolding {
// View definitions are built as SELECTs even when they are expanded inside
// an outer DML statement, so only that planner-time predicate folding path
// should ignore truncate errors like `WHERE ''`.
foldEvalCtx = exprctx.CtxWithHandleTruncateErrLevel(b.ctx.GetExprCtx(), errctx.LevelIgnore).GetEvalCtx()
}
for _, expr := range expressions {
cnfItems := expression.SplitCNFItems(expr)
for _, item := range cnfItems {
if con, ok := item.(*expression.Constant); ok && expression.ConstExprConsiderPlanCache(con, useCache) {
ret, _, err := expression.EvalBool(b.ctx.GetExprCtx().GetEvalCtx(), expression.CNFExprs{con}, chunk.Row{})
ret, _, err := expression.EvalBool(foldEvalCtx, expression.CNFExprs{con}, chunk.Row{})
if err != nil {
return nil, errors.Trace(err)
}
Expand Down Expand Up @@ -5185,6 +5192,13 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName ast.CI
b.hintState = originHintState
b.ctx.GetSessionVars().PlannerSelectBlockAsName.Store(originPlannerSelectBlockAsName)
}()
// Only relax truncate handling while folding constant predicates in this
// view expansion. Keep the outer statement semantics unchanged.
originIgnoreTruncateErrForViewPredicateFolding := b.ignoreTruncateErrForViewPredicateFolding
b.ignoreTruncateErrForViewPredicateFolding = true
defer func() {
b.ignoreTruncateErrForViewPredicateFolding = originIgnoreTruncateErrForViewPredicateFolding
}()
nodeW := resolve.NewNodeWWithCtx(selectNode, b.resolveCtx)
selectLogicalPlan, err := b.Build(ctx, nodeW)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions pkg/planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@ type PlanBuilder struct {
partitionedTable []table.PartitionedTable
// buildingViewStack is used to check whether there is a recursive view.
buildingViewStack set.StringSet
// ignoreTruncateErrForViewPredicateFolding narrows truncate relaxation to
// constant predicate folding while expanding a view.
ignoreTruncateErrForViewPredicateFolding bool
// renamingViewName is the name of the view which is being renamed.
renamingViewName string
// isCreateView indicates whether the query is create view.
Expand Down
12 changes: 12 additions & 0 deletions tests/integrationtest/r/executor/insert.result
Original file line number Diff line number Diff line change
Expand Up @@ -2443,3 +2443,15 @@ ts
DROP TABLE t;
SET @@time_zone = @old_time_zone;
SET @@sql_mode = @old_sql_mode;
SET @old_sql_mode_65832 = @@sql_mode;
SET sql_mode = 'STRICT_TRANS_TABLES';
CREATE TABLE t_65832_0(c0 BLOB(304));
CREATE TABLE t_65832_1(c0 CHAR DEFAULT '0');
CREATE VIEW v_65832(c0) AS SELECT 0.9699394901011086 FROM t_65832_0 INNER JOIN t_65832_0 AS t0_alias ON t_65832_0.c0 WHERE '';
INSERT INTO t_65832_1 VALUES ('v') ON DUPLICATE KEY UPDATE c0=(SELECT true FROM v_65832 CROSS JOIN t_65832_0 ON (true));
SELECT * FROM t_65832_1;
c0
v
DROP VIEW v_65832;
DROP TABLE t_65832_0, t_65832_1;
SET sql_mode = @old_sql_mode_65832;
Expand Down
18 changes: 18 additions & 0 deletions tests/integrationtest/t/executor/insert.test
Original file line number Diff line number Diff line change
Expand Up @@ -1783,3 +1783,21 @@ DROP TABLE t;
SET @@time_zone = @old_time_zone;
SET @@sql_mode = @old_sql_mode;
--disable_warnings

# Regression test for issue #65832:
# INSERT ... ON DUPLICATE KEY UPDATE with a subquery referencing a view whose
# SELECT definition contains a constant boolean expression (e.g. WHERE '') should
# not return ErrViewInvalid when the outer statement is an INSERT in strict SQL mode.
# Root cause: planner-time constant folding inherited the outer INSERT's
# truncate handling, causing WHERE '' to raise ErrTruncatedWrongVal and then
# (incorrectly) surface as ErrViewInvalid during view expansion.
SET @old_sql_mode_65832 = @@sql_mode;
SET sql_mode = 'STRICT_TRANS_TABLES';
CREATE TABLE t_65832_0(c0 BLOB(304));
CREATE TABLE t_65832_1(c0 CHAR DEFAULT '0');
CREATE VIEW v_65832(c0) AS SELECT 0.9699394901011086 FROM t_65832_0 INNER JOIN t_65832_0 AS t0_alias ON t_65832_0.c0 WHERE '';
INSERT INTO t_65832_1 VALUES ('v') ON DUPLICATE KEY UPDATE c0=(SELECT true FROM v_65832 CROSS JOIN t_65832_0 ON (true));
SELECT * FROM t_65832_1;
DROP VIEW v_65832;
DROP TABLE t_65832_0, t_65832_1;
SET sql_mode = @old_sql_mode_65832;
Loading