Skip to content

Commit

Permalink
sql: be more strict with validating EXPLAIN
Browse files Browse the repository at this point in the history
Verify during paring that we are not specifying an invalid mode for
`EXPLAIN ANALYZE`.

Fixes cockroachdb#51473.

Release note: None
  • Loading branch information
RaduBerinde committed Jul 28, 2020
1 parent 0bcf5ed commit 888c458
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
43 changes: 43 additions & 0 deletions pkg/sql/parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2817,6 +2817,49 @@ EXPLAIN EXECUTE a
^
HINT: try \h EXPLAIN`,
},
{
`EXPLAIN ANALYZE (PLAN) SELECT 1`,
`at or near "EOF": syntax error: EXPLAIN ANALYZE cannot be used with PLAN
DETAIL: source SQL:
EXPLAIN ANALYZE (PLAN) SELECT 1
^`,
},
{
`EXPLAIN (ANALYZE, PLAN) SELECT 1`,
`at or near "analyze": syntax error
DETAIL: source SQL:
EXPLAIN (ANALYZE, PLAN) SELECT 1
^
HINT: try \h <SELECTCLAUSE>`,
},
{
`EXPLAIN ANALYZE (OPT) SELECT 1`,
`at or near "EOF": syntax error: EXPLAIN ANALYZE cannot be used with OPT
DETAIL: source SQL:
EXPLAIN ANALYZE (OPT) SELECT 1
^`,
},
{
`EXPLAIN ANALYZE (VEC) SELECT 1`,
`at or near "EOF": syntax error: EXPLAIN ANALYZE cannot be used with VEC
DETAIL: source SQL:
EXPLAIN ANALYZE (VEC) SELECT 1
^`,
},
{
`EXPLAIN (DEBUG) SELECT 1`,
`at or near "EOF": syntax error: DEBUG flag can only be used with EXPLAIN ANALYZE
DETAIL: source SQL:
EXPLAIN (DEBUG) SELECT 1
^`,
},
{
`EXPLAIN (PLAN, DEBUG) SELECT 1`,
`at or near "EOF": syntax error: DEBUG flag can only be used with EXPLAIN ANALYZE
DETAIL: source SQL:
EXPLAIN (PLAN, DEBUG) SELECT 1
^`,
},
{
`SELECT $0`,
`lexical error: placeholder index must be between 1 and 65536
Expand Down
17 changes: 14 additions & 3 deletions pkg/sql/sem/tree/explain.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,15 @@ func (f ExplainFlag) String() string {
// Format implements the NodeFormatter interface.
func (node *Explain) Format(ctx *FmtCtx) {
ctx.WriteString("EXPLAIN ")
showMode := node.Mode != ExplainPlan
// ANALYZE is a special case because it is a statement implemented as an
// option to EXPLAIN.
if node.Flags[ExplainFlagAnalyze] {
ctx.WriteString("ANALYZE ")
showMode = true
}
wroteFlag := false
if node.Mode != ExplainPlan {
if showMode {
fmt.Fprintf(ctx, "(%s", node.Mode)
wroteFlag = true
}
Expand Down Expand Up @@ -207,10 +209,19 @@ func MakeExplain(options []string, stmt Statement) (Statement, error) {
}
opts.Flags[flag] = true
}
analyze := opts.Flags[ExplainFlagAnalyze]
if opts.Mode == 0 {
// Default mode is ExplainPlan.
opts.Mode = ExplainPlan
if analyze {
// ANALYZE implies DISTSQL.
opts.Mode = ExplainDistSQL
} else {
// Default mode is ExplainPlan.
opts.Mode = ExplainPlan
}
} else if analyze && opts.Mode != ExplainDistSQL {
return nil, pgerror.Newf(pgcode.Syntax, "EXPLAIN ANALYZE cannot be used with %s", opts.Mode)
}

return &Explain{
ExplainOptions: opts,
Statement: stmt,
Expand Down
4 changes: 3 additions & 1 deletion pkg/sql/sem/tree/pretty.go
Original file line number Diff line number Diff line change
Expand Up @@ -2017,13 +2017,15 @@ func (node *Export) doc(p *PrettyCfg) pretty.Doc {

func (node *Explain) doc(p *PrettyCfg) pretty.Doc {
d := pretty.Keyword("EXPLAIN")
showMode := node.Mode != ExplainPlan
// ANALYZE is a special case because it is a statement implemented as an
// option to EXPLAIN.
if node.Flags[ExplainFlagAnalyze] {
d = pretty.ConcatSpace(d, pretty.Keyword("ANALYZE"))
showMode = true
}
var opts []pretty.Doc
if node.Mode != ExplainPlan {
if showMode {
opts = append(opts, pretty.Keyword(node.Mode.String()))
}
for f := ExplainFlag(1); f <= numExplainFlags; f++ {
Expand Down

0 comments on commit 888c458

Please sign in to comment.