Minor irritant with comment parsing in a function (SQL) body

Started by Richard Huxtonover 22 years ago6 messagesbugs
Jump to latest
#1Richard Huxton
dev@archonet.com

Versions: 7.3, 7.4beta (not latest)
Applies to SQL functions, but not apparently to plpgsql (because of the
different parser, I presume).

This is really a "doctor it hurts when I..." thing - the fact that I've never
come across it before must mean it's pretty hard to trigger.

The first version of this function compiles fine, the second doesn't.

CREATE OR REPLACE FUNCTION zzz_test () RETURNS text AS '
SELECT ''hello world''::text;
-- SELECT ''goodbye world''
' LANGUAGE 'SQL';

CREATE OR REPLACE FUNCTION zzz_test () RETURNS text AS '
SELECT ''hello world''
-- SELECT ''goodbye world''
::text;
' LANGUAGE 'SQL';

ERROR: parser: unterminated quoted string at or near "'hello world'
-- SELECT 'goodbye world'
::text;
"

It took forever to find a simple reproducible example, but the rules seem to
be:
1. You must have quoting at the end of both adjacent lines
2. Both lines must be within a single SQL statement.
3. You must use the -- comment, not /* ... */

Originally spotted with a formulation like:
AND type1 = ''A''
AND type2 = ''B''
...
I commented one test and got an error message.

--
Richard Huxton
Archonet Ltd

#2Peter Eisentraut
peter_e@gmx.net
In reply to: Richard Huxton (#1)
Re: Minor irritant with comment parsing in a function (SQL)

Richard Huxton writes:

CREATE OR REPLACE FUNCTION zzz_test () RETURNS text AS '
SELECT ''hello world''
-- SELECT ''goodbye world''
::text;
' LANGUAGE 'SQL';

ERROR: parser: unterminated quoted string at or near "'hello world'
-- SELECT 'goodbye world'
::text;

That's a good one. The bug is actually independent of the function
definition, but you cannot easily reproduce it in psql, because psql cuts
out -- comment before sending the command to the server. Here's how one
could do it:

cmd=$(echo -e "SELECT 'hello world'\n-- SELECT 'goodbye world'\n::text;")
psql -c "$cmd"

The problem is strings of this form:

'foo'
'bar'

This is equivalent to 'foobar'. Comments are also allowed between the
parts:

'foo'
-- abc
'bar'

Still equivalent to 'foobar'. In your case it's scanning the string
similar to

'hello world'
-- SELECT 'goodbye world
'\n::text;

Hence the complain the the string is not terminated.

The bug here is that the scanner doesn't know that a newline (or end of
input) is a required as part of a -- comment. If I change the rule

comment ("--"{non_newline}*)

in scan.l to

comment ("--"{non_newline}*){newline}

then the example works. This does not cover the case of a comment at the
end of the input, but a solution shall be forthcoming.

--
Peter Eisentraut peter_e@gmx.net

#3Richard Huxton
dev@archonet.com
In reply to: Peter Eisentraut (#2)
Re: Minor irritant with comment parsing in a function (SQL)

On Wednesday 08 October 2003 20:56, Peter Eisentraut wrote:

Richard Huxton writes:

CREATE OR REPLACE FUNCTION zzz_test () RETURNS text AS '
SELECT ''hello world''
-- SELECT ''goodbye world''

::text;

' LANGUAGE 'SQL';

ERROR: parser: unterminated quoted string at or near "'hello world'
-- SELECT 'goodbye world'

::text;

That's a good one.

Well, I try ;-)

The bug is actually independent of the function
definition, but you cannot easily reproduce it in psql, because psql cuts
out -- comment before sending the command to the server. Here's how one
could do it:

You intrigue me sir...

cmd=$(echo -e "SELECT 'hello world'\n-- SELECT 'goodbye world'\n::text;")
psql -c "$cmd"

The problem is strings of this form:

'foo'
'bar'

This is equivalent to 'foobar'.

Ah - now if I ever new that, I'd forgotten it.

[snip]

In your case it's scanning the string
similar to

'hello world'
-- SELECT 'goodbye world
'\n::text;

Hence the complain the the string is not terminated.

So given the "comment" defn in scan.l, it's seeing the quote as the next token
in the input stream? (Wracks brain thinking back to compiler technologies
class in a decade a long, long way from here).

The bug here is that the scanner doesn't know that a newline (or end of
input) is a required as part of a -- comment. If I change the rule

comment ("--"{non_newline}*)

in scan.l to

comment ("--"{non_newline}*){newline}

then the example works. This does not cover the case of a comment at the
end of the input, but a solution shall be forthcoming.

Ah - in perl you'd be looking for a pattern anchored with a $ - I see what you
mean.

Thanks for the explanation Peter.

--
Richard Huxton
Archonet Ltd

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#2)
Re: Minor irritant with comment parsing in a function (SQL)

Peter Eisentraut <peter_e@gmx.net> writes:

The bug here is that the scanner doesn't know that a newline (or end of
input) is a required as part of a -- comment.

I think the minimum-damage place to fix this is by requiring \n after
{comment} in the horiz_whitespace rule. As is, it's possible for
xqcat to match to a second quote that is in the body of a -- comment.

regards, tom lane

#5Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#4)
Re: Minor irritant with comment parsing in a function (SQL)

Tom Lane writes:

I think the minimum-damage place to fix this is by requiring \n after
{comment} in the horiz_whitespace rule. As is, it's possible for
xqcat to match to a second quote that is in the body of a -- comment.

You mean like this?

horiz_whitespace ({horiz_space}|{comment}{newline})
whitespace_with_newline ({horiz_whitespace}*{newline}{whitespace}*)

That doesn't work. The offending comment in the example is matched to
{whitespace} after {newline} in the second rule. The {horiz_whitespace}*
is matched to empty. We could do

special_whitespace ({space}+|{comment}{newline})
horiz_whitespace ({horiz_space}|{comment})
whitespace_with_newline ({horiz_whitespace}*{newline}{special_whitespace}*)

--
Peter Eisentraut peter_e@gmx.net

#6Bruce Momjian
bruce@momjian.us
In reply to: Richard Huxton (#1)
Re: Minor irritant with comment parsing in a function (SQL) body

Peter has fixed this in CVS. Thanks for the report.

---------------------------------------------------------------------------

Richard Huxton wrote:

Versions: 7.3, 7.4beta (not latest)
Applies to SQL functions, but not apparently to plpgsql (because of the
different parser, I presume).

This is really a "doctor it hurts when I..." thing - the fact that I've never
come across it before must mean it's pretty hard to trigger.

The first version of this function compiles fine, the second doesn't.

CREATE OR REPLACE FUNCTION zzz_test () RETURNS text AS '
SELECT ''hello world''::text;
-- SELECT ''goodbye world''
' LANGUAGE 'SQL';

CREATE OR REPLACE FUNCTION zzz_test () RETURNS text AS '
SELECT ''hello world''
-- SELECT ''goodbye world''
::text;
' LANGUAGE 'SQL';

ERROR: parser: unterminated quoted string at or near "'hello world'
-- SELECT 'goodbye world'
::text;
"

It took forever to find a simple reproducible example, but the rules seem to
be:
1. You must have quoting at the end of both adjacent lines
2. Both lines must be within a single SQL statement.
3. You must use the -- comment, not /* ... */

Originally spotted with a formulation like:
AND type1 = ''A''
AND type2 = ''B''
...
I commented one test and got an error message.

--
Richard Huxton
Archonet Ltd

---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to majordomo@postgresql.org)

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073