plpgsql fails to parse 1_000..1_000 as 1000..1000 in FOR loops:
DO $$
DECLARE
i int;
BEGIN
FOR i IN 1_000..1_000 LOOP
END LOOP;
END $$;
ERROR: syntax error at or near "1_000."
LINE 5: FOR i IN 1_000..1_000 LOOP
The scan.l defines rule "numericfail" to handle this ambiguity without
requiring extra whitespace or parenthesis around the integer literals.
But the rule only accepts digits 0-9. Again, an oversight in
faff8f8e47. Fixed in the attached patch.
--
Erik
>From 7e51d9ea7ef2ffc2a2b8c831533a382a5493575b Mon Sep 17 00:00:00 2001
From: Erik Wienhold <[email protected]>
Date: Wed, 15 May 2024 02:43:12 +0200
Subject: [PATCH] plpgsql: fix parsing of integer range with underscores
Fix lexer rule "numericfail" that ensures that we parse 1_000..1_000 as
1000..1000 instead of failing with 'syntax error at or near "1_000."' or
requiring extra whitespace/parenthesis to resolve the ambiguity.
Oversight in faff8f8e47 which added underscores to numeric literals.
---
src/backend/parser/scan.l | 2 +-
src/fe_utils/psqlscan.l | 2 +-
src/interfaces/ecpg/preproc/pgc.l | 2 +-
src/test/regress/expected/numerology.out | 7 +++++++
src/test/regress/sql/numerology.sql | 8 ++++++++
5 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index 5eaadf53b2..a8e504ad09 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -407,7 +407,7 @@ octfail 0[oO]_?
binfail 0[bB]_?
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
-numericfail {decdigit}+\.\.
+numericfail {decinteger}\.\.
real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
realfail ({decinteger}|{numeric})[Ee][-+]
diff --git a/src/fe_utils/psqlscan.l b/src/fe_utils/psqlscan.l
index c9df0594fd..7780151434 100644
--- a/src/fe_utils/psqlscan.l
+++ b/src/fe_utils/psqlscan.l
@@ -343,7 +343,7 @@ octfail 0[oO]_?
binfail 0[bB]_?
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
-numericfail {decdigit}+\.\.
+numericfail {decinteger}\.\.
real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
realfail ({decinteger}|{numeric})[Ee][-+]
diff --git a/src/interfaces/ecpg/preproc/pgc.l b/src/interfaces/ecpg/preproc/pgc.l
index bcfbd0978b..7744d2facf 100644
--- a/src/interfaces/ecpg/preproc/pgc.l
+++ b/src/interfaces/ecpg/preproc/pgc.l
@@ -376,7 +376,7 @@ octfail 0[oO]_?
binfail 0[bB]_?
numeric (({decinteger}\.{decinteger}?)|(\.{decinteger}))
-numericfail {decdigit}+\.\.
+numericfail {decinteger}\.\.
real ({decinteger}|{numeric})[Ee][-+]?{decinteger}
realfail ({decinteger}|{numeric})[Ee][-+]
diff --git a/src/test/regress/expected/numerology.out b/src/test/regress/expected/numerology.out
index f662a5050a..86caccbbc5 100644
--- a/src/test/regress/expected/numerology.out
+++ b/src/test/regress/expected/numerology.out
@@ -297,6 +297,13 @@ SELECT 1_000.5e0_1;
10005
(1 row)
+DO $$
+DECLARE
+ i int;
+BEGIN
+ FOR i IN 1_000..1_000 LOOP
+ END LOOP;
+END $$;
-- error cases
SELECT _100;
ERROR: column "_100" does not exist
diff --git a/src/test/regress/sql/numerology.sql b/src/test/regress/sql/numerology.sql
index 1941c58e68..eb8d4e48d7 100644
--- a/src/test/regress/sql/numerology.sql
+++ b/src/test/regress/sql/numerology.sql
@@ -77,6 +77,14 @@ SELECT 1_000.;
SELECT .000_005;
SELECT 1_000.5e0_1;
+DO $$
+DECLARE
+ i int;
+BEGIN
+ FOR i IN 1_000..1_000 LOOP
+ END LOOP;
+END $$;
+
-- error cases
SELECT _100;
SELECT 100_;
--
2.45.1