From 2ba377c9fc5a8bac886a54d12ab169772e5ff638 Mon Sep 17 00:00:00 2001 From: DrewKimball Date: Mon, 12 Sep 2022 16:44:53 -0700 Subject: [PATCH] opt: include optional columns when remapping Project provided ordering This commit fixes a bug that was recently introduced in #86193 that can cause an internal panic when remapping an ordering from the input to the output of a `Project` operator. #86193 modified the logic to ensure that the remapping only refers to columns from the required ordering; however, it failed to add the optional columns to the allowed set of columns. This could cause a panic if the provided ordering contains columns from the optional set. This is fixed by adding the optional columns when remapping. Fixes #87806 Release note (bug fix): Fixes a bug introduced in 22.1.7 that could cause an internal panic when a query ordering contained redundant ordering columns. --- pkg/sql/opt/ordering/project.go | 2 +- pkg/sql/opt/xform/testdata/physprops/ordering | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/pkg/sql/opt/ordering/project.go b/pkg/sql/opt/ordering/project.go index b824cfba05ce..ac906a43212f 100644 --- a/pkg/sql/opt/ordering/project.go +++ b/pkg/sql/opt/ordering/project.go @@ -82,7 +82,7 @@ func projectBuildProvided(expr memo.RelExpr, required *props.OrderingChoice) opt // can cause the child to provide an ordering that is equivalent to the // required ordering, but which the parent Project cannot prove is equivalent // because its FDs have less information. This can lead to a panic later on. - ordCols := required.ColSet() + ordCols := required.ColSet().Union(required.Optional) if !ordCols.SubsetOf(expr.Relational().OutputCols) { panic(errors.AssertionFailedf("expected required columns to be a subset of output columns")) } diff --git a/pkg/sql/opt/xform/testdata/physprops/ordering b/pkg/sql/opt/xform/testdata/physprops/ordering index cec9f7ac2b62..382181339a5e 100644 --- a/pkg/sql/opt/xform/testdata/physprops/ordering +++ b/pkg/sql/opt/xform/testdata/physprops/ordering @@ -2609,3 +2609,46 @@ sort │ └── fd: (6)-->(5) └── filters └── (t0_85393.rowid:2 IS NULL) OR (t1_85393.rowid:6 = t0_85393.rowid:2) [outer=(2,6)] + +# Regression test for #87806 - include optional columns when remapping Project +# provided ordering. +exec-ddl +CREATE TABLE table87806 ( + col1_0 TIMESTAMPTZ, col1_1 BOOL, col1_2 REGPROC, col1_3 REGNAMESPACE, + PRIMARY KEY (col1_1, col1_2 ASC), + UNIQUE (col1_1 ASC), + INDEX (col1_3) +); +---- + +opt format=hide-all +SELECT tab_171969.col1_3 +FROM table87806 AS tab_171967 +JOIN table87806 AS tab_171968 +JOIN table87806@table87806_col1_3_idx AS tab_171969 +ON tab_171968.col1_1 = tab_171969.col1_1 +AND tab_171968.col1_3 = tab_171969.col1_3 +AND tab_171968.col1_3 = tab_171969.tableoid +ON tab_171967.col1_2 = tab_171968.tableoid +AND tab_171967.col1_3 = tab_171968.col1_3 +WHERE tab_171967.col1_1 +ORDER BY tab_171969.col1_1 ASC; +---- +project + └── inner-join (lookup table87806@table87806_col1_3_idx [as=tab_171967]) + ├── lookup columns are key + ├── project + │ ├── inner-join (lookup table87806 [as=tab_171968]) + │ │ ├── lookup columns are key + │ │ ├── select + │ │ │ ├── index-join table87806 + │ │ │ │ └── scan table87806@table87806_col1_3_idx [as=tab_171969] + │ │ │ │ ├── constraint: /16/14/15: (/NULL - ] + │ │ │ │ └── flags: force-index=table87806_col1_3_idx + │ │ │ └── filters + │ │ │ └── tab_171969.col1_3 = tab_171969.tableoid + │ │ └── filters + │ │ └── tab_171968.col1_3 = tab_171969.col1_3 + │ └── projections + │ └── true + └── filters (true)