Thread: FOR integer loop bug?
Postgres 14.2 In commenting on a SO question I came across the below. Given: CREATE OR REPLACE FUNCTION public.for_loop_test() RETURNS void LANGUAGE plpgsql AS $function$ BEGIN FOR i IN 1..10 LOOP RAISE NOTICE '%', i; END LOOP; END; $function$ ; select for_loop_test(); NOTICE: 1 NOTICE: 2 NOTICE: 3 NOTICE: 4 NOTICE: 5 NOTICE: 6 NOTICE: 7 NOTICE: 8 NOTICE: 9 NOTICE: 10 Then, note 1...10: CREATE OR REPLACE FUNCTION public.for_loop_test() RETURNS void LANGUAGE plpgsql AS $function$ BEGIN FOR i IN 1...10 LOOP RAISE NOTICE '%', i; END LOOP; END; $function$ select for_loop_test(); for_loop_test --------------- If you do: FOR i IN 1....10 LOOP or FOR i IN 1.10 LOOP You get: ERROR: syntax error at or near ".." LINE 6: FOR i IN 1....10 LOOP ERROR: syntax error at or near "1.10" LINE 6: FOR i IN 1.10 LOOP respectively. Why is the three period form allowed through and why does it produce no result? -- Adrian Klaver adrian.klaver@aklaver.com
pá 8. 4. 2022 v 19:56 odesílatel Adrian Klaver <adrian.klaver@aklaver.com> napsal:
Postgres 14.2
In commenting on a SO question I came across the below.
Given:
CREATE OR REPLACE FUNCTION public.for_loop_test()
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
FOR i IN 1..10 LOOP
RAISE NOTICE '%', i;
END LOOP;
END;
$function$
;
select for_loop_test();
NOTICE: 1
NOTICE: 2
NOTICE: 3
NOTICE: 4
NOTICE: 5
NOTICE: 6
NOTICE: 7
NOTICE: 8
NOTICE: 9
NOTICE: 10
Then, note 1...10:
CREATE OR REPLACE FUNCTION public.for_loop_test()
RETURNS void
LANGUAGE plpgsql
AS $function$
BEGIN
FOR i IN 1...10 LOOP
RAISE NOTICE '%', i;
END LOOP;
END;
$function$
select for_loop_test();
for_loop_test
---------------
If you do:
FOR i IN 1....10 LOOP
or
FOR i IN 1.10 LOOP
You get:
ERROR: syntax error at or near ".."
LINE 6: FOR i IN 1....10 LOOP
ERROR: syntax error at or near "1.10"
LINE 6: FOR i IN 1.10 LOOP
respectively.
Why is the three period form allowed through and why does it produce no
result?
Maybe
(2022-04-08 19:57:57) postgres=# select .10;
┌──────────┐
│ ?column? │
╞══════════╡
│ 0.10 │
└──────────┘
(1 row)
┌──────────┐
│ ?column? │
╞══════════╡
│ 0.10 │
└──────────┘
(1 row)
--
Adrian Klaver
adrian.klaver@aklaver.com
On 4/8/22 10:58 AM, Pavel Stehule wrote: > > > pá 8. 4. 2022 v 19:56 odesílatel Adrian Klaver > <a > > Why is the three period form allowed through and why does it produce no > result? > > > Maybe > > (2022-04-08 19:57:57) postgres=# select .10; > ┌──────────┐ > │ ?column? │ > ╞══════════╡ > │ 0.10 │ > └──────────┘ > (1 row) Alright so 1...10 is taken as 1::integer .. 0.10::integer CAST results in 0 and ends up as 1..0. This then is covered by: "If the lower bound is greater than the upper bound (or less than, in the REVERSE case), the loop body is not executed at all. No error is raised." Confirmed by: CREATE OR REPLACE FUNCTION utility.for_loop_test() RETURNS void LANGUAGE plpgsql AS $function$ BEGIN FOR i IN REVERSE 1...10 LOOP RAISE NOTICE '%', i; END LOOP; END; $function$ ; select for_loop_test(); NOTICE: 1 NOTICE: 0 for_loop_test --------------- Hmm, I'm going to have to think on this. > > > -- > Adrian Klaver > adrian.klaver@aklaver.com <mailto:adrian.klaver@aklaver.com> > > -- Adrian Klaver adrian.klaver@aklaver.com
On 4/8/22 13:07, Adrian Klaver wrote: > On 4/8/22 10:58 AM, Pavel Stehule wrote: >> >> >> pá 8. 4. 2022 v 19:56 odesílatel Adrian Klaver <a >> >> Why is the three period form allowed through and why does it produce no >> result? >> >> >> Maybe >> >> (2022-04-08 19:57:57) postgres=# select .10; >> ┌──────────┐ >> │ ?column? │ >> ╞══════════╡ >> │ 0.10 │ >> └──────────┘ >> (1 row) > > Alright so 1...10 is taken as 1::integer .. 0.10::integer CAST results in > 0 and ends up as 1..0. This then is covered by: > > "If the lower bound is greater than the upper bound (or less than, in the > REVERSE case), the loop body is not executed at all. No error is raised." > > Confirmed by: > > CREATE OR REPLACE FUNCTION utility.for_loop_test() > RETURNS void > LANGUAGE plpgsql > AS $function$ > BEGIN > FOR i IN REVERSE 1...10 LOOP > RAISE NOTICE '%', i; > END LOOP; > END; > > $function$ > ; > > select for_loop_test(); > NOTICE: 1 > NOTICE: 0 > for_loop_test > --------------- > > Hmm, I'm going to have to think on this. The only thinking is: "That's a bug waiting to happen!" -- Angular momentum makes the world go 'round.
On 4/8/22 11:23, Ron wrote: > On 4/8/22 13:07, Adrian Klaver wrote: >> Hmm, I'm going to have to think on this. > > The only thinking is: "That's a bug waiting to happen!" > That was my first inclination. From here: https://www.postgresql.org/docs/current/plpgsql-control-structures.html#PLPGSQL-CONTROL-STRUCTURES-LOOPS FOR name IN [ REVERSE ] expression .. expression [ BY expression ] LOOP So: CREATE OR REPLACE FUNCTION for_loop_test() RETURNS void LANGUAGE plpgsql AS $function$ BEGIN FOR i IN 1..(2/3.0) LOOP RAISE NOTICE '%', i; END LOOP; END; select for_loop_test(); NOTICE: 1 for_loop_test --------------- Because: select (2/3.0)::int; int4 ------ 1 I find the result from this 1...10 surprising, however I have to believe there is code counting on the equivalent of (2/3.0) working. -- Adrian Klaver adrian.klaver@aklaver.com