There is no ELSEIF construct.
Sure, but it would be nice to throw a syntax error rather than silently accepting the function. Unfortunately the way PL/PgSQL's parser works doesn't make this very easy. (BTW, I think that fixing how we do parsing would be one of the prime motivations for rewriting PL/PgSQL. One possibility would be to integrate the PL/PgSQL parser into the main SQL parser, although there may be a cleaner way to improve PL/PgSQL parsing.)
In any case, given this function:
create or replace function foo() returns int as ' #option dump begin if 5 > 5 then return 10; elseif 5 > 6 then return 15; else return 20; end if; end;' language 'plpgsql';
We produce this parsetree: (helpfully dumped via the undocumented "#option dump" feature)
Functions statements: 2:BLOCK <<*unnamed*>> 3: IF 'SELECT 5 > 5' THEN 4: RETURN 'SELECT 10' 5: EXECSQL 'elseif 5 > 6 then 15 15' ELSE 8: RETURN 'SELECT 20' ENDIF END -- *unnamed*
One way to fix the specific bug reported here would be to add K_ELSEIF to the PL/PgSQL lexer, and then throw a syntax error in the stmt_else production. But that is a very limited fix: if the user specifies any other word in the place of 'elseif', we will not throw a syntax error.
Another solution would be to teach the PL/PgSQL lexer to recognize the initial tokens of every SQL statement (SELECT, UPDATE, and so forth). Right now we just assume an unrecognized word must be the beginning of a SQL statement; if we taught the lexer about the initial tokens of all legal SQL statements, we could reject unrecognized words. But this is kind of ugly as well, as it means duplicating the knowledge about what constitutes a legal SQL statement in multiple places.
Alternatively, we could arrange to have the PL/PgSQL parser pass a block of text it has identified as a possible SQL statement to the main SQL parser; if it produces a syntax error, we can pass that syntax error back to the user. I'm not sure if this would have any negative ramifications, though.
Comments?
(BTW, another thing this example exposes is that we don't issue warnings about trivially-dead-code, such as statements in a basic block that follow a RETURN. This would probably be also worth doing.)
-Neil
---------------------------(end of broadcast)--------------------------- TIP 5: Have you checked our extensive FAQ?
http://www.postgresql.org/docs/faqs/FAQ.html