Skip to content

Commit 8114b4c

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

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

internal/db/db.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -223,15 +223,16 @@ func getColumnTypes(rows *sql.Rows) ([]reflect.Type, error) {
223223

224224
func readQueryResults(queryRows *sql.Rows, statementResultCh chan StatementResult, query string) (shouldContinue bool) {
225225
queries, _ := sqliteparserutils.SplitStatement(query)
226+
queryIndex := 0
226227
hasResultSetToRead := true
227228
for hasResultSetToRead {
228-
for _, query := range queries {
229-
if shouldContinue := readQueryResultSet(queryRows, statementResultCh, query); !shouldContinue {
230-
return false
231-
}
232-
233-
hasResultSetToRead = queryRows.NextResultSet()
229+
query := queries[queryIndex]
230+
if shouldContinue := readQueryResultSet(queryRows, statementResultCh, query); !shouldContinue {
231+
return false
234232
}
233+
234+
hasResultSetToRead = queryRows.NextResultSet()
235+
queryIndex++
235236
}
236237

237238
if err := queryRows.Err(); err != nil {

internal/db/output.go

Lines changed: 7 additions & 1 deletion
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

internal/db/utils.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package db
22

33
import (
44
"net/url"
5+
"reflect"
56
"strings"
67
"unicode"
78
)
@@ -45,3 +46,25 @@ func NeedsEscaping(name string) bool {
4546
}
4647
return false
4748
}
49+
50+
var explainQueryPlanStatement = "EXPLAIN QUERY PLAN"
51+
var explainQueryPlanColumnNames = []string{"id", "parent", "notused", "detail"}
52+
53+
func queryContainsExplainQueryPlanStatement(query string) bool {
54+
return strings.HasPrefix(
55+
strings.ToLower(query),
56+
strings.ToLower(explainQueryPlanStatement),
57+
)
58+
}
59+
60+
func columnNamesMatchExplainQueryPlan(colNames []string) bool {
61+
return reflect.DeepEqual(colNames, explainQueryPlanColumnNames)
62+
}
63+
64+
// "query" can be a string containing multiple queries separated by ";" or a single query
65+
func IsResultComingFromExplainQueryPlan(statementResult StatementResult) bool {
66+
query := statementResult.Query
67+
columnNames := statementResult.ColumnNames
68+
return queryContainsExplainQueryPlanStatement(query) &&
69+
columnNamesMatchExplainQueryPlan(columnNames)
70+
}

test/db_root_command_shell_test.go

Lines changed: 13 additions & 0 deletions
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)