From b2a48398ed2aa24a530630cc1f909a144f9bb7b0 Mon Sep 17 00:00:00 2001 From: Samuel Adetunji <45036507+adetunjii@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:21:12 +0100 Subject: [PATCH] Fix MySQL collection stats (#4145) Closes #3413. --- internal/backends/mysql/collection.go | 88 ++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/internal/backends/mysql/collection.go b/internal/backends/mysql/collection.go index 13c8341b7045..6e1c63cf898a 100644 --- a/internal/backends/mysql/collection.go +++ b/internal/backends/mysql/collection.go @@ -366,7 +366,93 @@ func (c *collection) Explain(ctx context.Context, params *backends.ExplainParams // Stats implements backends.Collection interface. func (c *collection) Stats(ctx context.Context, params *backends.CollectionStatsParams) (*backends.CollectionStatsResult, error) { - return nil, lazyerrors.New("not yet implemented") + p, err := c.r.DatabaseGetExisting(ctx, c.dbName) + if err != nil { + return nil, lazyerrors.Error(err) + } + + if p == nil { + return nil, backends.NewError( + backends.ErrorCodeCollectionDoesNotExist, + lazyerrors.Errorf("no ns %s.%s", c.dbName, c.name), + ) + } + + coll, err := c.r.CollectionGet(ctx, c.dbName, c.name) + if err != nil { + return nil, lazyerrors.Error(err) + } + + if coll == nil { + return nil, backends.NewError( + backends.ErrorCodeCollectionDoesNotExist, + lazyerrors.Errorf("no ns %s.%s", c.dbName, c.name), + ) + } + + stats, err := collectionsStats(ctx, p, c.dbName, []*metadata.Collection{coll}, params.Refresh) + if err != nil { + return nil, lazyerrors.Error(err) + } + + indexMap := map[string]string{} + for _, index := range coll.Indexes { + indexMap[index.Index] = index.Name + } + + q := ` + SELECT + s.index_name, + t.index_length, + FROM information_schema.tables t + JOIN information_schema.statistics s + ON t.table_schema = s.table_schema AND t.table_name = s.table_name + WHERE t.table_schema = ? AND t.table_name IN ? + ` + + rows, err := p.QueryContext(ctx, q, c.dbName, coll.TableName) + if err != nil { + return nil, lazyerrors.Error(err) + } + + defer rows.Close() + + indexSizes := make([]backends.IndexSize, len(indexMap)) + var i int + + for rows.Next() { + var name string + var size int64 + + if err := rows.Scan(&name, &size); err != nil { + return nil, lazyerrors.Error(err) + } + + indexName, ok := indexMap[name] + if !ok { + // new indexes have been created since metadata was last fetched + continue + } + + indexSizes[i] = backends.IndexSize{ + Name: indexName, + Size: size, + } + i++ + } + + if rows.Err() != nil { + return nil, lazyerrors.Error(rows.Err()) + } + + return &backends.CollectionStatsResult{ + CountDocuments: stats.countDocuments, + SizeTotal: stats.sizeTables + stats.sizeIndexes, + SizeIndexes: stats.sizeIndexes, + SizeCollection: stats.sizeTables, + SizeFreeStorage: stats.sizeFreeStorage, + IndexSizes: indexSizes, + }, nil } // Compact implements backends.Collection interface.