Skip to content

Commit 19e065c

Browse files
committed
Ensure variables live across calls in generate_series(numeric, numeric).
In generate_series_step_numeric(), the variables "start_num" and "stop_num" may be potentially freed until the next call. So they should be put in the location which can survive across calls. But previously they were not, and which could cause incorrect behavior of generate_series(numeric, numeric). This commit fixes this problem by copying them on multi_call_memory_ctx. Andrew Gierth
1 parent ccf292c commit 19e065c

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/backend/utils/adt/numeric.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,11 +1325,16 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
13251325

13261326
/*
13271327
* Use fctx to keep state from call to call. Seed current with the
1328-
* original start value.
1328+
* original start value. We must copy the start_num and stop_num
1329+
* values rather than pointing to them, since we may have detoasted
1330+
* them in the per-call context.
13291331
*/
1330-
init_var_from_num(start_num, &fctx->current);
1331-
init_var_from_num(stop_num, &fctx->stop);
1332+
init_var(&fctx->current);
1333+
init_var(&fctx->stop);
13321334
init_var(&fctx->step);
1335+
1336+
set_var_from_num(start_num, &fctx->current);
1337+
set_var_from_num(stop_num, &fctx->stop);
13331338
set_var_from_var(&steploc, &fctx->step);
13341339

13351340
funcctx->user_fctx = fctx;

src/test/regress/expected/numeric.out

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,3 +1461,41 @@ select (i / (10::numeric ^ 131071))::numeric(1,0)
14611461
9
14621462
(4 rows)
14631463

1464+
-- Check usage with variables
1465+
select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j;
1466+
i | j
1467+
---+---
1468+
1 | 1
1469+
1 | 2
1470+
1 | 3
1471+
2 | 2
1472+
2 | 3
1473+
3 | 3
1474+
(6 rows)
1475+
1476+
select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j;
1477+
i | j
1478+
---+---
1479+
1 | 1
1480+
2 | 1
1481+
2 | 2
1482+
3 | 1
1483+
3 | 2
1484+
3 | 3
1485+
(6 rows)
1486+
1487+
select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j;
1488+
i | j
1489+
---+---
1490+
1 | 1
1491+
1 | 2
1492+
1 | 3
1493+
1 | 4
1494+
1 | 5
1495+
2 | 1
1496+
2 | 3
1497+
2 | 5
1498+
3 | 1
1499+
3 | 4
1500+
(10 rows)
1501+

src/test/regress/sql/numeric.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,3 +854,7 @@ select (i / (10::numeric ^ 131071))::numeric(1,0)
854854
from generate_series(6 * (10::numeric ^ 131071),
855855
9 * (10::numeric ^ 131071),
856856
10::numeric ^ 131071) as a(i);
857+
-- Check usage with variables
858+
select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j;
859+
select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j;
860+
select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j;

0 commit comments

Comments
 (0)