From: | Scott Parkerson <scott(at)parkerson(dot)net> |
---|---|
To: | pgsql-general(at)postgresql(dot)org |
Cc: | Scott Parkerson <scott(at)parkerson(dot)net> |
Subject: | UPDATE with subquery; possible bug in query parser? |
Date: | 2013-04-20 16:27:51 |
Message-ID: | CAMG6XpSp8LeOTfEc=mtK8LkJNV1unpZ65W4GaS4iGT4H=GZO4w@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
I ran into this issue where an update command with a bad subquery in the
WHERE clause still ran and updated everything as if there was no WHERE
clause at all. Needless to say, it was a bit surprising. o_O
I've created a test (see below) that demonstrates what I think is to be the
issue; it's self-contained, so you can use it on a database without having
to worry about mucking anything up.
tl;dr; it seems to be related to when the "bad" subquery references a field
that matches the token in the WHERE clause.
This was tested on PostgreSQL 9.1.6 and 9.1.9; the former was on Mac OS X
(EnterpriseDB) and the latter was on CentOS 6.x using the PGDG build.
I wasn't sure if this should be posted to pgsql-bugs using the form yet;
I'd like to see if there's something I'm doing wrong here before I do that.
Thank you,
Scott Parkerson
---------------------------------------------------------------------------
--
-- test_update_subquery.sql
-- Demo a possible bug in the way the query parser works
--
-- Scott Parkerson <scott(at)parkerson(dot)net>
--
---------------------------------------------------------------------------
BEGIN;
-- Create tables for testing
CREATE TABLE foo (
id int NOT NULL,
name character varying(32) NOT NULL,
kind character varying(20) NOT NULL,
otherid int NOT NULL
);
CREATE TABLE other (
id int NOT NULL,
name character varying(20) NOT NULL
);
-- Test data
INSERT INTO other VALUES(1, 'Nothing');
INSERT INTO other VALUES(2, 'Nada');
INSERT INTO other VALUES(3, 'Zilch');
INSERT INTO foo VALUES(1, 'Electronecromegastompers, Inc.', 'CORP', 1);
INSERT INTO foo VALUES(2, 'Lizard Lick Towing', 'LLC', 1);
INSERT INTO foo VALUES(3, 'Bob Loblaw Law Firm', 'LLC', 2);
INSERT INTO foo VALUES(4, 'Cyberdyne Systems', 'CORP', 3);
INSERT INTO foo VALUES(5, 'Chock Full Of Gears and Stuff', 'PRIVATE', 3);
-- Test selects
SELECT COUNT(*) FROM foo WHERE kind = 'LLC'; -- expect 2
SELECT COUNT(*) FROM foo WHERE kind = 'LLC' AND otherid = 3; -- expect 0
-- Save here
SAVEPOINT before_update;
-- Update using a subselect; should update 3 items in foo
UPDATE foo
SET kind = 'LLC'
WHERE otherid IN
(SELECT id
FROM other
WHERE name != 'Nothing');
-- Check results
SELECT COUNT(*) FROM foo WHERE kind = 'LLC'; -- expect 4
SELECT COUNT(*) FROM foo WHERE kind = 'LLC' AND otherid = 3; -- expect 2
-- Rollback to before the update
ROLLBACK TO before_update;
-- This update has a bad select, but is allowed to go update the whole table
-- as if the where clause doesn't exist! Think it's because the "bad"
column in
-- the subquery matches a "good" column in the outer query's where clause?
UPDATE foo
SET kind = 'LLC'
WHERE otherid IN
(SELECT otherid
FROM other
WHERE name != 'Nothing');
-- Check results
SELECT COUNT(*) FROM foo WHERE kind = 'LLC'; -- expect 4, but returns 5
ROLLBACK TO before_update;
-- This update has a bad select with a difference; the bad token is
different
-- than the outer where clause. It fails as expected:
--
-- psql:test_update_subquery.sql:73: ERROR: column "herpderpid" does not
exist
-- LINE 4: (SELECT herpderpid
-- ^
UPDATE foo
SET kind = 'LLC'
WHERE otherid IN
(SELECT herpderpid
FROM other
WHERE name != 'Nothing');
ROLLBACK;
-- END OF TEST
From | Date | Subject | |
---|---|---|---|
Next Message | Satoshi Nagayasu | 2013-04-20 16:30:14 | Re: Where in the source code does postgres write to disk? |
Previous Message | Mike Levine | 2013-04-20 15:01:41 | Where in the source code does postgres write to disk? |