psql misbehaves because of a simple typo

Started by Serguei Mokhovabout 24 years ago14 messages
#1Serguei Mokhov
sa_mokho@alcor.concordia.ca

Hi,

Is it me (who hasn't read some FAQ or a doc/man page) or
it's a bug in the psql interactive terminal?

A sample session is provided at the bottom. I just typed
a simple CREATE TABLE command and did not put closing
parenthesis (I was typing too fast); I did put a semicolon, however.
psql gave me no error message whatsoever and accepted whatever
input afterwards and ignored it with the exception of \commands.

Was this reported? Do you need some other info?
Logs?

o I have a RHL7.1 and the tarball of 7.2b3 downloaded
from the website.

o # ./configure --enable-nls --enable-multibyte --enable-locale --enable-debug --enable-cassert

Here is the session:

[regress72b3@gunn regress72b3]$ /usr/local/pgsql/bin/psql test
Welcome to psql, the PostgreSQL interactive terminal.

Type: \copyright for distribution terms
\h for help with SQL commands
\? for help on internal slash commands
\g or terminate with semicolon to execute query
\q to quit

test=# create table test2(id serial;
test(# select version();
test(# ?
test(# \?
\a toggle between unaligned and aligned output mode
\c[onnect] [DBNAME|- [USER]]
connect to new database (currently "test")
\C TITLE set table title
\cd [DIRNAME] change the current working directory
\copy ... perform SQL COPY with data stream to the client host
\copyright show PostgreSQL usage and distribution terms
\d TABLE describe table (or view, index, sequence)
\d{t|i|s|v}... list tables/indexes/sequences/views
\d{p|S|l} list access privileges, system tables, or large objects
\da list aggregate functions
\dd NAME show comment for table, type, function, or operator
\df list functions
\do list operators
\dT list data types
\e FILENAME edit the current query buffer or file with external editor
\echo TEXT write text to standard output
\encoding ENCODING set client encoding
\f STRING set field separator
\g FILENAME send SQL command to server (and write results to file or |pipe)
\h NAME help on syntax of SQL commands, * for all commands
\H toggle HTML output mode (currently off)
\i FILENAME execute commands from file
\l list all databases
\lo_export, \lo_import, \lo_list, \lo_unlink
large object operations
\o FILENAME send all query results to file or |pipe
\p show the content of the current query buffer
\pset VAR set table output option (VAR := {format|border|expanded|
fieldsep|null|recordsep|tuples_only|title|tableattr|pager})
\q quit psql
\qecho TEXT write text to query output stream (see \o)
\r reset (clear) the query buffer
\s FILENAME print history or save it to file
\set NAME VALUE set internal variable
\t show only rows (currently off)
\T TEXT set HTML table tag attributes
\unset NAME unset (delete) internal variable
\w FILENAME write current query buffer to file
\x toggle expanded output (currently off)
\z list table access privileges
\! [COMMAND] execute command in shell or start interactive shell
test-# select version();
ERROR: parser: parse error at or near ";"
test=# select version();
version
-------------------------------------------------------------
PostgreSQL 7.2b3 on i686-pc-linux-gnu, compiled by GCC 2.96
(1 row)

test=#

--
Serguei A. Mokhov

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Serguei Mokhov (#1)
Re: psql misbehaves because of a simple typo

"Serguei Mokhov" <sa_mokho@alcor.concordia.ca> writes:

Is it me (who hasn't read some FAQ or a doc/man page) or
it's a bug in the psql interactive terminal?

Both. There's a bug there, but it's not the one you think.
psql seems to forget that it's got unmatched parentheses in the
buffer after executing a \? command. Watch the prompt:

regression=# (select
regression(# \?
... yadda yadda ...
regression-# 2;
ERROR: parser: parse error at or near ";"
regression=# (select
regression(# \?
... yadda yadda ...
regression-# 2);
?column?
----------
2
(1 row)

In the first example, it should not have thought that it had
a complete command after "2;".

regards, tom lane

#3Serguei Mokhov
sa_mokho@alcor.concordia.ca
In reply to: Serguei Mokhov (#1)
Re: psql misbehaves because of a simple typo

----- Original Message -----
From: Tom Lane <tgl@sss.pgh.pa.us>
Sent: Sunday, December 02, 2001 10:16 AM

"Serguei Mokhov" <sa_mokho@alcor.concordia.ca> writes:

Is it me (who hasn't read some FAQ or a doc/man page) or
it's a bug in the psql interactive terminal?

Both.

Oops.

There's a bug there, but it's not the one you think.

No, that's what I thought.

psql seems to forget that it's got unmatched parentheses in the
buffer after executing a \? command. Watch the prompt:

... and that's what I've witnessed.

Sorry for the 'false' alarm. This feature just bumped
into me unexpectedly.

-s

#4Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Tom Lane (#2)
Re: psql misbehaves because of a simple typo

"Serguei Mokhov" <sa_mokho@alcor.concordia.ca> writes:

Is it me (who hasn't read some FAQ or a doc/man page) or
it's a bug in the psql interactive terminal?

Both. There's a bug there, but it's not the one you think.
psql seems to forget that it's got unmatched parentheses in the
buffer after executing a \? command. Watch the prompt:

regression=# (select
regression(# \?
... yadda yadda ...
regression-# 2;
ERROR: parser: parse error at or near ";"
regression=# (select
regression(# \?
... yadda yadda ...
regression-# 2);
?column?
----------
2
(1 row)

In the first example, it should not have thought that it had
a complete command after "2;".

The actual code that resets the paren level is:

/* backslash command */
else if (was_bslash)
{
const char *end_of_cmd = NULL;

paren_level = 0;
line[i - prevlen] = '\0'; /* overwrites backslash */

I believe this code is good. If someone issues a backslash command,
they probably want to get out of they paren nesting, or may not even
know they are in paren nesting, as Serguei did not in the example shown.

While it doesn't seem logical, it does help prevent people from getting
stuck in psql. The fact that backslash commands inside parens clear the
counter is a minor anoyance but resonable behavior.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#4)
Re: psql misbehaves because of a simple typo

Bruce Momjian <pgman@candle.pha.pa.us> writes:

The fact that backslash commands inside parens clear the
counter is a minor anoyance but resonable behavior.

If they cleared the command buffer too, it might be construed
as novice-friendly behavior (though I'd still call it broken).
However, letting the counter get out of sync with the buffer
contents cannot be called anything but a bug.

regards, tom lane

#6Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Tom Lane (#5)
Re: psql misbehaves because of a simple typo

Bruce Momjian <pgman@candle.pha.pa.us> writes:

The fact that backslash commands inside parens clear the
counter is a minor anoyance but resonable behavior.

If they cleared the command buffer too, it might be construed
as novice-friendly behavior (though I'd still call it broken).
However, letting the counter get out of sync with the buffer
contents cannot be called anything but a bug.

OK, so what do we want to do? Clearing the buffer on a any backslash
command is clearly not what we want to do. Should we clear the buffer
on a backslash command _only_ if the number of paren's is not even? If
we don't clear the counter on a backslash command with uneven parens, do
we risk trapping people in psql?

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
#7Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Tom Lane (#5)
Re: psql misbehaves because of a simple typo

Bruce Momjian <pgman@candle.pha.pa.us> writes:

The fact that backslash commands inside parens clear the
counter is a minor anoyance but resonable behavior.

If they cleared the command buffer too, it might be construed
as novice-friendly behavior (though I'd still call it broken).
However, letting the counter get out of sync with the buffer
contents cannot be called anything but a bug.

Maybe we should clear the counter _only_ if the user clears the buffer,
or sends the query to the backend with \g.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: Bruce Momjian (#6)
Re: psql misbehaves because of a simple typo

Bruce Momjian <pgman@candle.pha.pa.us> writes:

OK, so what do we want to do? Clearing the buffer on a any backslash
command is clearly not what we want to do. Should we clear the buffer
on a backslash command _only_ if the number of paren's is not even? If
we don't clear the counter on a backslash command with uneven parens, do
we risk trapping people in psql?

"Trap"? AFAIK \q works in any case.

\r should reset both the buffer and the counter, and seems to do so,
though I'm not quite seeing where it manages to accomplish the latter
(command.c only resets query_buf). \e should probably provoke a
recomputation of paren_level after the edit occurs. Offhand I do not
think that any other backslash commands should reset either the buffer
or the counter. Peter, your thoughts?

regards, tom lane

#9Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Tom Lane (#8)
Re: psql misbehaves because of a simple typo

Bruce Momjian <pgman@candle.pha.pa.us> writes:

OK, so what do we want to do? Clearing the buffer on a any backslash
command is clearly not what we want to do. Should we clear the buffer
on a backslash command _only_ if the number of paren's is not even? If
we don't clear the counter on a backslash command with uneven parens, do
we risk trapping people in psql?

"Trap"? AFAIK \q works in any case.

\r should reset both the buffer and the counter, and seems to do so,
though I'm not quite seeing where it manages to accomplish the latter
(command.c only resets query_buf). \e should probably provoke a

See mainloop.c, line 450. Any backshash command resets the counter.

recomputation of paren_level after the edit occurs. Offhand I do not
think that any other backslash commands should reset either the buffer
or the counter. Peter, your thoughts?

Re-doing it for the editor is interesting. The other items like quotes
and stuff should also probably be recomputed too.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
#10Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Tom Lane (#8)
1 attachment(s)
Re: psql misbehaves because of a simple typo

Bruce Momjian <pgman@candle.pha.pa.us> writes:

OK, so what do we want to do? Clearing the buffer on a any backslash
command is clearly not what we want to do. Should we clear the buffer
on a backslash command _only_ if the number of paren's is not even? If
we don't clear the counter on a backslash command with uneven parens, do
we risk trapping people in psql?

"Trap"? AFAIK \q works in any case.

\r should reset both the buffer and the counter, and seems to do so,
though I'm not quite seeing where it manages to accomplish the latter
(command.c only resets query_buf). \e should probably provoke a
recomputation of paren_level after the edit occurs. Offhand I do not
think that any other backslash commands should reset either the buffer
or the counter. Peter, your thoughts?

OK, here is a patch for 7.3. It clears the paren counter only when the
buffer is cleared. Forget what I said about recomputing quotes. You
can't use backslash commands while you are in quotes.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Attachments:

/bjm/difftext/plainDownload
Index: src/bin/psql/mainloop.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/mainloop.c,v
retrieving revision 1.43
diff -c -r1.43 mainloop.c
*** src/bin/psql/mainloop.c	2001/11/05 17:46:31	1.43
--- src/bin/psql/mainloop.c	2001/12/28 04:41:48
***************
*** 447,453 ****
  			{
  				const char *end_of_cmd = NULL;
  
- 				paren_level = 0;
  				line[i - prevlen] = '\0';		/* overwrites backslash */
  
  				/* is there anything else on the line for the command? */
--- 447,452 ----
***************
*** 469,474 ****
--- 468,476 ----
  												 &end_of_cmd);
  
  				success = slashCmdStatus != CMD_ERROR;
+ 
+ 				if (query_buf->len == 0)
+ 					paren_level = 0;
  
  				if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) &&
  					query_buf->len == 0)
#11Serguei Mokhov
serguei_mokhov@yahoo.com
In reply to: Bruce Momjian (#9)
Re: psql misbehaves because of a simple typo
--- Bruce Momjian <pgman@candle.pha.pa.us> wrote:

[...]

See mainloop.c, line 450. Any backshash command resets the counter.

recomputation of paren_level after the edit occurs. Offhand I do not
think that any other backslash commands should reset either the buffer
or the counter. Peter, your thoughts?

Re-doing it for the editor is interesting. The other items like quotes
and stuff should also probably be recomputed too.

Whooof! Looks like psql's sitting on a quite big can of worms.
You don't plan to take them all out before 7.2, do you?

=====
--
Serguei A. Mokhov <mailto:mokhov@cs.concordia.ca>

__________________________________________________
Do You Yahoo!?
Send your FREE holiday greetings online!
http://greetings.yahoo.com

#12Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Serguei Mokhov (#11)
Re: psql misbehaves because of a simple typo
--- Bruce Momjian <pgman@candle.pha.pa.us> wrote:

[...]

See mainloop.c, line 450. Any backshash command resets the counter.

recomputation of paren_level after the edit occurs. Offhand I do not
think that any other backslash commands should reset either the buffer
or the counter. Peter, your thoughts?

Re-doing it for the editor is interesting. The other items like quotes
and stuff should also probably be recomputed too.

Whooof! Looks like psql's sitting on a quite big can of worms.
You don't plan to take them all out before 7.2, do you?

No, this is all 7.3 discussion.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026
#13Peter Eisentraut
peter_e@gmx.net
In reply to: Bruce Momjian (#10)
Re: psql misbehaves because of a simple typo

Bruce Momjian writes:

OK, here is a patch for 7.3. It clears the paren counter only when the
buffer is cleared. Forget what I said about recomputing quotes. You
can't use backslash commands while you are in quotes.

I don't think this works when the command is \g because you're testing for
the cleared buffer too early. Look at what happens under "if
(slashCmdStatus == CMD_SEND)". The test should be after that (around line
489 in original copy).

--
Peter Eisentraut peter_e@gmx.net

#14Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Peter Eisentraut (#13)
1 attachment(s)
Re: psql misbehaves because of a simple typo

Bruce Momjian writes:

OK, here is a patch for 7.3. It clears the paren counter only when the
buffer is cleared. Forget what I said about recomputing quotes. You
can't use backslash commands while you are in quotes.

I don't think this works when the command is \g because you're testing for
the cleared buffer too early. Look at what happens under "if
(slashCmdStatus == CMD_SEND)". The test should be after that (around line
489 in original copy).

Are you sure?

test=> (select
test(> \g
ERROR: parser: parse error at or near ""
test(>

I now see the next \p kills me:

test(> \p
( select
test=>

Oops, line 489 doesn't work either:

test=> (select
test(> \g
ERROR: parser: parse error at or near ""
test=>

I now remember how confusing the previous_buffer handling is. It is
this line that is tricky:

/* handle backslash command */
slashCmdStatus = HandleSlashCmds(&line[i],
query_buf->len > 0 ? query_buf : previous_buf,
^^^^^^^^^^^^^^^^^^^^^^^^
&end_of_cmd);
It works now:

test=> (select
test(> \g
ERROR: parser: parse error at or near ""
test(> \p
(select

Patch attached.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Attachments:

/pgpatches/parentext/plainDownload
Index: src/bin/psql/mainloop.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/mainloop.c,v
retrieving revision 1.45
diff -c -r1.45 mainloop.c
*** src/bin/psql/mainloop.c	2001/12/28 05:01:05	1.45
--- src/bin/psql/mainloop.c	2001/12/28 19:12:37
***************
*** 447,453 ****
  			{
  				const char *end_of_cmd = NULL;
  
- 				paren_level = 0;
  				line[i - prevlen] = '\0';		/* overwrites backslash */
  
  				/* is there anything else on the line for the command? */
--- 447,452 ----
***************
*** 473,479 ****
  				if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) &&
  					query_buf->len == 0)
  				{
! 					/* copy previous buffer to current for for handling */
  					appendPQExpBufferStr(query_buf, previous_buf->data);
  				}
  
--- 472,478 ----
  				if ((slashCmdStatus == CMD_SEND || slashCmdStatus == CMD_NEWEDIT) &&
  					query_buf->len == 0)
  				{
! 					/* copy previous buffer to current for handling */
  					appendPQExpBufferStr(query_buf, previous_buf->data);
  				}
  
***************
*** 486,491 ****
--- 485,493 ----
  					appendPQExpBufferStr(previous_buf, query_buf->data);
  					resetPQExpBuffer(query_buf);
  				}
+ 
+ 				if (query_buf->len == 0 && previous_buf->len == 0)
+ 					paren_level = 0;
  
  				/* process anything left after the backslash command */
  				i += end_of_cmd - &line[i];