Skip to content

Commit 10cad92

Browse files
committed
explain: fix overflow when printing estimated row count
Previously, when the optimizer estimated a very large row count (which is float64), we would first cast it to uint64 (which would work ok in case the count is large - we'd get `max int64 + 1`), and then we would cast it to int64 which can result in a negative number. This is now fixed by adding a check before casting to int64 to cap the value at max int64. Epic: None Release note: None
1 parent bf5ffc4 commit 10cad92

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

pkg/sql/opt/exec/execbuilder/testdata/explain

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2393,3 +2393,36 @@ inner-join (hash)
23932393
│ └── unfiltered-cols: (6-9)
23942394
└── filters
23952395
└── k:6 = a:1 [outer=(1,6), constraints=(/1: (/NULL - ]; /6: (/NULL - ]), fd=(1)==(6), (6)==(1)]
2396+
2397+
# Regression test for overflow when printing out the estimated row count.
2398+
statement ok
2399+
CREATE TABLE very_large_table (k INT PRIMARY KEY);
2400+
2401+
statement ok
2402+
ALTER TABLE very_large_table INJECT STATISTICS '[
2403+
{
2404+
"columns": ["k"],
2405+
"created_at": "2024-01-01 1:00:00.00000+00:00",
2406+
"row_count": 1000000000000,
2407+
"distinct_count": 1000000000000
2408+
}
2409+
]'
2410+
2411+
query T
2412+
EXPLAIN SELECT t1.k FROM very_large_table AS t1, very_large_table AS t2;
2413+
----
2414+
distribution: local
2415+
vectorized: true
2416+
·
2417+
• cross join
2418+
│ estimated row count: 9,223,372,036,854,775,807
2419+
2420+
├── • scan
2421+
│ estimated row count: 1,000,000,000,000 (100% of the table; stats collected <hidden> ago)
2422+
│ table: very_large_table@very_large_table_pkey
2423+
│ spans: FULL SCAN
2424+
2425+
└── • scan
2426+
estimated row count: 1,000,000,000,000 (100% of the table; stats collected <hidden> ago)
2427+
table: very_large_table@very_large_table_pkey
2428+
spans: FULL SCAN

pkg/util/humanizeutil/count.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,24 @@
1111
package humanizeutil
1212

1313
import (
14+
"math"
15+
1416
"github.com/cockroachdb/redact"
1517
"github.com/dustin/go-humanize"
1618
)
1719

1820
// Count formats a unitless integer value like a row count. It uses separating
1921
// commas for large values (e.g. "1,000,000").
2022
func Count(val uint64) redact.SafeString {
23+
if val > math.MaxInt64 {
24+
val = math.MaxInt64
25+
}
2126
return redact.SafeString(humanize.Comma(int64(val)))
2227
}
2328

2429
func Countf(val float64) redact.SafeString {
30+
if val > math.MaxInt64 {
31+
val = math.MaxInt64
32+
}
2533
return redact.SafeString(humanize.Commaf(val))
2634
}

0 commit comments

Comments
 (0)