Skip to content

Commit 0945a0b

Browse files
committed
Add schema to StatsQualifier for schema databases
1 parent fe6616d commit 0945a0b

File tree

10 files changed

+86
-31
lines changed

10 files changed

+86
-31
lines changed

enginetest/queries/stats_queries.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ var StatisticsQueries = []ScriptTest{
3535
SkipResultCheckOnServerEngine: true, // the non-interface types are not identified over the wire result
3636
Query: "SELECT * FROM information_schema.column_statistics",
3737
Expected: []sql.Row{
38-
{"mydb", "t", "i", stats.NewStatistic(3, 3, 0, 24, time.Now(), sql.NewStatQualifier("mydb", "t", "primary"), []string{"i"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
38+
{"mydb", "t", "i", stats.NewStatistic(3, 3, 0, 24, time.Now(), sql.NewStatQualifier("mydb", "", "t", "primary"), []string{"i"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
3939
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(1)}, nil, nil),
4040
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(2)}, nil, nil),
4141
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(3)}, nil, nil),
@@ -60,7 +60,7 @@ var StatisticsQueries = []ScriptTest{
6060
SkipResultCheckOnServerEngine: true, // the non-interface types are not identified over the wire result
6161
Query: "SELECT * FROM information_schema.column_statistics",
6262
Expected: []sql.Row{
63-
{"mydb", "t", "i", stats.NewStatistic(40, 40, 1, 0, time.Now(), sql.NewStatQualifier("mydb", "t", "primary"), []string{"i"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
63+
{"mydb", "t", "i", stats.NewStatistic(40, 40, 1, 0, time.Now(), sql.NewStatQualifier("mydb", "", "t", "primary"), []string{"i"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
6464
stats.NewHistogramBucket(20, 20, 0, 1, sql.Row{float64(50)}, nil, nil),
6565
stats.NewHistogramBucket(20, 20, 0, 1, sql.Row{float64(80)}, nil, nil),
6666
}, sql.IndexClassDefault, nil),
@@ -89,13 +89,13 @@ var StatisticsQueries = []ScriptTest{
8989
SkipResultCheckOnServerEngine: true, // the non-interface types are not identified over the wire result
9090
Query: "SELECT * FROM information_schema.column_statistics",
9191
Expected: []sql.Row{
92-
{"mydb", "t", "i", stats.NewStatistic(3, 3, 0, 48, time.Now(), sql.NewStatQualifier("mydb", "t", "primary"), []string{"i"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
92+
{"mydb", "t", "i", stats.NewStatistic(3, 3, 0, 48, time.Now(), sql.NewStatQualifier("mydb", "", "t", "primary"), []string{"i"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
9393
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(1)}, nil, []sql.Row{}),
9494
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(2)}, nil, []sql.Row{}),
9595
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(3)}, nil, []sql.Row{}),
9696
}, sql.IndexClassDefault, nil),
9797
},
98-
{"mydb", "t", "j", stats.NewStatistic(3, 3, 0, 48, time.Now(), sql.NewStatQualifier("mydb", "t", "j"), []string{"j"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
98+
{"mydb", "t", "j", stats.NewStatistic(3, 3, 0, 48, time.Now(), sql.NewStatQualifier("mydb", "", "t", "j"), []string{"j"}, []sql.Type{types.Int64}, []sql.HistogramBucket{
9999
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(4)}, nil, []sql.Row{}),
100100
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(5)}, nil, []sql.Row{}),
101101
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{int64(6)}, nil, []sql.Row{}),
@@ -117,7 +117,7 @@ var StatisticsQueries = []ScriptTest{
117117
SkipResultCheckOnServerEngine: true, // the non-interface types are not identified over the wire result
118118
Query: "SELECT * FROM information_schema.column_statistics",
119119
Expected: []sql.Row{
120-
{"mydb", "t", "i", stats.NewStatistic(4, 4, 0, 32, time.Now(), sql.NewStatQualifier("mydb", "t", "primary"), []string{"i"}, []sql.Type{types.Float64}, []sql.HistogramBucket{
120+
{"mydb", "t", "i", stats.NewStatistic(4, 4, 0, 32, time.Now(), sql.NewStatQualifier("mydb", "", "t", "primary"), []string{"i"}, []sql.Type{types.Float64}, []sql.HistogramBucket{
121121
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{float64(1.25)}, nil, []sql.Row{}),
122122
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{float64(7.5)}, nil, []sql.Row{}),
123123
stats.NewHistogramBucket(1, 1, 0, 1, sql.Row{float64(10.5)}, nil, []sql.Row{}),

memory/stats.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,17 @@ func (s *StatsProv) estimateStats(ctx *sql.Context, table sql.Table, keys map[st
156156
types = append(types, sch[i].Type)
157157
}
158158

159-
qual, err := sql.NewQualifierFromString(string(key))
159+
var schemaName string
160+
if tabSch, ok := table.(sql.DatabaseSchemaTable); ok {
161+
schemaName = tabSch.DatabaseSchema().SchemaName()
162+
}
163+
164+
var qual sql.StatQualifier
165+
if schemaName == "" {
166+
qual, err = sql.NewQualifierFromString(string(key))
167+
} else {
168+
qual, err = sql.NewSchemaQualifierFromString(string(key))
169+
}
160170
if err != nil {
161171
return err
162172
}
@@ -260,7 +270,7 @@ func (s *StatsProv) GetStats(ctx *sql.Context, qual sql.StatQualifier, cols []st
260270

261271
func (s *StatsProv) DropStats(ctx *sql.Context, qual sql.StatQualifier, cols []string) error {
262272
colsSuff := strings.Join(cols, ",") + ")"
263-
for key, _ := range s.colStats {
273+
for key := range s.colStats {
264274
if strings.HasPrefix(string(key), qual.String()) && strings.HasSuffix(string(key), colsSuff) {
265275
delete(s.colStats, key)
266276
}
@@ -295,7 +305,7 @@ func (s *StatsProv) DataLength(ctx *sql.Context, db string, table sql.Table) (ui
295305
}
296306

297307
func (s *StatsProv) DropDbStats(ctx *sql.Context, db string, flush bool) error {
298-
for key, _ := range s.colStats {
308+
for key := range s.colStats {
299309
if strings.HasPrefix(string(key), db) {
300310
delete(s.colStats, key)
301311
}

sql/analyzer/costed_index_scan.go

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,17 @@ func getCostedIndexScan(ctx *sql.Context, statsProv sql.StatsProvider, rt sql.Ta
173173
if dbTab, ok := rt.UnderlyingTable().(sql.Databaseable); ok {
174174
dbName = strings.ToLower(dbTab.Database())
175175
}
176-
tableName := strings.ToLower(rt.UnderlyingTable().Name())
176+
table := rt.UnderlyingTable()
177+
var schemaName string
178+
if schTab, ok := table.(sql.DatabaseSchemaTable); ok {
179+
schemaName = strings.ToLower(schTab.DatabaseSchema().SchemaName())
180+
}
181+
tableName := strings.ToLower(table.Name())
177182

178183
if len(qualToStat) > 0 {
179184
// don't mix and match real and default stats
180185
for _, idx := range indexes {
181-
qual := sql.NewStatQualifier(dbName, tableName, strings.ToLower(idx.ID()))
186+
qual := sql.NewStatQualifier(dbName, schemaName, tableName, strings.ToLower(idx.ID()))
182187
_, ok := qualToStat[qual]
183188
if !ok {
184189
qualToStat = nil
@@ -188,7 +193,7 @@ func getCostedIndexScan(ctx *sql.Context, statsProv sql.StatsProvider, rt sql.Ta
188193
}
189194

190195
for _, idx := range indexes {
191-
qual := sql.NewStatQualifier(dbName, tableName, strings.ToLower(idx.ID()))
196+
qual := sql.NewStatQualifier(dbName, schemaName, tableName, strings.ToLower(idx.ID()))
192197
stat, ok := qualToStat[qual]
193198
if !ok {
194199
stat, err = uniformDistStatisticsForIndex(ctx, statsProv, iat, idx)
@@ -1536,6 +1541,10 @@ func uniformDistStatisticsForIndex(ctx *sql.Context, statsProv sql.StatsProvider
15361541
if dbTable, ok := iat.(sql.Databaseable); ok {
15371542
dbName = strings.ToLower(dbTable.Database())
15381543
}
1544+
var schemaName string
1545+
if schTab, ok := iat.(sql.DatabaseSchemaTable); ok {
1546+
schemaName = strings.ToLower(schTab.DatabaseSchema().SchemaName())
1547+
}
15391548
tableName := strings.ToLower(iat.Name())
15401549

15411550
var sch sql.Schema
@@ -1545,7 +1554,7 @@ func uniformDistStatisticsForIndex(ctx *sql.Context, statsProv sql.StatsProvider
15451554
sch = iat.Schema()
15461555
}
15471556

1548-
return newUniformDistStatistic(dbName, tableName, sch, idx, rowCount, avgSize)
1557+
return newUniformDistStatistic(dbName, schemaName, tableName, sch, idx, rowCount, avgSize)
15491558
}
15501559

15511560
func indexFds(tableName string, sch sql.Schema, idx sql.Index) (*sql.FuncDepSet, sql.ColSet, error) {
@@ -1588,7 +1597,7 @@ func indexFds(tableName string, sch sql.Schema, idx sql.Index) (*sql.FuncDepSet,
15881597
return sql.NewTablescanFDs(all, strictKeys, laxKeys, notNull), idxCols, nil
15891598
}
15901599

1591-
func newUniformDistStatistic(dbName, tableName string, sch sql.Schema, idx sql.Index, rowCount, avgSize uint64) (sql.Statistic, error) {
1600+
func newUniformDistStatistic(dbName, schemaName, tableName string, sch sql.Schema, idx sql.Index, rowCount, avgSize uint64) (sql.Statistic, error) {
15921601
tablePrefix := fmt.Sprintf("%s.", tableName)
15931602

15941603
distinctCount := rowCount
@@ -1615,7 +1624,7 @@ func newUniformDistStatistic(dbName, tableName string, sch sql.Schema, idx sql.I
16151624
class = sql.IndexClassDefault
16161625
}
16171626

1618-
qual := sql.NewStatQualifier(dbName, tableName, strings.ToLower(idx.ID()))
1627+
qual := sql.NewStatQualifier(dbName, schemaName, tableName, strings.ToLower(idx.ID()))
16191628
stat := stats.NewStatistic(rowCount, distinctCount, nullCount, avgSize, time.Now(), qual, cols, types, nil, class, nil)
16201629

16211630
fds, idxCols, err := indexFds(tableName, sch, idx)

sql/analyzer/costed_index_scan_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ func TestRangeBuilder(t *testing.T) {
583583
idx = idx_1
584584
}
585585

586-
stat, err := newUniformDistStatistic("mydb", testTable, sch, idx, 10, 10)
586+
stat, err := newUniformDistStatistic("mydb", "", testTable, sch, idx, 10, 10)
587587
require.NoError(t, err)
588588

589589
err = c.cost(root, stat, idx)

sql/analyzer/indexed_joins.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1344,7 +1344,12 @@ func makeIndexScan(ctx *sql.Context, statsProv sql.StatsProvider, tab plan.Table
13441344
for _, e := range idx.SqlIdx().Expressions() {
13451345
cols = append(cols, strings.TrimPrefix(e, tablePrefix))
13461346
}
1347-
stats, _ := statsProv.GetStats(ctx, sql.NewStatQualifier(tn.Database().Name(), tn.Name(), idx.SqlIdx().ID()), cols)
1347+
var schemaName string
1348+
if schTab, ok := tn.(sql.DatabaseSchemaTable); ok {
1349+
schemaName = strings.ToLower(schTab.DatabaseSchema().SchemaName())
1350+
}
1351+
1352+
stats, _ := statsProv.GetStats(ctx, sql.NewStatQualifier(tn.Database().Name(), schemaName, tn.Name(), idx.SqlIdx().ID()), cols)
13481353

13491354
return &memo.IndexScan{
13501355
Table: ret,

sql/plan/histogram.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,16 @@ func (u *UpdateHistogram) IsReadOnly() bool {
7979
return false
8080
}
8181

82-
func NewDropHistogram(db, table string, cols []string) *DropHistogram {
83-
return &DropHistogram{db: db, cols: cols, table: table}
82+
func NewDropHistogram(db, schema, table string, cols []string) *DropHistogram {
83+
return &DropHistogram{db: db, schema: schema, cols: cols, table: table}
8484
}
8585

8686
type DropHistogram struct {
87-
db string
88-
table string
89-
cols []string
90-
prov sql.StatsProvider
87+
db string
88+
schema string
89+
table string
90+
cols []string
91+
prov sql.StatsProvider
9192
}
9293

9394
var _ sql.Node = (*DropHistogram)(nil)
@@ -106,6 +107,10 @@ func (d *DropHistogram) Db() string {
106107
return d.db
107108
}
108109

110+
func (d *DropHistogram) SchemaName() string {
111+
return d.schema
112+
}
113+
109114
func (d *DropHistogram) Table() string {
110115
return d.table
111116
}

sql/planbuilder/analyze.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (b *Builder) buildAnalyze(inScope *scope, n *ast.Analyze, query string) (ou
7070
switch n.Action {
7171
case ast.UpdateStr:
7272
sch := tableScope.node.Schema()
73-
return b.buildAnalyzeUpdate(inScope, n, strings.ToLower(n.Tables[0].DbQualifier.String()), strings.ToLower(n.Tables[0].Name.String()), sch, columns, types)
73+
return b.buildAnalyzeUpdate(inScope, n, strings.ToLower(n.Tables[0].DbQualifier.String()), strings.ToLower(n.Tables[0].SchemaQualifier.String()), strings.ToLower(n.Tables[0].Name.String()), sch, columns, types)
7474
case ast.DropStr:
7575
outScope = inScope.push()
7676
dbName := n.Tables[0].DbQualifier.String()
@@ -81,7 +81,7 @@ func (b *Builder) buildAnalyze(inScope *scope, n *ast.Analyze, query string) (ou
8181
b.handleErr(sql.ErrNoDatabaseSelected.New())
8282
}
8383

84-
outScope.node = plan.NewDropHistogram(strings.ToLower(dbName), strings.ToLower(n.Tables[0].Name.String()), columns).WithProvider(b.cat)
84+
outScope.node = plan.NewDropHistogram(strings.ToLower(dbName), strings.ToLower(n.Tables[0].SchemaQualifier.String()), strings.ToLower(n.Tables[0].Name.String()), columns).WithProvider(b.cat)
8585
default:
8686
err := fmt.Errorf("invalid ANALYZE action: %s, expected UPDATE or DROP", n.Action)
8787
b.handleErr(err)
@@ -117,7 +117,7 @@ func (b *Builder) buildAnalyzeTables(inScope *scope, n *ast.Analyze, query strin
117117
return
118118
}
119119

120-
func (b *Builder) buildAnalyzeUpdate(inScope *scope, n *ast.Analyze, dbName, tableName string, sch sql.Schema, columns []string, types []sql.Type) (outScope *scope) {
120+
func (b *Builder) buildAnalyzeUpdate(inScope *scope, n *ast.Analyze, dbName, schemaName, tableName string, sch sql.Schema, columns []string, types []sql.Type) (outScope *scope) {
121121
if dbName == "" {
122122
dbName = b.ctx.GetCurrentDatabase()
123123
}
@@ -155,7 +155,7 @@ func (b *Builder) buildAnalyzeUpdate(inScope *scope, n *ast.Analyze, dbName, tab
155155

156156
statistic := statisticJ.ToStatistic()
157157

158-
statistic.SetQualifier(sql.NewStatQualifier(strings.ToLower(dbName), tableName, strings.ToLower(indexName)))
158+
statistic.SetQualifier(sql.NewStatQualifier(strings.ToLower(dbName), strings.ToLower(schemaName), tableName, strings.ToLower(indexName)))
159159
statistic.SetColumns(columns)
160160
statistic.SetTypes(types)
161161

sql/rowexec/other.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ func (b *BaseBuilder) buildDropHistogram(ctx *sql.Context, n *plan.DropHistogram
333333

334334
return &dropHistogramIter{
335335
db: n.Db(),
336+
schema: n.SchemaName(),
336337
table: n.Table(),
337338
columns: n.Cols(),
338339
prov: n.StatsProvider(),

sql/rowexec/other_iters.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func (itr *updateHistogramIter) Close(_ *sql.Context) error {
8484

8585
type dropHistogramIter struct {
8686
db string
87+
schema string
8788
table string
8889
columns []string
8990
prov sql.StatsProvider
@@ -99,7 +100,7 @@ func (itr *dropHistogramIter) Next(ctx *sql.Context) (sql.Row, error) {
99100
defer func() {
100101
itr.done = true
101102
}()
102-
qual := sql.NewStatQualifier(itr.db, itr.table, "")
103+
qual := sql.NewStatQualifier(itr.db, itr.schema, itr.table, "")
103104
err := itr.prov.DropStats(ctx, qual, itr.columns)
104105
if err != nil {
105106
return sql.Row{itr.table, "histogram", "error", err.Error()}, nil

sql/statistics.go

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ type MutableStatistic interface {
9191
WithLowerBound(Row) Statistic
9292
}
9393

94+
// NewSchemaQualifierFromString creates a new StatQualifier from a string.
9495
func NewQualifierFromString(q string) (StatQualifier, error) {
9596
parts := strings.Split(q, ".")
9697
if len(parts) < 3 {
@@ -99,23 +100,42 @@ func NewQualifierFromString(q string) (StatQualifier, error) {
99100
return StatQualifier{Database: parts[0], Tab: parts[1], Idx: parts[2]}, nil
100101
}
101102

102-
func NewStatQualifier(db, table, index string) StatQualifier {
103-
return StatQualifier{Database: strings.ToLower(db), Tab: strings.ToLower(table), Idx: strings.ToLower(index)}
103+
// NewSchemaQualifierFromString creates a new StatQualifier from a string,
104+
// assuming the string contains a schema part.
105+
func NewSchemaQualifierFromString(q string) (StatQualifier, error) {
106+
parts := strings.Split(q, ".")
107+
if len(parts) < 4 {
108+
return StatQualifier{}, fmt.Errorf("invalid qualifier string: '%s', expected '<database>.<schema>.<table>.<index>'", q)
109+
}
110+
return StatQualifier{Database: parts[0], Sch: parts[1], Tab: parts[2], Idx: parts[3]}, nil
111+
}
112+
113+
func NewStatQualifier(db, schema, table, index string) StatQualifier {
114+
return StatQualifier{
115+
Database: strings.ToLower(db),
116+
Sch: strings.ToLower(schema),
117+
Tab: strings.ToLower(table),
118+
Idx: strings.ToLower(index)}
104119
}
105120

106121
// StatQualifier is the namespace hierarchy for a given statistic.
107122
// The qualifier and set of columns completely describes a unique stat.
108123
type StatQualifier struct {
109124
Database string `json:"database"`
125+
Sch string `json:"schema"`
110126
Tab string `json:"table"`
111127
Idx string `json:"index"`
112128
}
113129

114130
func (q StatQualifier) String() string {
131+
tableName := q.Tab
132+
if q.Sch != "" {
133+
tableName = fmt.Sprintf("%s.%s", q.Sch, q.Tab)
134+
}
115135
if q.Idx != "" {
116-
return fmt.Sprintf("%s.%s.%s", q.Database, q.Tab, q.Idx)
136+
return fmt.Sprintf("%s.%s.%s", q.Database, tableName, q.Idx)
117137
}
118-
return fmt.Sprintf("%s.%s", q.Database, q.Tab)
138+
return fmt.Sprintf("%s.%s", q.Database, tableName)
119139
}
120140

121141
func (q StatQualifier) Empty() bool {
@@ -126,6 +146,10 @@ func (q StatQualifier) Db() string {
126146
return q.Database
127147
}
128148

149+
func (q StatQualifier) Schema() string {
150+
return q.Sch
151+
}
152+
129153
func (q StatQualifier) Table() string {
130154
return q.Tab
131155
}

0 commit comments

Comments
 (0)