From 60c51543224877f796962895e82955f421b5a179 Mon Sep 17 00:00:00 2001 From: Marcus Gartner Date: Mon, 28 Aug 2023 15:40:10 -0400 Subject: [PATCH] opt: fix plan gist decoding of inverted filters Details about inverted filter nodes are not encoded in plan gists. The explain emitter assumed there were always some details encoded, and would raise an internal error whenever decoding a plan gist with an inverted filter. This commit prevents the internal error from occurring. Fixes #108979 There is no release not because plan gists are an undocumented feature. Release note: None --- .../opt/exec/execbuilder/testdata/explain_gist | 18 ++++++++++++++++++ pkg/sql/opt/exec/explain/emit.go | 8 ++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain_gist b/pkg/sql/opt/exec/execbuilder/testdata/explain_gist index 0aaf5aa0d65d..8da59387f74b 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain_gist +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain_gist @@ -171,3 +171,21 @@ SELECT crdb_internal.decode_plan_gist('AgGSARIAAwlAsJ8BE5IBAhcGFg==') table: ?@? spans: 1+ spans limit + +# Regression test for #108979. Correctly decode inverted filters. +query T nosort +SELECT crdb_internal.decode_plan_gist('AgGwAgQAgQIAAgAEBQITsAICAxgGDA==') +---- +• top-k +│ order +│ +└── • filter + │ + └── • index join + │ table: ?@? + │ + └── • inverted filter + │ + └── • scan + table: ?@? + spans: 1+ spans diff --git a/pkg/sql/opt/exec/explain/emit.go b/pkg/sql/opt/exec/explain/emit.go index 6702102c13da..b24520ed5194 100644 --- a/pkg/sql/opt/exec/explain/emit.go +++ b/pkg/sql/opt/exec/explain/emit.go @@ -780,8 +780,12 @@ func (e *emitter) emitNodeAttributes(n *Node) error { case invertedFilterOp: a := n.args.(*invertedFilterArgs) - ob.Attr("inverted column", a.Input.Columns()[a.InvColumn].Name) - ob.Attr("num spans", len(a.InvFilter.SpansToRead)) + if a.InvColumn != 0 { + ob.Attr("inverted column", a.Input.Columns()[a.InvColumn].Name) + } + if a.InvFilter != nil && len(a.InvFilter.SpansToRead) > 0 { + ob.Attr("num spans", len(a.InvFilter.SpansToRead)) + } case invertedJoinOp: a := n.args.(*invertedJoinArgs)