Skip to content

Commit 0c896cf

Browse files
committed
sql: guard against non-public mutation columns in CREATE STATISTICS
Defensively guard against non-public mutation columns when building statistics requests for CREATE STATISTICS / ANALYZE. Fixes: #118537 Release note: None
1 parent 038ffe7 commit 0c896cf

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

pkg/sql/create_stats.go

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,12 @@ func createStatsDefaultColumns(
420420
return err
421421
}
422422

423+
// There shouldn't be any non-public columns, but defensively skip over them
424+
// if there are.
425+
if !col.Public() {
426+
return nil
427+
}
428+
423429
// Skip unsupported virtual computed columns.
424430
if isUnsupportedVirtual(col) {
425431
return nil
@@ -466,9 +472,30 @@ func createStatsDefaultColumns(
466472
continue
467473
}
468474

469-
colIDs := make([]descpb.ColumnID, i+1)
475+
colIDs := make([]descpb.ColumnID, 0, i+1)
470476
for j := 0; j <= i; j++ {
471-
colIDs[j] = desc.GetPrimaryIndex().GetKeyColumnID(j)
477+
col, err := catalog.MustFindColumnByID(desc, desc.GetPrimaryIndex().GetKeyColumnID(j))
478+
if err != nil {
479+
return nil, err
480+
}
481+
482+
// There shouldn't be any non-public columns, but defensively skip over
483+
// them if there are.
484+
if !col.Public() {
485+
continue
486+
}
487+
488+
// Skip unsupported virtual computed columns.
489+
if isUnsupportedVirtual(col) {
490+
continue
491+
}
492+
colIDs = append(colIDs, col.GetID())
493+
}
494+
495+
// Do not attempt to create multi-column stats with < 2 columns. This can
496+
// happen when an index contains only virtual computed columns.
497+
if len(colIDs) < 2 {
498+
continue
472499
}
473500

474501
// Remember the requested stats so we don't request duplicates.
@@ -503,16 +530,23 @@ func createStatsDefaultColumns(
503530
if err != nil {
504531
return nil, err
505532
}
533+
534+
// There shouldn't be any non-public columns, but defensively skip them
535+
// if there are.
536+
if !col.Public() {
537+
continue
538+
}
539+
506540
// Skip unsupported virtual computed columns.
507541
if isUnsupportedVirtual(col) {
508542
continue
509543
}
510544
colIDs = append(colIDs, col.GetID())
511545
}
512546

513-
// Do not attempt to create multi-column stats with no columns. This
514-
// can happen when an index contains only virtual computed columns.
515-
if len(colIDs) == 0 {
547+
// Do not attempt to create multi-column stats with < 2 columns. This can
548+
// happen when an index contains only virtual computed columns.
549+
if len(colIDs) < 2 {
516550
continue
517551
}
518552

pkg/sql/logictest/testdata/logic_test/distsql_stats

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,3 +2670,38 @@ upper_bound range_rows distinct_range_rows equal_rows
26702670

26712671
statement ok
26722672
RESET enable_create_stats_using_extremes
2673+
2674+
# Regression test for #118537. Do not create stats on non-public mutation
2675+
# columns.
2676+
statement ok
2677+
CREATE TABLE t118537 (
2678+
a INT,
2679+
PRIMARY KEY (a) USING HASH WITH (bucket_count = 3)
2680+
)
2681+
2682+
statement ok
2683+
INSERT INTO t118537 SELECT generate_series(0, 9)
2684+
2685+
statement ok
2686+
SET CLUSTER SETTING jobs.debug.pausepoints = 'newschemachanger.before.exec'
2687+
2688+
skipif config local-legacy-schema-changer
2689+
statement error job \d+ was paused before it completed with reason: pause point "newschemachanger.before.exec" hit
2690+
ALTER TABLE t118537 ALTER PRIMARY KEY USING COLUMNS (a) USING HASH
2691+
2692+
statement ok
2693+
CREATE STATISTICS mutation FROM t118537
2694+
2695+
query TTIB colnames
2696+
SELECT statistics_name, column_names, row_count, histogram_id IS NOT NULL AS has_histogram
2697+
FROM [SHOW STATISTICS FOR TABLE t118537]
2698+
ORDER BY statistics_name, column_names::STRING
2699+
----
2700+
statistics_name column_names row_count has_histogram
2701+
mutation {a} 10 true
2702+
2703+
statement ok
2704+
SET CLUSTER SETTING jobs.debug.pausepoints = ''
2705+
2706+
statement ok
2707+
RESUME JOB (SELECT job_id FROM crdb_internal.jobs WHERE description LIKE 'ALTER TABLE %t118537 ALTER PRIMARY KEY USING COLUMNS (a) USING HASH' AND status = 'paused' FETCH FIRST 1 ROWS ONLY)

0 commit comments

Comments
 (0)