aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFujii Masao <fujii@postgresql.org>2014-12-18 21:13:52 +0900
committerFujii Masao <fujii@postgresql.org>2014-12-18 21:13:52 +0900
commit19e065c0492c34fbccbd2c3707ba68cff14195a3 (patch)
treef34ea79704758b2adcaf1e8beafc4d77035d2b5a /src
parentccf292cd2ec16c69ddfee3bf72afe113a7595e00 (diff)
downloadpostgresql-19e065c0492c34fbccbd2c3707ba68cff14195a3.tar.gz
postgresql-19e065c0492c34fbccbd2c3707ba68cff14195a3.zip
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
Diffstat (limited to 'src')
-rw-r--r--src/backend/utils/adt/numeric.c11
-rw-r--r--src/test/regress/expected/numeric.out38
-rw-r--r--src/test/regress/sql/numeric.sql4
3 files changed, 50 insertions, 3 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index c73f9bc005a..d841b6fa8b1 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -1325,11 +1325,16 @@ generate_series_step_numeric(PG_FUNCTION_ARGS)
/*
* Use fctx to keep state from call to call. Seed current with the
- * original start value.
+ * original start value. We must copy the start_num and stop_num
+ * values rather than pointing to them, since we may have detoasted
+ * them in the per-call context.
*/
- init_var_from_num(start_num, &fctx->current);
- init_var_from_num(stop_num, &fctx->stop);
+ init_var(&fctx->current);
+ init_var(&fctx->stop);
init_var(&fctx->step);
+
+ set_var_from_num(start_num, &fctx->current);
+ set_var_from_num(stop_num, &fctx->stop);
set_var_from_var(&steploc, &fctx->step);
funcctx->user_fctx = fctx;
diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out
index ee6cb50d5a6..9d6814564df 100644
--- a/src/test/regress/expected/numeric.out
+++ b/src/test/regress/expected/numeric.out
@@ -1461,3 +1461,41 @@ select (i / (10::numeric ^ 131071))::numeric(1,0)
9
(4 rows)
+-- Check usage with variables
+select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j;
+ i | j
+---+---
+ 1 | 1
+ 1 | 2
+ 1 | 3
+ 2 | 2
+ 2 | 3
+ 3 | 3
+(6 rows)
+
+select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j;
+ i | j
+---+---
+ 1 | 1
+ 2 | 1
+ 2 | 2
+ 3 | 1
+ 3 | 2
+ 3 | 3
+(6 rows)
+
+select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j;
+ i | j
+---+---
+ 1 | 1
+ 1 | 2
+ 1 | 3
+ 1 | 4
+ 1 | 5
+ 2 | 1
+ 2 | 3
+ 2 | 5
+ 3 | 1
+ 3 | 4
+(10 rows)
+
diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql
index a7e92ac3ccf..1633e4c3752 100644
--- a/src/test/regress/sql/numeric.sql
+++ b/src/test/regress/sql/numeric.sql
@@ -854,3 +854,7 @@ select (i / (10::numeric ^ 131071))::numeric(1,0)
from generate_series(6 * (10::numeric ^ 131071),
9 * (10::numeric ^ 131071),
10::numeric ^ 131071) as a(i);
+-- Check usage with variables
+select * from generate_series(1::numeric, 3::numeric) i, generate_series(i,3) j;
+select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,i) j;
+select * from generate_series(1::numeric, 3::numeric) i, generate_series(1,5,i) j;