diff --git a/cli.go b/cli.go index a8f07e5..4d6b098 100644 --- a/cli.go +++ b/cli.go @@ -440,6 +440,9 @@ func resultLine(result *Result, verbose bool) string { if result.Stats.OptimizerVersion != "" { detail += fmt.Sprintf("optimizer version: %s\n", result.Stats.OptimizerVersion) } + if result.Stats.OptimizerStatisticsPackage != "" { + detail += fmt.Sprintf("optimizer statistics: %s\n", result.Stats.OptimizerStatisticsPackage) + } return fmt.Sprintf("%s (%s)\n%s", set, result.Stats.ElapsedTime, detail) } return fmt.Sprintf("%s (%s)\n", set, result.Stats.ElapsedTime) diff --git a/cli_test.go b/cli_test.go index df8516d..66fb9b0 100644 --- a/cli_test.go +++ b/cli_test.go @@ -318,12 +318,13 @@ func TestResultLine(t *testing.T) { AffectedRows: 3, IsMutation: false, Stats: QueryStats{ - ElapsedTime: "10 msec", - CPUTime: "5 msec", - RowsScanned: "10", - RowsReturned: "3", - DeletedRowsScanned: "1", - OptimizerVersion: "2", + ElapsedTime: "10 msec", + CPUTime: "5 msec", + RowsScanned: "10", + RowsReturned: "3", + DeletedRowsScanned: "1", + OptimizerVersion: "2", + OptimizerStatisticsPackage: "auto_20210829_05_22_28UTC", }, Timestamp: ts, }, @@ -334,6 +335,7 @@ cpu time: 5 msec rows scanned: 10 rows deleted rows scanned: 1 rows optimizer version: 2 +optimizer statistics: auto_20210829_05_22_28UTC `, timestamp), }, { diff --git a/statement.go b/statement.go index 5dc3aec..38f68de 100644 --- a/statement.go +++ b/statement.go @@ -71,12 +71,13 @@ type Row struct { // Some fields may not have a valid value depending on the environment. // For example, only ElapsedTime and RowsReturned has valid value for Cloud Spanner Emulator. type QueryStats struct { - ElapsedTime string - CPUTime string - RowsReturned string - RowsScanned string - DeletedRowsScanned string - OptimizerVersion string + ElapsedTime string + CPUTime string + RowsReturned string + RowsScanned string + DeletedRowsScanned string + OptimizerVersion string + OptimizerStatisticsPackage string } var ( @@ -96,6 +97,7 @@ var ( createViewRe = regexp.MustCompile(`(?is)^CREATE\s+VIEW\s.+$`) createOrReplaceViewRe = regexp.MustCompile(`(?is)^CREATE\s+OR\s+REPLACE\s+VIEW\s.+$`) dropViewRe = regexp.MustCompile(`(?is)^DROP\s+VIEW\s.+$`) + alterStatisticsRe = regexp.MustCompile(`(?is)^ALTER\s+STATISTICS\s.+$`) // DML dmlRe = regexp.MustCompile(`(?is)^(INSERT|UPDATE|DELETE)\s+.+$`) @@ -159,6 +161,8 @@ func BuildStatement(input string) (Statement, error) { return &TruncateTableStatement{Table: unquoteIdentifier(matched[1])}, nil case createViewRe.MatchString(input), createOrReplaceViewRe.MatchString(input), dropViewRe.MatchString(input): return &DdlStatement{Ddl: input}, nil + case alterStatisticsRe.MatchString(input): + return &DdlStatement{Ddl: input}, nil case showDatabasesRe.MatchString(input): return &ShowDatabasesStatement{}, nil case showCreateTableRe.MatchString(input): @@ -320,6 +324,12 @@ func parseQueryStats(stats map[string]interface{}) QueryStats { } } + if v, ok := stats["optimizer_statistics_package"]; ok { + if pkg, ok := v.(string); ok { + queryStats.OptimizerStatisticsPackage = pkg + } + } + return queryStats } diff --git a/statement_test.go b/statement_test.go index b7cae30..7ce9633 100644 --- a/statement_test.go +++ b/statement_test.go @@ -126,6 +126,11 @@ func TestBuildStatement(t *testing.T) { input: "DROP VIEW t1view", want: &DdlStatement{Ddl: "DROP VIEW t1view"}, }, + { + desc: "ALTER STATISTICS statement", + input: "ALTER STATISTICS package SET OPTIONS (allow_gc = false)", + want: &DdlStatement{Ddl: "ALTER STATISTICS package SET OPTIONS (allow_gc = false)"}, + }, { desc: "INSERT statement", input: "INSERT INTO t1 (id, name) VALUES (1, 'yuki')",