Skip to content

Commit

Permalink
Merge pull request #64 from vitessio/rohit/reference2
Browse files Browse the repository at this point in the history
Add table row count to summary output
  • Loading branch information
systay authored Nov 22, 2024
2 parents 98191dc + e769e9c commit bfe4db4
Show file tree
Hide file tree
Showing 19 changed files with 1,611 additions and 30 deletions.
8 changes: 5 additions & 3 deletions go/cmd/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ limitations under the License.
package cmd

import (
"errors"
"fmt"

"github.com/spf13/cobra"

Expand Down Expand Up @@ -53,9 +53,11 @@ func keysCmd() *cobra.Command {
return cmd
}

const allowedInputTypes = "'sql', 'mysql-log' or 'vtgate-log'"

func addInputTypeFlag(cmd *cobra.Command, s *string) {
*s = "sql"
cmd.Flags().StringVar(s, "input-type", "sql", "Specifies the type of input file: 'sql' or 'mysql-log'")
cmd.Flags().StringVar(s, "input-type", "sql", fmt.Sprintf("Specifies the type of input file: %s", allowedInputTypes))
}

func configureLoader(inputType string, needsBindVars bool) (data.Loader, error) {
Expand All @@ -67,6 +69,6 @@ func configureLoader(inputType string, needsBindVars bool) (data.Loader, error)
case "vtgate-log":
return data.VtGateLogLoader{NeedsBindVars: needsBindVars}, nil
default:
return nil, errors.New("invalid input type: must be 'sql' or 'mysql-log'")
return nil, fmt.Errorf("invalid input type: must be %s", allowedInputTypes)
}
}
1 change: 1 addition & 0 deletions go/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func Execute() {
root.AddCommand(testerCmd())
root.AddCommand(tracerCmd())
root.AddCommand(keysCmd())
root.AddCommand(schemaCmd())

err := root.Execute()
if err != nil {
Expand Down
50 changes: 50 additions & 0 deletions go/cmd/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright 2024 The Vitess Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cmd

import (
"github.com/spf13/cobra"
"vitess.io/vitess/go/mysql"

"github.com/vitessio/vt/go/schema"
)

func schemaCmd() *cobra.Command {
var vtParams mysql.ConnParams

cmd := &cobra.Command{
Use: "schema ",
Short: "Loads info from the database including row counts",
Example: "vt schema",
Args: cobra.ExactArgs(0),
RunE: func(_ *cobra.Command, _ []string) error {
cfg := schema.Config{
VTParams: vtParams,
}

return schema.Run(cfg)
},
}

cmd.Flags().StringVarP(&vtParams.Host, "host", "", "127.0.0.1", "Database host")
cmd.Flags().IntVarP(&vtParams.Port, "port", "", 3306, "Database port")
cmd.Flags().StringVarP(&vtParams.Uname, "user", "", "root", "Database user")
cmd.Flags().StringVarP(&vtParams.Pass, "password", "", "", "Database password")
cmd.Flags().StringVarP(&vtParams.DbName, "database", "", "", "Database name")

return cmd
}
20 changes: 16 additions & 4 deletions go/data/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package data

import (
"fmt"
"strconv"
"strings"

log "github.com/sirupsen/logrus"
)
Expand All @@ -36,10 +38,11 @@ type (
}

Query struct {
FirstWord string
Query string
Line int
Type CmdType
FirstWord string
Query string
Line int
Type CmdType
UsageCount int

// These fields are only set if the log file is a slow query log
QueryTime, LockTime float64
Expand All @@ -56,13 +59,20 @@ type (
// If the query log contains directives, they will be read and queries will be skipped as necessary.
func ForeachSQLQuery(loader IteratorLoader, f func(Query) error) error {
skip := false
usageCount := 1
for {
query, kontinue := loader.Next()
if !kontinue {
break
}

switch query.Type {
case UsageCount:
var err error
usageCount, err = strconv.Atoi(strings.TrimSpace(query.Query))
if err != nil {
return fmt.Errorf("usage Count is incorrectly specified: %s", query.Query)
}
case Skip, Error, VExplain:
skip = true
case Unknown:
Expand All @@ -74,9 +84,11 @@ func ForeachSQLQuery(loader IteratorLoader, f func(Query) error) error {
skip = false
continue
}
query.UsageCount = usageCount
if err := f(query); err != nil {
return err
}
usageCount = 1
}
}

Expand Down
2 changes: 2 additions & 0 deletions go/data/typ.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const (
VitessOnly
MysqlOnly
Reference
UsageCount
)

var commandMap = map[string]CmdType{ //nolint:gochecknoglobals // this is instead of a const
Expand All @@ -46,6 +47,7 @@ var commandMap = map[string]CmdType{ //nolint:gochecknoglobals // this is instea
"vitess_only": VitessOnly,
"mysql_only": MysqlOnly,
"reference": Reference,
"usage_count": UsageCount,
}

func (cmd CmdType) String() string {
Expand Down
8 changes: 6 additions & 2 deletions go/keys/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,12 @@ func (ql *queryList) processQuery(si *schemaInfo, ast sqlparser.Statement, q dat

structure := sqlparser.CanonicalString(ast)
r, found := ql.queries[structure]
usageCount := q.UsageCount
if usageCount == 0 {
usageCount = 1
}
if found {
r.UsageCount++
r.UsageCount += usageCount
r.LineNumbers = append(r.LineNumbers, q.Line)
r.QueryTime += q.QueryTime
r.LockTime += q.LockTime
Expand All @@ -163,7 +167,7 @@ func (ql *queryList) processQuery(si *schemaInfo, ast sqlparser.Statement, q dat
ql.queries[structure] = &QueryAnalysisResult{
QueryStructure: structure,
StatementType: result.StatementType,
UsageCount: 1,
UsageCount: usageCount,
LineNumbers: []int{q.Line},
TableNames: tableNames,
GroupingColumns: result.GroupingColumns,
Expand Down
105 changes: 105 additions & 0 deletions go/schema/schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
Copyright 2024 The Vitess Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package schema

import (
"context"
"encoding/json"
"fmt"
"io"
"os"

"vitess.io/vitess/go/mysql"
)

type Config struct {
VTParams mysql.ConnParams
}

func Run(cfg Config) error {
return run(os.Stdout, cfg)
}

func run(out io.Writer, cfg Config) error {
si, err := Get(cfg)
if err != nil {
return err
}
b, err := json.MarshalIndent(si, "", " ")
if err != nil {
return err
}
_, err = out.Write(b)
return err
}

type TableInfo struct {
Name string `json:"name"`
Rows int `json:"rows"`
}

type Info struct {
FileType string `json:"fileType"`
Tables []TableInfo `json:"tables"`
}

func Get(cfg Config) (*Info, error) {
vtParams := &mysql.ConnParams{
Host: cfg.VTParams.Host,
Port: cfg.VTParams.Port,
Uname: cfg.VTParams.Uname,
Pass: cfg.VTParams.Pass,
DbName: cfg.VTParams.DbName,
}

vtConn, err := mysql.Connect(context.Background(), vtParams)
if err != nil {
return nil, err
}
defer vtConn.Close()
queryTableSizes := "SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema = '%s' and table_type = 'BASE TABLE'"
qr, err := vtConn.ExecuteFetch(fmt.Sprintf(queryTableSizes, cfg.VTParams.DbName), -1, false)
if err != nil {
return nil, err
}
var tables []TableInfo
for _, row := range qr.Rows {
tableName := row[0].ToString()
tableRows, _ := row[1].ToInt64()
tables = append(tables, TableInfo{
Name: tableName,
Rows: int(tableRows),
})
}
schemaInfo := &Info{
Tables: tables,
}
return schemaInfo, nil
}

func Load(fileName string) (*Info, error) {
b, err := os.ReadFile(fileName)
if err != nil {
return nil, err
}
var si Info
err = json.Unmarshal(b, &si)
if err != nil {
return nil, err
}
return &si, nil
}
48 changes: 48 additions & 0 deletions go/schema/schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
Copyright 2024 The Vitess Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package schema

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestSchema(t *testing.T) {
si, err := Load("../testdata/sakila-schema-info.json")
require.NoError(t, err)
require.NotNil(t, si)
require.NotEmpty(t, si.Tables)
require.Len(t, si.Tables, 16)
var tables []string
for _, table := range si.Tables {
tables = append(tables, table.Name)
}
require.Contains(t, tables, "actor")
require.NotContains(t, tables, "foo")
for _, table := range si.Tables {
require.NotEmpty(t, table.Name)
switch table.Name {
case "language":
require.Equal(t, 6, table.Rows)
case "film":
require.Equal(t, 1000, table.Rows)
default:
require.Positive(t, table.Rows, "table %s has no rows", table.Name)
}
}
}
Loading

0 comments on commit bfe4db4

Please sign in to comment.