Bug of PL/pgSQL parser
Dear Sirs!:)I encounted one small problem,working with
PostgreSQL 7.3devel.It can look a
bit strange,but i have to use whitespaces in names of databases,tables,fields
and so on(like "roomno jk").It's possible to create them all and work with them
(INSERT,DELETE,UPDATE),but PL/pgSQL parser(compiler ?) can't execute such
statements.To explain the problem, I took and changed next examples from
pgsql/src/pl/plpgsql/test:
-- ************************************************************
-- * Tables for the patchfield test of PL/pgSQL
-- * $Header: /projects/cvsroot/pgsql/src/pl/plpgsql/test/tables.sql,v 1.1 1998/08/24 19:16:27 momjian Exp $
-- ************************************************************
create table Room (
"roomno jk" char(8), --- common SQL parser eats it
comment text
);
create unique index Room_rno on Room using btree ("roomno jk" bpchar_ops);
create table WSlot (
slotname char(20),
"roomno jk" char(8), --- common SQL parser eats it
slotlink char(20),
backlink char(20)
);
create unique index WSlot_name on WSlot using btree (slotname bpchar_ops);
You also can use such "roomno jk" in DECLARATION of PL/pgSQL procedures and functions :
-- ************************************************************
-- * Trigger procedures and functions for the patchfield
-- * test of PL/pgSQL
-- * $Header: /projects/cvsroot/pgsql/src/pl/plpgsql/test/triggers.sql,v 1.2 2000/10/22 23:25:11 tgl Exp $
-- ************************************************************
-- * AFTER UPDATE on Room
-- * - If room no changes let wall slots follow
-- ************************************************************
PL/pgSQL eats it,he will cry during execution.
create function tg_room_au() returns opaque as '
begin
if new."roomno jk" != old."roomno jk" then
update WSlot set "roomno jk" = new."roomno jk" where "roomno jk" = old."roomno jk";
end if;
return new;
end;
' language 'plpgsql';
create trigger tg_room_au after update
on Room for each row execute procedure tg_room_au();
-- ************************************************************
-- * BEFORE INSERT or UPDATE on WSlot
-- * - Check that room exists
-- ************************************************************
PL/pgSQL also eats it,he will cry during execution.
create function tg_wslot_biu() returns opaque as '
begin
if count(*) = 0 from Room where "roomno jk" = new."roomno jk" then
raise exception ''Room % does not exist'', new."roomno jk";
end if;
return new;
end;
' language 'plpgsql';
create trigger tg_wslot_biu before insert or update
on WSlot for each row execute procedure tg_wslot_biu();
Then do next:
insert into Room values ('001', 'Entrance'); --Everything is ok
Then do it and catch failure:
insert into WSlot values ('WS.001.1a', '001', '', '');
PostgreSQL returns :
psql:/home/eu/SQL/plt/p_test.sql:19: ERROR: parse error at or near "new"
psql:/home/eu/SQL/plt/p_test.sql:20: WARNING: plpgsql: ERROR during compile of tg_wslot_biu near line 3
As you see there's no support for "roomno jk" in PL/pgSQL parser.
To this moment i know nothing serious about flex,lex and yacc,but
a simple look at PL/pgSQL parser shows,that situations of
"roomno jk" are just undefined there.
regards,Eugene
P.S.In case you make patch,please,send me a copy.
I see this on the TODO list:
# Fix PL/PgSQL to handle quoted mixed-case identifiers
Perhaps you could make a view (alias the names with spaces) to work on?
Show quoted text
On Fri, 2002-07-12 at 06:31, eutm wrote:
Dear Sirs!:)I encounted one small problem,working with
PostgreSQL 7.3devel.It can look a
bit strange,but i have to use whitespaces in names of databases,tables,fields
and so on(like "roomno jk").It's possible to create them all and work with them
(INSERT,DELETE,UPDATE),but PL/pgSQL parser(compiler ?) can't execute such
statements.To explain the problem, I took and changed next examples from
pgsql/src/pl/plpgsql/test:-- ************************************************************
-- * Tables for the patchfield test of PL/pgSQL
-- * $Header: /projects/cvsroot/pgsql/src/pl/plpgsql/test/tables.sql,v 1.1 1998/08/24 19:16:27 momjian Exp $
-- ************************************************************create table Room (
"roomno jk" char(8), --- common SQL parser eats it
comment text
);
create unique index Room_rno on Room using btree ("roomno jk" bpchar_ops);create table WSlot (
slotname char(20),
"roomno jk" char(8), --- common SQL parser eats it
slotlink char(20),
backlink char(20)
);
create unique index WSlot_name on WSlot using btree (slotname bpchar_ops);You also can use such "roomno jk" in DECLARATION of PL/pgSQL procedures and functions :
-- ************************************************************
-- * Trigger procedures and functions for the patchfield
-- * test of PL/pgSQL
-- * $Header: /projects/cvsroot/pgsql/src/pl/plpgsql/test/triggers.sql,v 1.2 2000/10/22 23:25:11 tgl Exp $
-- ************************************************************
-- * AFTER UPDATE on Room
-- * - If room no changes let wall slots follow
-- ************************************************************PL/pgSQL eats it,he will cry during execution.
create function tg_room_au() returns opaque as '
begin
if new."roomno jk" != old."roomno jk" then
update WSlot set "roomno jk" = new."roomno jk" where "roomno jk" = old."roomno jk";
end if;
return new;
end;
' language 'plpgsql';create trigger tg_room_au after update
on Room for each row execute procedure tg_room_au();-- ************************************************************
-- * BEFORE INSERT or UPDATE on WSlot
-- * - Check that room exists
-- ************************************************************PL/pgSQL also eats it,he will cry during execution.
create function tg_wslot_biu() returns opaque as '
begin
if count(*) = 0 from Room where "roomno jk" = new."roomno jk" then
raise exception ''Room % does not exist'', new."roomno jk";
end if;
return new;
end;
' language 'plpgsql';create trigger tg_wslot_biu before insert or update
on WSlot for each row execute procedure tg_wslot_biu();Then do next:
insert into Room values ('001', 'Entrance'); --Everything is okThen do it and catch failure:
insert into WSlot values ('WS.001.1a', '001', '', '');PostgreSQL returns :
psql:/home/eu/SQL/plt/p_test.sql:19: ERROR: parse error at or near "new"
psql:/home/eu/SQL/plt/p_test.sql:20: WARNING: plpgsql: ERROR during compile of tg_wslot_biu near line 3As you see there's no support for "roomno jk" in PL/pgSQL parser.
To this moment i know nothing serious about flex,lex and yacc,but
a simple look at PL/pgSQL parser shows,that situations of
"roomno jk" are just undefined there.
regards,Eugene
P.S.In case you make patch,please,send me a copy.---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
"eutm" <eutm@yandex.ru> writes:
Dear Sirs!:)I encounted one small problem,working with
PostgreSQL 7.3devel.It can look a
bit strange,but i have to use whitespaces in names of databases,tables,fields
and so on(like "roomno jk").It's possible to create them all and work with them
(INSERT,DELETE,UPDATE),but PL/pgSQL parser(compiler ?) can't execute such
statements.
Yeah, this is a known bug: the plpgsql lexer doesn't really handle
quoted identifiers correctly. (It effectively acts like double-quote
is just another letter, which of course falls down on cases like
embedded whitespace.) If you have any experience with writing flex
rules, perhaps you'd care to submit a patch.
regards, tom lane