pgsql: Allow empty target list in SELECT.

Started by Tom Laneover 12 years ago9 messagescomitters
Jump to latest
#1Tom Lane
tgl@sss.pgh.pa.us

Allow empty target list in SELECT.

This fixes a problem noted as a followup to bug #8648: if a query has a
semantically-empty target list, e.g. SELECT * FROM zero_column_table,
ruleutils.c will dump it as a syntactically-empty target list, which was
not allowed. There doesn't seem to be any reliable way to fix this by
hacking ruleutils (note in particular that the originally zero-column table
might since have had columns added to it); and even if we had such a fix,
it would do nothing for existing dump files that might contain bad syntax.
The best bet seems to be to relax the syntactic restriction.

Also, add parse-analysis errors for SELECT DISTINCT with no columns (after
*-expansion) and RETURNING with no columns. These cases previously
produced unexpected behavior because the parsed Query looked like it had
no DISTINCT or RETURNING clause, respectively. If anyone ever offers
a plausible use-case for this, we could work a bit harder on making the
situation distinguishable.

Arguably this is a bug fix that should be back-patched, but I'm worried
that there may be client apps or PLs that expect "SELECT ;" to throw a
syntax error. The issue doesn't seem important enough to risk changing
behavior in minor releases.

Branch
------
master

Details
-------
http://git.postgresql.org/pg/commitdiff/1b4f7f93b4693858cb983af3cd557f6097dab67b

Modified Files
--------------
doc/src/sgml/ref/select.sgml | 28 +++++++++++++++++++++-------
src/backend/parser/analyze.c | 13 +++++++++++++
src/backend/parser/gram.y | 8 ++++++--
src/backend/parser/parse_clause.c | 19 +++++++++++++++++++
src/test/regress/expected/errors.out | 23 ++++++++---------------
src/test/regress/sql/errors.sql | 15 ++++++---------
6 files changed, 73 insertions(+), 33 deletions(-)

--
Sent via pgsql-committers mailing list (pgsql-committers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers

#2Thom Brown
thom@linux.com
In reply to: Tom Lane (#1)
Re: pgsql: Allow empty target list in SELECT.

On 15 December 2013 02:23, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Allow empty target list in SELECT.

This fixes a problem noted as a followup to bug #8648: if a query has a
semantically-empty target list, e.g. SELECT * FROM zero_column_table,
ruleutils.c will dump it as a syntactically-empty target list, which was
not allowed. There doesn't seem to be any reliable way to fix this by
hacking ruleutils (note in particular that the originally zero-column table
might since have had columns added to it); and even if we had such a fix,
it would do nothing for existing dump files that might contain bad syntax.
The best bet seems to be to relax the syntactic restriction.

Also, add parse-analysis errors for SELECT DISTINCT with no columns (after
*-expansion) and RETURNING with no columns. These cases previously
produced unexpected behavior because the parsed Query looked like it had
no DISTINCT or RETURNING clause, respectively. If anyone ever offers
a plausible use-case for this, we could work a bit harder on making the
situation distinguishable.

Arguably this is a bug fix that should be back-patched, but I'm worried
that there may be client apps or PLs that expect "SELECT ;" to throw a
syntax error. The issue doesn't seem important enough to risk changing
behavior in minor releases.

This commit introduces another bug:

# create table colours (id serial, name text, visible boolean);
CREATE TABLE

# insert into colours (name, visible) values
('blue',true),('yellow',true),('ultraviolet',false),('green',true),('infrared',false);
INSERT 0 5

# select into colours2 from colours;
SELECT 5

# select * from colours2;
(No rows)

--
Thom

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thom Brown (#2)
Re: pgsql: Allow empty target list in SELECT.

Thom Brown <thom@linux.com> writes:

On 15 December 2013 02:23, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Allow empty target list in SELECT.

This commit introduces another bug:

# create table colours (id serial, name text, visible boolean);
CREATE TABLE

# insert into colours (name, visible) values
('blue',true),('yellow',true),('ultraviolet',false),('green',true),('infrared',false);
INSERT 0 5

# select into colours2 from colours;
SELECT 5

# select * from colours2;
(No rows)

That's just a pre-existing issue in psql that it's not terribly smart
about displaying zero-column rows. But what psql are you using?
I see

regression=# select * from colours2;
--
(5 rows)

regards, tom lane

--
Sent via pgsql-committers mailing list (pgsql-committers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers

#4Thom Brown
thom@linux.com
In reply to: Tom Lane (#3)
Re: pgsql: Allow empty target list in SELECT.

On 22 October 2014 21:57, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thom Brown <thom@linux.com> writes:

On 15 December 2013 02:23, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Allow empty target list in SELECT.

This commit introduces another bug:

# create table colours (id serial, name text, visible boolean);
CREATE TABLE

# insert into colours (name, visible) values

('blue',true),('yellow',true),('ultraviolet',false),('green',true),('infrared',false);

INSERT 0 5

# select into colours2 from colours;
SELECT 5

# select * from colours2;
(No rows)

That's just a pre-existing issue in psql that it's not terribly smart
about displaying zero-column rows. But what psql are you using?
I see

regression=# select * from colours2;
--
(5 rows)

I'm using the one I built along with everything else:

$ which psql
/home/thom/Development/psql/bin/psql

--
Thom

#5Thom Brown
thom@linux.com
In reply to: Thom Brown (#4)
Re: pgsql: Allow empty target list in SELECT.

On 22 October 2014 22:06, Thom Brown <thom@linux.com> wrote:

On 22 October 2014 21:57, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Thom Brown <thom@linux.com> writes:

On 15 December 2013 02:23, Tom Lane <tgl@sss.pgh.pa.us> wrote:

Allow empty target list in SELECT.

This commit introduces another bug:

# create table colours (id serial, name text, visible boolean);
CREATE TABLE

# insert into colours (name, visible) values

('blue',true),('yellow',true),('ultraviolet',false),('green',true),('infrared',false);

INSERT 0 5

# select into colours2 from colours;
SELECT 5

# select * from colours2;
(No rows)

That's just a pre-existing issue in psql that it's not terribly smart
about displaying zero-column rows. But what psql are you using?
I see

regression=# select * from colours2;
--
(5 rows)

I'm using the one I built along with everything else:

$ which psql
/home/thom/Development/psql/bin/psql

I can see the same output as you if I get it to ignore my .psqlrc file:

# select * from colours2;
--
(5 rows)

Turns out it's "\x auto" causing it.

--
Thom

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: Thom Brown (#5)
Re: pgsql: Allow empty target list in SELECT.

Thom Brown <thom@linux.com> writes:

I can see the same output as you if I get it to ignore my .psqlrc file:

# select * from colours2;
--
(5 rows)

Turns out it's "\x auto" causing it.

Ah. Seems like a bug in the expanded-mode printout logic then.
But, in any case, it's been like that a very long time. You
could do this at least as far back as 8.4:

regression=# create table foo();
CREATE TABLE
regression=# insert into foo default values;
INSERT 0 1
regression=# insert into foo default values;
INSERT 0 1
regression=# select * from foo;
--
(2 rows)

regression=# \x on
Expanded display is on.
regression=# select * from foo;
(No rows)

regards, tom lane

--
Sent via pgsql-committers mailing list (pgsql-committers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers

#7Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#6)
Re: pgsql: Allow empty target list in SELECT.

On Wed, Oct 22, 2014 at 04:19:10PM -0400, Tom Lane wrote:

Thom Brown <thom@linux.com> writes:

I can see the same output as you if I get it to ignore my .psqlrc file:

# select * from colours2;
--
(5 rows)

Turns out it's "\x auto" causing it.

Ah. Seems like a bug in the expanded-mode printout logic then.
But, in any case, it's been like that a very long time. You
could do this at least as far back as 8.4:

regression=# create table foo();
CREATE TABLE
regression=# insert into foo default values;
INSERT 0 1
regression=# insert into foo default values;
INSERT 0 1
regression=# select * from foo;
--
(2 rows)

regression=# \x on
Expanded display is on.
regression=# select * from foo;
(No rows)

I have developed a patch to fix this, e.g.:

test=> select * from foo;
--
(2 rows)

test=> \x
Expanded display is on.
test=> select * from foo;
(2 rows)

I used the same footer function every other output format was using.
Patch attached.

I also found that the normal non-expanded output was forcing the use of
a pager for these tests, which seemed odd considering there were no
rows. The problem is that the variable col_count is an unsigned integer,
and there were a few places we were subtracting one from it. When
col_count was zero, subtracting one returned a very larger positive
number, and triggered the pager. That is fixed in this patch as well.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ Everyone has their own god. +

Attachments:

psql.difftext/x-diff; charset=us-asciiDownload+25-25
#8Bruce Momjian
bruce@momjian.us
In reply to: Bruce Momjian (#7)
Re: pgsql: Allow empty target list in SELECT.

On Fri, Mar 20, 2015 at 08:25:50AM -0400, Bruce Momjian wrote:

regression=# create table foo();
CREATE TABLE
regression=# insert into foo default values;
INSERT 0 1
regression=# insert into foo default values;
INSERT 0 1
regression=# select * from foo;
--
(2 rows)

regression=# \x on
Expanded display is on.
regression=# select * from foo;
(No rows)

I have developed a patch to fix this, e.g.:

test=> select * from foo;
--
(2 rows)

test=> \x
Expanded display is on.
test=> select * from foo;
(2 rows)

I used the same footer function every other output format was using.
Patch attached.

Patch applied.

--
Bruce Momjian <bruce@momjian.us> http://momjian.us
EnterpriseDB http://enterprisedb.com

+ Everyone has their own god. +

--
Sent via pgsql-committers mailing list (pgsql-committers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-committers

#9Thom Brown
thom@linux.com
In reply to: Bruce Momjian (#8)
Re: pgsql: Allow empty target list in SELECT.

On 25 March 2015 at 01:04, Bruce Momjian <bruce@momjian.us> wrote:

On Fri, Mar 20, 2015 at 08:25:50AM -0400, Bruce Momjian wrote:

regression=# create table foo();
CREATE TABLE
regression=# insert into foo default values;
INSERT 0 1
regression=# insert into foo default values;
INSERT 0 1
regression=# select * from foo;
--
(2 rows)

regression=# \x on
Expanded display is on.
regression=# select * from foo;
(No rows)

I have developed a patch to fix this, e.g.:

test=> select * from foo;
--
(2 rows)

test=> \x
Expanded display is on.
test=> select * from foo;
(2 rows)

I used the same footer function every other output format was using.
Patch attached.

Patch applied.

Thanks.

--
Thom