Skip to content

Commit 45370c1

Browse files
Make estimate_gapfill_groups return double as caught by LLM fuzzer (#9904)
Caught by LLM fuzzer: new routine estimating number of gapfill groups returned int instead of double, it is now fixed.
1 parent d801f80 commit 45370c1

3 files changed

Lines changed: 38 additions & 4 deletions

File tree

tsl/src/nodes/gapfill/gapfill_plan.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -577,8 +577,8 @@ gapfill_build_pathtarget(PathTarget *pt_upper, PathTarget *pt_path, PathTarget *
577577
}
578578
}
579579

580-
static int
581-
estimate_gapfill_groups(PlannerInfo *root, int path_rows)
580+
static double
581+
estimate_gapfill_groups(PlannerInfo *root, double path_rows)
582582
{
583583
#if PG16_GE
584584
List *group_exprs = get_sortgrouplist_exprs(root->processed_groupClause, root->processed_tlist);
@@ -601,7 +601,7 @@ estimate_gapfill_groups(PlannerInfo *root, int path_rows)
601601
group_exprs_without_gapfill = lappend(group_exprs_without_gapfill, group_expr);
602602
}
603603
}
604-
int num_groups = 1;
604+
double num_groups = 1.0;
605605
if (group_exprs_without_gapfill != NULL)
606606
{
607607
num_groups = estimate_num_groups(root, group_exprs_without_gapfill, path_rows, NULL, NULL);
@@ -633,7 +633,7 @@ gapfill_path_create(PlannerInfo *root, Path *subpath, FuncExpr *func)
633633

634634
/* If we can estimate gapfills, we should estimate number of non-gapfill groups
635635
* as gapfills will be repeated for each group. */
636-
int num_groups = 1;
636+
double num_groups = 1.0;
637637
if (gapfill_rows > 0)
638638
{
639639
num_groups = estimate_gapfill_groups(root, subpath->rows);

tsl/test/shared/expected/gapfill_bug.out

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,3 +489,24 @@ SELECT * FROM STATS LEFT JOIN VOLUME USING (bucket);
489489
DROP TABLE gf8844_table1;
490490
DROP TABLE gf8844_table2;
491491
RESET timezone;
492+
-- Test that there is no overflow when number of gapfill groups exceeds INT_MAX
493+
CREATE TABLE gf_t1(t int, d int);
494+
INSERT INTO gf_t1 SELECT i % 10, i FROM generate_series(1, 50000) i;
495+
ANALYZE gf_t1;
496+
-- Cross join: 50000 * 50000 = 2.5e9 estimated rows, exceeding INT_MAX (2,147,483,647).
497+
-- GROUP BY with high-cardinality columns makes the aggregate estimate ~2.5e9 groups.
498+
EXPLAIN (costs off) SELECT time_bucket_gapfill(1, t1.t, 0, 10), t1.d, t2.d
499+
FROM gf_t1 t1, gf_t1 t2
500+
GROUP BY 1, 2, 3;
501+
--- QUERY PLAN ---
502+
Custom Scan (GapFill)
503+
-> Sort
504+
Sort Key: t1.d, t2.d, (time_bucket_gapfill(1, t1.t, 0, 10))
505+
-> HashAggregate
506+
Group Key: time_bucket_gapfill(1, t1.t, 0, 10), t1.d, t2.d
507+
-> Nested Loop
508+
-> Seq Scan on gf_t1 t1
509+
-> Materialize
510+
-> Seq Scan on gf_t1 t2
511+
512+
drop table gf_t1 cascade;

tsl/test/shared/sql/gapfill_bug.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,16 @@ DROP TABLE gf8844_table1;
279279
DROP TABLE gf8844_table2;
280280

281281
RESET timezone;
282+
283+
-- Test that there is no overflow when number of gapfill groups exceeds INT_MAX
284+
CREATE TABLE gf_t1(t int, d int);
285+
INSERT INTO gf_t1 SELECT i % 10, i FROM generate_series(1, 50000) i;
286+
ANALYZE gf_t1;
287+
288+
-- Cross join: 50000 * 50000 = 2.5e9 estimated rows, exceeding INT_MAX (2,147,483,647).
289+
-- GROUP BY with high-cardinality columns makes the aggregate estimate ~2.5e9 groups.
290+
EXPLAIN (costs off) SELECT time_bucket_gapfill(1, t1.t, 0, 10), t1.d, t2.d
291+
FROM gf_t1 t1, gf_t1 t2
292+
GROUP BY 1, 2, 3;
293+
294+
drop table gf_t1 cascade;

0 commit comments

Comments
 (0)