Thread: FOR integer loop bug?

FOR integer loop bug?

From
Adrian Klaver
Date:
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



Re: FOR integer loop bug?

From
Pavel Stehule
Date:


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)

 

--
Adrian Klaver
adrian.klaver@aklaver.com


Re: FOR integer loop bug?

From
Adrian Klaver
Date:
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



Re: FOR integer loop bug?

From
Ron
Date:
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.



Re: FOR integer loop bug?

From
Adrian Klaver
Date:
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