diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go index ae87227cc52..f66a03f235b 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_engine_test.go @@ -2110,7 +2110,11 @@ func TestStatsFunctions(t *testing.T) { harness.configureStats = true for _, test := range StatProcTests { t.Run(test.Name, func(t *testing.T) { - enginetest.TestScript(t, harness, test) + // reset engine so provider statistics are clean + harness.engine = nil + e := mustNewEngine(t, harness) + defer e.Close() + enginetest.TestScriptWithEngine(t, e, harness, test) }) } } diff --git a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go index 81fd0a9c8ae..d1d9cd2c5a3 100644 --- a/go/libraries/doltcore/sqle/enginetest/dolt_harness.go +++ b/go/libraries/doltcore/sqle/enginetest/dolt_harness.go @@ -247,7 +247,7 @@ func (d *DoltHarness) NewEngine(t *testing.T) (enginetest.QueryEngine, error) { // Get a fresh session if we are reusing the engine if !initializeEngine { var err error - d.session, err = dsess.NewDoltSession(enginetest.NewBaseSession(), d.provider, d.multiRepoEnv.Config(), d.branchControl, nil) + d.session, err = dsess.NewDoltSession(enginetest.NewBaseSession(), d.provider, d.multiRepoEnv.Config(), d.branchControl, d.statsPro) require.NoError(t, err) } diff --git a/go/libraries/doltcore/sqle/enginetest/stats_queries.go b/go/libraries/doltcore/sqle/enginetest/stats_queries.go index aac26dd8ea9..f82ec6ea4c2 100644 --- a/go/libraries/doltcore/sqle/enginetest/stats_queries.go +++ b/go/libraries/doltcore/sqle/enginetest/stats_queries.go @@ -404,6 +404,69 @@ var DoltStatsIOTests = []queries.ScriptTest{ } var StatProcTests = []queries.ScriptTest{ + { + Name: "deleting stats removes information_schema access point", + SetUpScript: []string{ + "CREATE table xy (x bigint primary key, y int, z varchar(500), key(y,z));", + "insert into xy values (0,0,0)", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "analyze table xy", + }, + { + Query: "select count(*) from information_schema.column_statistics", + Expected: []sql.Row{{2}}, + }, + { + Query: "call dolt_stats_drop()", + }, + { + Query: "select count(*) from information_schema.column_statistics", + Expected: []sql.Row{{0}}, + }, + }, + }, + { + Name: "restart empty stats panic", + SetUpScript: []string{ + "CREATE table xy (x bigint primary key, y int, z varchar(500), key(y,z));", + }, + Assertions: []queries.ScriptTestAssertion{ + { + Query: "analyze table xy", + }, + { + Query: "select count(*) from dolt_statistics", + Expected: []sql.Row{{0}}, + }, + { + Query: "set @@GLOBAL.dolt_stats_auto_refresh_threshold = 0", + Expected: []sql.Row{{}}, + }, + { + Query: "set @@GLOBAL.dolt_stats_auto_refresh_interval = 0", + Expected: []sql.Row{{}}, + }, + { + // don't panic + Query: "call dolt_stats_restart()", + }, + { + Query: "select sleep(.1)", + }, + { + Query: "insert into xy values (0,0,0)", + }, + { + Query: "select sleep(.1)", + }, + { + Query: "select count(*) from dolt_statistics", + Expected: []sql.Row{{2}}, + }, + }, + }, { Name: "basic start, status, stop loop", SetUpScript: []string{ diff --git a/go/libraries/doltcore/sqle/stats/update.go b/go/libraries/doltcore/sqle/stats/update.go index cb8546ec284..2c97e799903 100644 --- a/go/libraries/doltcore/sqle/stats/update.go +++ b/go/libraries/doltcore/sqle/stats/update.go @@ -80,7 +80,6 @@ func updateStats(ctx *sql.Context, sqlTable sql.Table, dTab *doltdb.Table, index } else if cnt == 0 { // table is empty ret[meta.qual] = NewDoltStats() - ret[meta.qual].chunks = meta.allAddrs ret[meta.qual].CreatedAt = time.Now() ret[meta.qual].Columns = meta.cols ret[meta.qual].Types = types @@ -192,6 +191,10 @@ func mergeStatUpdates(newStats *DoltStats, idxMeta indexMeta) *DoltStats { } } + if len(mergeHist) == 0 { + return newStats + } + newStats.Histogram = mergeHist newStats.chunks = idxMeta.allAddrs newStats.updateActive()