diff --git a/pkg/sql/opt/norm/mutation_funcs.go b/pkg/sql/opt/norm/mutation_funcs.go new file mode 100644 index 000000000000..f0cc82e57e2f --- /dev/null +++ b/pkg/sql/opt/norm/mutation_funcs.go @@ -0,0 +1,116 @@ +// Copyright 2020 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package norm + +import ( + "github.com/cockroachdb/cockroach/pkg/sql/opt" + "github.com/cockroachdb/cockroach/pkg/sql/opt/memo" +) + +// SimplifiablePartialIndexProjectCols returns the set of projected partial +// index PUT and DEL columns with expressions that can be simplified to false. +// These projected expressions can only be simplified to false when an UPDATE or +// UPSERT mutates neither the associated index's columns nor the columns +// referenced in the partial index predicate. +func (c *CustomFuncs) SimplifiablePartialIndexProjectCols( + private *memo.MutationPrivate, + uniqueChecks memo.UniqueChecksExpr, + fkChecks memo.FKChecksExpr, + projections memo.ProjectionsExpr, +) opt.ColSet { + tabMeta := c.mem.Metadata().TableMeta(private.Table) + + // Determine the set of target table columns that need to be updated. + var updateCols opt.ColSet + for ord, col := range private.UpdateCols { + if col != 0 { + updateCols.Add(tabMeta.MetaID.ColumnID(ord)) + } + } + + // Determine the set of columns needed for the mutation operator, excluding + // the partial index PUT and DEL columns. + neededMutationCols := c.neededMutationCols(private, uniqueChecks, fkChecks, false /* includePartialIndexCols */) + + // Determine the set of project columns that are already simplified to + // false. + var simplifiedProjectCols opt.ColSet + for i := range projections { + project := &projections[i] + if project.Element == memo.FalseSingleton { + simplifiedProjectCols.Add(project.Col) + } + } + + // Columns that are required by the mutation operator and columns that + // have already been simplified to false are ineligible to be simplified. + ineligibleCols := neededMutationCols.Union(simplifiedProjectCols) + + var cols opt.ColSet + ord := 0 + for i, n := 0, tabMeta.Table.DeletableIndexCount(); i < n; i++ { + pred, isPartialIndex := tabMeta.PartialIndexPredicate(i) + + // Skip non-partial indexes. + if !isPartialIndex { + continue + } + + // If the columns being updated are part of the index or referenced in + // the partial index predicate, then the update requires may update the + // index. Therefore, the partial index PUT and DEL columns cannot be + // simplified. + // + // Note that we use the set of index columns where the virtual + // columns have been mapped to their source columns. Virtual columns + // are never part of the updated columns. Updates to source columns + // trigger index changes. + predFilters := *pred.(*memo.FiltersExpr) + indexAndPredCols := tabMeta.IndexColumnsMapVirtual(i) + indexAndPredCols.UnionWith(predFilters.OuterCols()) + if indexAndPredCols.Intersects(updateCols) { + continue + } + + // Add the projected PUT column if it is eligible to be simplified. + putCol := private.PartialIndexPutCols[ord] + if !ineligibleCols.Contains(putCol) { + cols.Add(putCol) + } + + // Add the projected DEL column if it is eligible to be simplified. + delCol := private.PartialIndexDelCols[ord] + if !ineligibleCols.Contains(delCol) { + cols.Add(delCol) + } + + ord++ + } + + return cols +} + +// SimplifyPartialIndexProjections returns a new projection expression with any +// projected column's expression simplified to false if the column exists in +// simplifiableCols. +func (c *CustomFuncs) SimplifyPartialIndexProjections( + projections memo.ProjectionsExpr, simplifiableCols opt.ColSet, +) memo.ProjectionsExpr { + simplified := make(memo.ProjectionsExpr, len(projections)) + for i := range projections { + if col := projections[i].Col; simplifiableCols.Contains(col) { + simplified[i] = c.f.ConstructProjectionsItem(memo.FalseSingleton, col) + } else { + simplified[i] = projections[i] + } + } + return simplified +} diff --git a/pkg/sql/opt/norm/prune_cols_funcs.go b/pkg/sql/opt/norm/prune_cols_funcs.go index eae66d98cd90..e7325cd6c62b 100644 --- a/pkg/sql/opt/norm/prune_cols_funcs.go +++ b/pkg/sql/opt/norm/prune_cols_funcs.go @@ -44,6 +44,15 @@ func (c *CustomFuncs) NeededExplainCols(private *memo.ExplainPrivate) opt.ColSet // in turn trigger the PruneMutationInputCols rule. func (c *CustomFuncs) NeededMutationCols( private *memo.MutationPrivate, uniqueChecks memo.UniqueChecksExpr, fkChecks memo.FKChecksExpr, +) opt.ColSet { + return c.neededMutationCols(private, uniqueChecks, fkChecks, true /* includePartialIndexCols */) +} + +func (c *CustomFuncs) neededMutationCols( + private *memo.MutationPrivate, + uniqueChecks memo.UniqueChecksExpr, + fkChecks memo.FKChecksExpr, + includePartialIndexCols bool, ) opt.ColSet { var cols opt.ColSet @@ -60,8 +69,10 @@ func (c *CustomFuncs) NeededMutationCols( addCols(private.FetchCols) addCols(private.UpdateCols) addCols(private.CheckCols) - addCols(private.PartialIndexPutCols) - addCols(private.PartialIndexDelCols) + if includePartialIndexCols { + addCols(private.PartialIndexPutCols) + addCols(private.PartialIndexDelCols) + } addCols(private.ReturnCols) addCols(opt.OptionalColList(private.PassthroughCols)) if private.CanaryCol != 0 { diff --git a/pkg/sql/opt/norm/rules/mutation.opt b/pkg/sql/opt/norm/rules/mutation.opt index e69de29bb2d1..cb1f8d264373 100644 --- a/pkg/sql/opt/norm/rules/mutation.opt +++ b/pkg/sql/opt/norm/rules/mutation.opt @@ -0,0 +1,39 @@ +# ============================================================================= +# mutation.opt contains normalization rules for the mutation operators. +# ============================================================================= + +# SimplifyPartialIndexProjections converts partial index PUT and DEL projected +# expressions to false when it is guaranteed that the mutation will not require +# changes to the associated partial index. These projected expressions can only +# be simplified to false when an UPDATE or UPSERT mutates neither the +# associated index's columns nor the columns referenced in the partial index +# predicate. +[SimplifyPartialIndexProjections, Normalize] +(Update | Upsert + $project:(Project $input:* $projections:* $passthrough:*) + $uniqueChecks:* + $fkChecks:* + $mutationPrivate:* & + ^(ColsAreEmpty + $simplifiableCols:(SimplifiablePartialIndexProjectCols + $mutationPrivate + $uniqueChecks + $fkChecks + $projections + ) + ) +) +=> +((OpName) + (Project + $input + (SimplifyPartialIndexProjections + $projections + $simplifiableCols + ) + $passthrough + ) + $uniqueChecks + $fkChecks + $mutationPrivate +) diff --git a/pkg/sql/opt/norm/testdata/rules/mutation b/pkg/sql/opt/norm/testdata/rules/mutation new file mode 100644 index 000000000000..18534be9d94a --- /dev/null +++ b/pkg/sql/opt/norm/testdata/rules/mutation @@ -0,0 +1,332 @@ +exec-ddl +CREATE TABLE t ( + k INT PRIMARY KEY, + a INT, + b INT, + c INT, + d INT, + e INT, + f INT, + g INT, + h BOOL, + INDEX (c) WHERE d > 1, + INDEX (e) WHERE f > 1 AND g > 1 +) +---- + +# Simplify UPDATE partial index put/del column to false when the indexed columns +# and columns referenced in predicates are not mutating. +norm expect=SimplifyPartialIndexProjections +UPDATE t SET a = 2, b = 2 WHERE k = 1 +---- +update t + ├── columns: + ├── fetch columns: k:11 a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── update-mapping: + │ ├── a_new:21 => a:2 + │ └── a_new:21 => b:3 + ├── partial index put columns: partial_index_put1:22 partial_index_put2:23 + ├── partial index del columns: partial_index_put1:22 partial_index_put2:23 + ├── cardinality: [0 - 0] + ├── volatile, mutations + └── project + ├── columns: partial_index_put1:22!null partial_index_put2:23!null a_new:21!null k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── cardinality: [0 - 1] + ├── key: () + ├── fd: ()-->(11-19,21-23) + ├── select + │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ ├── cardinality: [0 - 1] + │ ├── key: () + │ ├── fd: ()-->(11-19) + │ ├── scan t + │ │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ │ ├── partial index predicates + │ │ │ ├── secondary: filters + │ │ │ │ └── d:15 > 1 [outer=(15), constraints=(/15: [/2 - ]; tight)] + │ │ │ └── secondary: filters + │ │ │ ├── f:17 > 1 [outer=(17), constraints=(/17: [/2 - ]; tight)] + │ │ │ └── g:18 > 1 [outer=(18), constraints=(/18: [/2 - ]; tight)] + │ │ ├── key: (11) + │ │ └── fd: (11)-->(12-19) + │ └── filters + │ └── k:11 = 1 [outer=(11), constraints=(/11: [/1 - /1]; tight), fd=()-->(11)] + └── projections + ├── false [as=partial_index_put1:22] + ├── false [as=partial_index_put2:23] + └── 2 [as=a_new:21] + +# Simplify UPSERT partial index put/del column to false when the indexed columns +# and columns referenced in predicates are not mutating. +norm expect=SimplifyPartialIndexProjections +UPSERT INTO t (k, a, b) VALUES (1, 2, 3) +---- +upsert t + ├── columns: + ├── arbiter indexes: primary + ├── canary column: k:16 + ├── fetch columns: k:16 a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + ├── insert-mapping: + │ ├── column1:11 => k:1 + │ ├── column2:12 => a:2 + │ ├── column3:13 => b:3 + │ ├── column14:14 => c:4 + │ ├── column14:14 => d:5 + │ ├── column14:14 => e:6 + │ ├── column14:14 => f:7 + │ ├── column14:14 => g:8 + │ └── column15:15 => h:9 + ├── update-mapping: + │ ├── column2:12 => a:2 + │ └── column3:13 => b:3 + ├── partial index put columns: partial_index_put1:33 partial_index_put2:35 + ├── partial index del columns: partial_index_del1:34 partial_index_del2:36 + ├── cardinality: [0 - 0] + ├── volatile, mutations + └── project + ├── columns: partial_index_put1:33!null partial_index_del1:34!null partial_index_put2:35!null partial_index_del2:36!null column1:11!null column2:12!null column3:13!null column14:14 column15:15 k:16 a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + ├── cardinality: [1 - 1] + ├── key: () + ├── fd: ()-->(11-24,33-36) + ├── left-join (cross) + │ ├── columns: column1:11!null column2:12!null column3:13!null column14:14 column15:15 k:16 a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + │ ├── cardinality: [1 - 1] + │ ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one) + │ ├── key: () + │ ├── fd: ()-->(11-24) + │ ├── values + │ │ ├── columns: column1:11!null column2:12!null column3:13!null column14:14 column15:15 + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(11-15) + │ │ └── (1, 2, 3, NULL, NULL) + │ ├── select + │ │ ├── columns: k:16!null a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + │ │ ├── cardinality: [0 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(16-24) + │ │ ├── scan t + │ │ │ ├── columns: k:16!null a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + │ │ │ ├── partial index predicates + │ │ │ │ ├── secondary: filters + │ │ │ │ │ └── d:20 > 1 [outer=(20), constraints=(/20: [/2 - ]; tight)] + │ │ │ │ └── secondary: filters + │ │ │ │ ├── f:22 > 1 [outer=(22), constraints=(/22: [/2 - ]; tight)] + │ │ │ │ └── g:23 > 1 [outer=(23), constraints=(/23: [/2 - ]; tight)] + │ │ │ ├── key: (16) + │ │ │ └── fd: (16)-->(17-24) + │ │ └── filters + │ │ └── k:16 = 1 [outer=(16), constraints=(/16: [/1 - /1]; tight), fd=()-->(16)] + │ └── filters (true) + └── projections + ├── false [as=partial_index_put1:33] + ├── false [as=partial_index_del1:34] + ├── false [as=partial_index_put2:35] + └── false [as=partial_index_del2:36] + +# Simplify INSERT ... ON CONFLICT ... DO UPDATE partial index put/del column to +# false when the indexed columns and columns referenced in predicates are not +# mutating. +norm expect=SimplifyPartialIndexProjections +INSERT INTO t (k, a, b) VALUES (1, 2, 3) ON CONFLICT (k) DO UPDATE SET a = t.a + 1, b = t.b + 1 +---- +upsert t + ├── columns: + ├── arbiter indexes: primary + ├── canary column: k:16 + ├── fetch columns: k:16 a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + ├── insert-mapping: + │ ├── column1:11 => k:1 + │ ├── column2:12 => a:2 + │ ├── column3:13 => b:3 + │ ├── column14:14 => c:4 + │ ├── column14:14 => d:5 + │ ├── column14:14 => e:6 + │ ├── column14:14 => f:7 + │ ├── column14:14 => g:8 + │ └── column15:15 => h:9 + ├── update-mapping: + │ ├── upsert_a:29 => a:2 + │ └── upsert_b:30 => b:3 + ├── partial index put columns: partial_index_put1:37 partial_index_put2:39 + ├── partial index del columns: partial_index_del1:38 partial_index_del2:40 + ├── cardinality: [0 - 0] + ├── volatile, mutations + └── project + ├── columns: partial_index_put1:37!null partial_index_del1:38!null partial_index_put2:39!null partial_index_del2:40!null upsert_a:29 upsert_b:30 column1:11!null column2:12!null column3:13!null column14:14 column15:15 k:16 a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + ├── cardinality: [1 - 1] + ├── immutable + ├── key: () + ├── fd: ()-->(11-24,29,30,37-40) + ├── left-join (cross) + │ ├── columns: column1:11!null column2:12!null column3:13!null column14:14 column15:15 k:16 a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + │ ├── cardinality: [1 - 1] + │ ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one) + │ ├── key: () + │ ├── fd: ()-->(11-24) + │ ├── values + │ │ ├── columns: column1:11!null column2:12!null column3:13!null column14:14 column15:15 + │ │ ├── cardinality: [1 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(11-15) + │ │ └── (1, 2, 3, NULL, NULL) + │ ├── select + │ │ ├── columns: k:16!null a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + │ │ ├── cardinality: [0 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(16-24) + │ │ ├── scan t + │ │ │ ├── columns: k:16!null a:17 b:18 c:19 d:20 e:21 f:22 g:23 h:24 + │ │ │ ├── partial index predicates + │ │ │ │ ├── secondary: filters + │ │ │ │ │ └── d:20 > 1 [outer=(20), constraints=(/20: [/2 - ]; tight)] + │ │ │ │ └── secondary: filters + │ │ │ │ ├── f:22 > 1 [outer=(22), constraints=(/22: [/2 - ]; tight)] + │ │ │ │ └── g:23 > 1 [outer=(23), constraints=(/23: [/2 - ]; tight)] + │ │ │ ├── key: (16) + │ │ │ └── fd: (16)-->(17-24) + │ │ └── filters + │ │ └── k:16 = 1 [outer=(16), constraints=(/16: [/1 - /1]; tight), fd=()-->(16)] + │ └── filters (true) + └── projections + ├── false [as=partial_index_put1:37] + ├── false [as=partial_index_del1:38] + ├── false [as=partial_index_put2:39] + ├── false [as=partial_index_del2:40] + ├── CASE WHEN k:16 IS NULL THEN column2:12 ELSE a:17 + 1 END [as=upsert_a:29, outer=(12,16,17), immutable] + └── CASE WHEN k:16 IS NULL THEN column3:13 ELSE b:18 + 1 END [as=upsert_b:30, outer=(13,16,18), immutable] + +# Do not simplify partial index put/del column to false when the indexed columns +# are mutating. +norm expect-not=SimplifyPartialIndexProjections +UPDATE t SET c = 1, e = 1 WHERE k = 1 +---- +update t + ├── columns: + ├── fetch columns: k:11 a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── update-mapping: + │ ├── c_new:21 => c:4 + │ └── c_new:21 => e:6 + ├── partial index put columns: partial_index_put1:22 partial_index_put2:23 + ├── partial index del columns: partial_index_put1:22 partial_index_put2:23 + ├── cardinality: [0 - 0] + ├── volatile, mutations + └── project + ├── columns: partial_index_put1:22 partial_index_put2:23 c_new:21!null k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── cardinality: [0 - 1] + ├── key: () + ├── fd: ()-->(11-19,21-23) + ├── select + │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ ├── cardinality: [0 - 1] + │ ├── key: () + │ ├── fd: ()-->(11-19) + │ ├── scan t + │ │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ │ ├── partial index predicates + │ │ │ ├── secondary: filters + │ │ │ │ └── d:15 > 1 [outer=(15), constraints=(/15: [/2 - ]; tight)] + │ │ │ └── secondary: filters + │ │ │ ├── f:17 > 1 [outer=(17), constraints=(/17: [/2 - ]; tight)] + │ │ │ └── g:18 > 1 [outer=(18), constraints=(/18: [/2 - ]; tight)] + │ │ ├── key: (11) + │ │ └── fd: (11)-->(12-19) + │ └── filters + │ └── k:11 = 1 [outer=(11), constraints=(/11: [/1 - /1]; tight), fd=()-->(11)] + └── projections + ├── d:15 > 1 [as=partial_index_put1:22, outer=(15)] + ├── (f:17 > 1) AND (g:18 > 1) [as=partial_index_put2:23, outer=(17,18)] + └── 1 [as=c_new:21] + +# Do not simplify partial index put/del column to false when the columns +# referenced in partial index predicates are mutating. +norm expect-not=SimplifyPartialIndexProjections +UPDATE t SET d = d + 1, g = g + 1 WHERE k = 1 +---- +update t + ├── columns: + ├── fetch columns: k:11 a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── update-mapping: + │ ├── d_new:21 => d:5 + │ └── g_new:22 => g:8 + ├── partial index put columns: partial_index_put1:23 partial_index_put2:25 + ├── partial index del columns: partial_index_del1:24 partial_index_del2:26 + ├── cardinality: [0 - 0] + ├── volatile, mutations + └── project + ├── columns: partial_index_put1:23 partial_index_del1:24 partial_index_put2:25 partial_index_del2:26 k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 d_new:21 g_new:22 + ├── cardinality: [0 - 1] + ├── immutable + ├── key: () + ├── fd: ()-->(11-19,21-26) + ├── project + │ ├── columns: d_new:21 g_new:22 k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ ├── cardinality: [0 - 1] + │ ├── immutable + │ ├── key: () + │ ├── fd: ()-->(11-19,21,22) + │ ├── select + │ │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ │ ├── cardinality: [0 - 1] + │ │ ├── key: () + │ │ ├── fd: ()-->(11-19) + │ │ ├── scan t + │ │ │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ │ │ ├── partial index predicates + │ │ │ │ ├── secondary: filters + │ │ │ │ │ └── d:15 > 1 [outer=(15), constraints=(/15: [/2 - ]; tight)] + │ │ │ │ └── secondary: filters + │ │ │ │ ├── f:17 > 1 [outer=(17), constraints=(/17: [/2 - ]; tight)] + │ │ │ │ └── g:18 > 1 [outer=(18), constraints=(/18: [/2 - ]; tight)] + │ │ │ ├── key: (11) + │ │ │ └── fd: (11)-->(12-19) + │ │ └── filters + │ │ └── k:11 = 1 [outer=(11), constraints=(/11: [/1 - /1]; tight), fd=()-->(11)] + │ └── projections + │ ├── d:15 + 1 [as=d_new:21, outer=(15), immutable] + │ └── g:18 + 1 [as=g_new:22, outer=(18), immutable] + └── projections + ├── d_new:21 > 1 [as=partial_index_put1:23, outer=(21)] + ├── d:15 > 1 [as=partial_index_del1:24, outer=(15)] + ├── (f:17 > 1) AND (g_new:22 > 1) [as=partial_index_put2:25, outer=(17,22)] + └── (f:17 > 1) AND (g:18 > 1) [as=partial_index_del2:26, outer=(17,18)] + +# Do not simplify partial index put/del column to false when it is also an +# update column. +norm +UPDATE t SET h = d > 1 WHERE k = 1 +---- +update t + ├── columns: + ├── fetch columns: k:11 a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── update-mapping: + │ └── h_new:21 => h:9 + ├── partial index put columns: h_new:21 partial_index_put2:22 + ├── partial index del columns: h_new:21 partial_index_put2:22 + ├── cardinality: [0 - 0] + ├── volatile, mutations + └── project + ├── columns: partial_index_put2:22!null h_new:21 k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + ├── cardinality: [0 - 1] + ├── key: () + ├── fd: ()-->(11-19,21,22) + ├── select + │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ ├── cardinality: [0 - 1] + │ ├── key: () + │ ├── fd: ()-->(11-19) + │ ├── scan t + │ │ ├── columns: k:11!null a:12 b:13 c:14 d:15 e:16 f:17 g:18 h:19 + │ │ ├── partial index predicates + │ │ │ ├── secondary: filters + │ │ │ │ └── d:15 > 1 [outer=(15), constraints=(/15: [/2 - ]; tight)] + │ │ │ └── secondary: filters + │ │ │ ├── f:17 > 1 [outer=(17), constraints=(/17: [/2 - ]; tight)] + │ │ │ └── g:18 > 1 [outer=(18), constraints=(/18: [/2 - ]; tight)] + │ │ ├── key: (11) + │ │ └── fd: (11)-->(12-19) + │ └── filters + │ └── k:11 = 1 [outer=(11), constraints=(/11: [/1 - /1]; tight), fd=()-->(11)] + └── projections + ├── false [as=partial_index_put2:22] + └── d:15 > 1 [as=h_new:21, outer=(15)] diff --git a/pkg/sql/opt/norm/testdata/rules/prune_cols b/pkg/sql/opt/norm/testdata/rules/prune_cols index ef54a006d307..001be4a90991 100644 --- a/pkg/sql/opt/norm/testdata/rules/prune_cols +++ b/pkg/sql/opt/norm/testdata/rules/prune_cols @@ -2076,27 +2076,27 @@ update partial_indexes ├── cardinality: [0 - 0] ├── volatile, mutations └── project - ├── columns: partial_index_put1:12 d_new:11 a:6!null d:9 + ├── columns: partial_index_put1:12!null d_new:11 a:6!null d:9 ├── cardinality: [0 - 1] ├── immutable ├── key: () ├── fd: ()-->(6,9,11,12) ├── select - │ ├── columns: a:6!null b:7 d:9 + │ ├── columns: a:6!null d:9 │ ├── cardinality: [0 - 1] │ ├── key: () - │ ├── fd: ()-->(6,7,9) + │ ├── fd: ()-->(6,9) │ ├── scan partial_indexes - │ │ ├── columns: a:6!null b:7 d:9 + │ │ ├── columns: a:6!null d:9 │ │ ├── partial index predicates │ │ │ └── secondary: filters │ │ │ └── b:7 > 1 [outer=(7), constraints=(/7: [/2 - ]; tight)] │ │ ├── key: (6) - │ │ └── fd: (6)-->(7,9) + │ │ └── fd: (6)-->(9) │ └── filters │ └── a:6 = 1 [outer=(6), constraints=(/6: [/1 - /1]; tight), fd=()-->(6)] └── projections - ├── b:7 > 1 [as=partial_index_put1:12, outer=(7)] + ├── false [as=partial_index_put1:12] └── d:9 + 1 [as=d_new:11, outer=(9), immutable] # Do not prune the indexed column c when a column in the partial index @@ -2163,16 +2163,16 @@ upsert partial_indexes ├── cardinality: [0 - 0] ├── volatile, mutations └── project - ├── columns: partial_index_put1:18 partial_index_del1:19 column1:6!null column2:7!null column8:8 column9:9 a:10 d:13 + ├── columns: partial_index_put1:18!null partial_index_del1:19!null column1:6!null column2:7!null column8:8 column9:9 a:10 d:13 ├── cardinality: [1 - 1] ├── key: () ├── fd: ()-->(6-10,13,18,19) ├── left-join (cross) - │ ├── columns: column1:6!null column2:7!null column8:8 column9:9 a:10 b:11 d:13 + │ ├── columns: column1:6!null column2:7!null column8:8 column9:9 a:10 d:13 │ ├── cardinality: [1 - 1] │ ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one) │ ├── key: () - │ ├── fd: ()-->(6-11,13) + │ ├── fd: ()-->(6-10,13) │ ├── values │ │ ├── columns: column1:6!null column2:7!null column8:8 column9:9 │ │ ├── cardinality: [1 - 1] @@ -2180,23 +2180,23 @@ upsert partial_indexes │ │ ├── fd: ()-->(6-9) │ │ └── (1, 2, NULL, NULL) │ ├── select - │ │ ├── columns: a:10!null b:11 d:13 + │ │ ├── columns: a:10!null d:13 │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(10,11,13) + │ │ ├── fd: ()-->(10,13) │ │ ├── scan partial_indexes - │ │ │ ├── columns: a:10!null b:11 d:13 + │ │ │ ├── columns: a:10!null d:13 │ │ │ ├── partial index predicates │ │ │ │ └── secondary: filters │ │ │ │ └── b:11 > 1 [outer=(11), constraints=(/11: [/2 - ]; tight)] │ │ │ ├── key: (10) - │ │ │ └── fd: (10)-->(11,13) + │ │ │ └── fd: (10)-->(13) │ │ └── filters │ │ └── a:10 = 1 [outer=(10), constraints=(/10: [/1 - /1]; tight), fd=()-->(10)] │ └── filters (true) └── projections - ├── CASE WHEN a:10 IS NULL THEN column8:8 ELSE b:11 END > 1 [as=partial_index_put1:18, outer=(8,10,11)] - └── b:11 > 1 [as=partial_index_del1:19, outer=(11)] + ├── false [as=partial_index_put1:18] + └── false [as=partial_index_del1:19] # Do not prune the indexed column c when a column in the partial index # predicate, b, is being updated. @@ -2279,16 +2279,16 @@ upsert partial_indexes ├── cardinality: [0 - 0] ├── volatile, mutations └── project - ├── columns: partial_index_put1:20 partial_index_del1:21 upsert_d:19!null column1:6!null column2:7!null column8:8 column9:9 a:10 d:13 + ├── columns: partial_index_put1:20!null partial_index_del1:21!null upsert_d:19!null column1:6!null column2:7!null column8:8 column9:9 a:10 d:13 ├── cardinality: [1 - 1] ├── key: () ├── fd: ()-->(6-10,13,19-21) ├── left-join (cross) - │ ├── columns: column1:6!null column2:7!null column8:8 column9:9 a:10 b:11 d:13 + │ ├── columns: column1:6!null column2:7!null column8:8 column9:9 a:10 d:13 │ ├── cardinality: [1 - 1] │ ├── multiplicity: left-rows(exactly-one), right-rows(exactly-one) │ ├── key: () - │ ├── fd: ()-->(6-11,13) + │ ├── fd: ()-->(6-10,13) │ ├── values │ │ ├── columns: column1:6!null column2:7!null column8:8 column9:9 │ │ ├── cardinality: [1 - 1] @@ -2296,23 +2296,23 @@ upsert partial_indexes │ │ ├── fd: ()-->(6-9) │ │ └── (1, 2, NULL, NULL) │ ├── select - │ │ ├── columns: a:10!null b:11 d:13 + │ │ ├── columns: a:10!null d:13 │ │ ├── cardinality: [0 - 1] │ │ ├── key: () - │ │ ├── fd: ()-->(10,11,13) + │ │ ├── fd: ()-->(10,13) │ │ ├── scan partial_indexes - │ │ │ ├── columns: a:10!null b:11 d:13 + │ │ │ ├── columns: a:10!null d:13 │ │ │ ├── partial index predicates │ │ │ │ └── secondary: filters │ │ │ │ └── b:11 > 1 [outer=(11), constraints=(/11: [/2 - ]; tight)] │ │ │ ├── key: (10) - │ │ │ └── fd: (10)-->(11,13) + │ │ │ └── fd: (10)-->(13) │ │ └── filters │ │ └── a:10 = 1 [outer=(10), constraints=(/10: [/1 - /1]; tight), fd=()-->(10)] │ └── filters (true) └── projections - ├── CASE WHEN a:10 IS NULL THEN column8:8 ELSE b:11 END > 1 [as=partial_index_put1:20, outer=(8,10,11)] - ├── b:11 > 1 [as=partial_index_del1:21, outer=(11)] + ├── false [as=partial_index_put1:20] + ├── false [as=partial_index_del1:21] └── CASE WHEN a:10 IS NULL THEN column2:7 ELSE 3 END [as=upsert_d:19, outer=(7,10)] # Do not prune the indexed column c when a column in the partial index