Skip to content

Commit 63b2ca9

Browse files
committed
feat(print-statements): intercept explain query plan statements
1 parent 5cc9ad0 commit 63b2ca9

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

Diff for: internal/db/output.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ type TablePrinter struct {
2121
func (t TablePrinter) print(statementResult StatementResult, outF io.Writer) error {
2222
data := [][]string{}
2323
table := createTable(outF)
24-
if !t.withoutHeader {
24+
showHeader := !IsResultComingFromExplainQueryPlan(statementResult) && !t.withoutHeader
25+
if showHeader {
2526
table.SetHeader(statementResult.ColumnNames)
2627
}
2728

@@ -100,6 +101,11 @@ func appendData(statementResult StatementResult, data [][]string, mode FormatTyp
100101
}
101102
data = append(data, formattedRow)
102103
}
104+
105+
if IsResultComingFromExplainQueryPlan(statementResult) {
106+
data = [][]string{{"Tree goes here!"}}
107+
}
108+
103109
return data, nil
104110
}
105111

Diff for: internal/db/utils.go

+29
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"net/url"
55
"strings"
66
"unicode"
7+
8+
"golang.org/x/exp/slices"
79
)
810

911
func IsUrl(uri string) bool {
@@ -45,3 +47,30 @@ func NeedsEscaping(name string) bool {
4547
}
4648
return false
4749
}
50+
51+
var explainQueryPlanStatement = "EXPLAIN QUERY PLAN"
52+
var explainQueryPlanColumnNames = []string{"id", "parent", "notused", "detail"}
53+
54+
func queryContainsExplainQueryPlanStatement(query string) bool {
55+
return strings.Contains(query, explainQueryPlanStatement)
56+
}
57+
58+
func columnNamesMatchExplainQueryPlan(colNames []string) bool {
59+
if len(colNames) != len(explainQueryPlanColumnNames) {
60+
return false
61+
}
62+
for _, colName := range explainQueryPlanColumnNames {
63+
if !slices.Contains(colNames, colName) {
64+
return false
65+
}
66+
}
67+
return true
68+
}
69+
70+
// "query" can be a string containing multiple queries separated by ";" or a single query
71+
func IsResultComingFromExplainQueryPlan(statementResult StatementResult) bool {
72+
query := statementResult.Query
73+
columnNames := statementResult.ColumnNames
74+
return queryContainsExplainQueryPlanStatement(query) &&
75+
columnNamesMatchExplainQueryPlan(columnNames)
76+
}

Diff for: test/db_root_command_shell_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,19 @@ func (s *DBRootCommandShellSuite) Test_GivenATableNameWithSpecialCharacters_When
271271
s.tc.AssertSqlEquals(outS, expected)
272272
}
273273

274+
func (s *DBRootCommandShellSuite) Test_GivenATableNameWithTheSameSignatureAsExpainQueryPlan_WhenChainingItWithExplainQueryPlan_ExpectCorrectData() {
275+
_, _, err := s.tc.Execute("CREATE TABLE fake_explain (ID INTEGER PRIMARY KEY, PARENT INTEGER, NOTUSED INTEGER, DETAIL TEXT)")
276+
s.tc.Assert(err, qt.IsNil)
277+
278+
outS, errS, err := s.tc.ExecuteShell([]string{"SELECT * FROM fake_explain; EXPLAIN QUERY PLAN SELECT 1;"})
279+
s.tc.Assert(err, qt.IsNil)
280+
s.tc.Assert(errS, qt.Equals, "")
281+
282+
expected := "id parent notused detail \ntree goes here!"
283+
284+
s.tc.AssertSqlEquals(outS, expected)
285+
}
286+
274287
func (s *DBRootCommandShellSuite) Test_GivenATableWithRecordsWithSingleQuote_WhenCalllSelectAllFromTable_ExpectSingleQuoteScape() {
275288
s.tc.CreateEmptySimpleTable("t")
276289
_, errS, err := s.tc.Execute("INSERT INTO t VALUES (0, \"x'x\", 0)")

0 commit comments

Comments
 (0)