diff --git a/pkg/sql/stats/stats_cache.go b/pkg/sql/stats/stats_cache.go index 37f81290d473..9411ad15f221 100644 --- a/pkg/sql/stats/stats_cache.go +++ b/pkg/sql/stats/stats_cache.go @@ -36,6 +36,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/sql/types" "github.com/cockroachdb/cockroach/pkg/util/cache" "github.com/cockroachdb/cockroach/pkg/util/encoding" + "github.com/cockroachdb/cockroach/pkg/util/errorutil" "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/protoutil" @@ -214,10 +215,23 @@ func decodeTableStatisticsKV( // The statistics are ordered by their CreatedAt time (newest-to-oldest). func (sc *TableStatisticsCache) GetTableStats( ctx context.Context, table catalog.TableDescriptor, -) ([]*TableStatistic, error) { +) (stats []*TableStatistic, err error) { if !statsUsageAllowed(table, sc.settings) { return nil, nil } + defer func() { + if r := recover(); r != nil { + // In the event of a "safe" panic, we only want to log the error and + // continue executing the query without stats for this table. + if ok, e := errorutil.ShouldCatch(r); ok { + err = e + } else { + // Other panic objects can't be considered "safe" and thus are + // propagated as crashes that terminate the session. + panic(r) + } + } + }() forecast := forecastAllowed(table, sc.settings) return sc.getTableStatsFromCache(ctx, table.GetID(), &forecast) }