Skip to content

Commit

Permalink
indexrec: refactor index recommendation output
Browse files Browse the repository at this point in the history
Previously, we manually formatted the string for the index recommendation's
SQL output. This commit takes advantage of the existing functionality for
formatting SQL statements, specifically `CREATE INDEX` and `DROP INDEX`. This
will make it easier to add more types of index recommendations in the future.

Release note: None
  • Loading branch information
Neha George committed Dec 10, 2021
1 parent c2ae143 commit c055f85
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 45 deletions.
1 change: 0 additions & 1 deletion pkg/sql/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,6 @@ go_library(
"//pkg/sql/opt/exec/explain",
"//pkg/sql/opt/indexrec",
"//pkg/sql/opt/memo",
"//pkg/sql/opt/norm",
"//pkg/sql/opt/optbuilder",
"//pkg/sql/opt/xform",
"//pkg/sql/optionalnodeliveness",
Expand Down
89 changes: 45 additions & 44 deletions pkg/sql/opt/indexrec/index_recommendation_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/opt"
"github.com/cockroachdb/cockroach/pkg/sql/opt/cat"
"github.com/cockroachdb/cockroach/pkg/sql/opt/memo"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/util"
)

Expand Down Expand Up @@ -166,17 +167,17 @@ func (irs *IndexRecommendationSet) Output() []string {
for _, t := range sortedTables {
indexes := irs.indexRecs[t]
for _, indexRec := range indexes {
var sb strings.Builder
recTypeStr := "index creation"
if indexRec.existingIndex != nil {
recTypeStr = "index replacement"
}
sb.WriteString(fmt.Sprintf("%d. type: %s", indexRecOrd, recTypeStr))
indexCols := indexRec.indexCols()
storing := indexRec.storingColumns()

indexRecType := fmt.Sprintf("%d. type: %s", indexRecOrd, recTypeStr)
indexRecSQL := indexRec.indexRecommendationString(indexCols, storing)
output = append(output, indexRecType, indexRecSQL)
indexRecOrd++
indexCols := indexRec.indexColsString()
storingClause := indexRec.storingClauseString()
sb.WriteString(indexRec.indexRecommendationString(indexCols, storingClause))
output = append(output, sb.String())
}
}
return output
Expand Down Expand Up @@ -246,67 +247,67 @@ func (ir *indexRecommendation) addStoredColOrds(scannedColOrds util.FastIntSet)
ir.newStoredColOrds.UnionWith(scannedStoredColOrds)
}

// indexColsString returns a string containing the explicit key columns of the
// index, used in indexRecommendationString.
func (ir *indexRecommendation) indexColsString() string {
indexCols := make([]string, len(ir.index.cols))
// indexCols returns the explicit key columns of the index, used in
// indexRecommendationString.
func (ir *indexRecommendation) indexCols() []tree.IndexElem {
indexCols := make([]tree.IndexElem, len(ir.index.cols))

for i, n := 0, len(ir.index.cols); i < n; i++ {
var indexColSb strings.Builder
for i := range ir.index.cols {
indexCol := ir.index.Column(i)
colName := indexCol.Column.ColName()
indexColSb.WriteString(colName.String())

var direction tree.Direction
if indexCol.Descending {
indexColSb.WriteString(" DESC")
direction = tree.Descending
}

indexCols[i] = indexColSb.String()
indexCols[i] = tree.IndexElem{Column: colName, Direction: direction}
}

return strings.Join(indexCols, ", ")
return indexCols
}

// storingClauseString returns the STORING clause string output of an index
// recommendation.
func (ir *indexRecommendation) storingClauseString() string {
if ir.newStoredColOrds.Len() == 0 {
return ""
}
var storingSb strings.Builder
for i, col := range ir.newStoredColOrds.Ordered() {
colName := ir.index.tab.Column(col).ColName()
if i > 0 {
storingSb.WriteString(", ")
}
storingSb.WriteString(colName.String())
// storingColumns returns the stored columns of an index recommendation, used in
// indexRecommendationString.
func (ir *indexRecommendation) storingColumns() []tree.Name {
storingLen := ir.newStoredColOrds.Len()
if storingLen == 0 {
return nil
}
return " STORING (" + storingSb.String() + ")"
storingCols := make([]tree.Name, 0, storingLen)
ir.newStoredColOrds.ForEach(func(colOrd int) {
colName := ir.index.tab.Column(colOrd).ColName()
storingCols = append(storingCols, colName)
})
return storingCols
}

// indexRecommendationString returns the string output for an index
// recommendation, containing the SQL command(s) needed to follow this
// recommendation.
func (ir *indexRecommendation) indexRecommendationString(indexCols, storingClause string) string {
func (ir *indexRecommendation) indexRecommendationString(
indexCols []tree.IndexElem, storing []tree.Name,
) string {
var sb strings.Builder
tableName := ir.index.tab.Name()
tableName := tree.NewUnqualifiedTableName(ir.index.tab.Name())

if ir.existingIndex != nil {
sb.WriteString("\n SQL commands: ")
indexName := ir.existingIndex.Name()
dropCmd := fmt.Sprintf("DROP INDEX %s@%s; ", tableName.String(), indexName.String())
sb.WriteString(dropCmd)
sb.WriteString(" SQL commands: ")
indexName := tree.UnrestrictedName(ir.existingIndex.Name())
dropCmd := tree.DropIndex{
IndexList: []*tree.TableIndexName{{Table: *tableName, Index: indexName}},
}
sb.WriteString(dropCmd.String() + "; ")
} else {
sb.WriteString("\n SQL command: ")
sb.WriteString(" SQL command: ")
}

createCmd := fmt.Sprintf(
"CREATE INDEX ON %s (%s)%s;",
tableName.String(),
indexCols,
storingClause,
)
sb.WriteString(createCmd)
createCmd := tree.CreateIndex{
Table: *tableName,
Columns: indexCols,
Storing: storing,
}
sb.WriteString(createCmd.String() + ";")

return sb.String()
}

0 comments on commit c055f85

Please sign in to comment.