Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2c4debb

Browse files
committed
Make new expression eval code reject references to dropped columns.
Formerly, a Var referencing an already-dropped column was allowed and wouldalways produce a NULL value. However, that behavior was implemented inslot_getattr which the new expression code doesn't use; thus there is now arisk of returning theoretically-deleted data. We had regression test casesthat purported to exercise this, but they failed to expose any problem,apparently because plpgsql filters the dropped column and produces anoutput tuple that has a NULL there already.Ideally the DROP or ALTER attempt in these test cases would get rejecteddue to dependency checks; but until that happens, let's modify the behaviorso that we fail the query during executor start. This was already true forthe related case of a column having changed type underneath us, and there'sno obvious reason why we need to be laxer for dropped columns.In passing, adjust the error messages in CheckVarSlotCompatibility toinclude the composite type name. In the cases shown in the regressiontests this is always just "record", but it should be more useful inactual stale-plan cases, where the slot tupdesc would be a table'stupdesc directly.Discussion:https://postgr.es/m/16803.1490723570@sss.pgh.pa.us
1 parentce96ce6 commit2c4debb

File tree

5 files changed

+95
-47
lines changed

5 files changed

+95
-47
lines changed

‎src/backend/executor/execExprInterp.c

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1516,22 +1516,20 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
15161516
{
15171517
/*
15181518
* What we have to check for here is the possibility of an attribute
1519-
* having been changed in type since the plan tree was created. Ideally
1520-
* the plan will get invalidated and not re-used, but just in case, we
1521-
* keep these defenses. Fortunately it's sufficient to check once on the
1522-
* first time through.
1523-
*
1524-
* System attributes don't require checking since their types never
1525-
* change.
1526-
*
1527-
* Note: we allow a reference to a dropped attribute. slot_getattr will
1528-
* force a NULL result in such cases.
1519+
* having been dropped or changed in type since the plan tree was created.
1520+
* Ideally the plan will get invalidated and not re-used, but just in
1521+
* case, we keep these defenses. Fortunately it's sufficient to check
1522+
* once on the first time through.
15291523
*
15301524
* Note: ideally we'd check typmod as well as typid, but that seems
15311525
* impractical at the moment: in many cases the tupdesc will have been
15321526
* generated by ExecTypeFromTL(), and that can't guarantee to generate an
15331527
* accurate typmod in all cases, because some expression node types don't
1534-
* carry typmod.
1528+
* carry typmod. Fortunately, for precisely that reason, there should be
1529+
* no places with a critical dependency on the typmod of a value.
1530+
*
1531+
* System attributes don't require checking since their types never
1532+
* change.
15351533
*/
15361534
if (attnum>0)
15371535
{
@@ -1544,17 +1542,20 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
15441542

15451543
attr=slot_tupdesc->attrs[attnum-1];
15461544

1547-
/* can't check type if dropped, since atttypid is probably 0 */
1548-
if (!attr->attisdropped)
1549-
{
1550-
if (vartype!=attr->atttypid)
1551-
ereport(ERROR,
1552-
(errcode(ERRCODE_DATATYPE_MISMATCH),
1553-
errmsg("attribute %d has wrong type",attnum),
1554-
errdetail("Table has type %s, but query expects %s.",
1555-
format_type_be(attr->atttypid),
1556-
format_type_be(vartype))));
1557-
}
1545+
if (attr->attisdropped)
1546+
ereport(ERROR,
1547+
(errcode(ERRCODE_UNDEFINED_COLUMN),
1548+
errmsg("attribute %d of type %s has been dropped",
1549+
attnum,format_type_be(slot_tupdesc->tdtypeid))));
1550+
1551+
if (vartype!=attr->atttypid)
1552+
ereport(ERROR,
1553+
(errcode(ERRCODE_DATATYPE_MISMATCH),
1554+
errmsg("attribute %d of type %s has wrong type",
1555+
attnum,format_type_be(slot_tupdesc->tdtypeid)),
1556+
errdetail("Table has type %s, but query expects %s.",
1557+
format_type_be(attr->atttypid),
1558+
format_type_be(vartype))));
15581559
}
15591560
}
15601561

‎src/test/regress/expected/create_view.out

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,10 +1396,10 @@ select pg_get_viewdef('vv6', true);
13961396
(1 row)
13971397

13981398
--
1399-
-- Checksomecases involving dropped columns in a function's rowtype result
1399+
-- Check cases involving dropped/altered columns in a function's rowtype result
14001400
--
14011401
create table tt14t (f1 text, f2 text, f3 text, f4 text);
1402-
insert into tt14t values('foo', 'bar', 'baz', 'quux');
1402+
insert into tt14t values('foo', 'bar', 'baz', '42');
14031403
alter table tt14t drop column f2;
14041404
create function tt14f() returns setof tt14t as
14051405
$$
@@ -1424,14 +1424,15 @@ select pg_get_viewdef('tt14v', true);
14241424
(1 row)
14251425

14261426
select * from tt14v;
1427-
f1 | f3 | f4
1428-
-----+-----+------
1429-
foo | baz |quux
1427+
f1 | f3 |f4
1428+
-----+-----+----
1429+
foo | baz |42
14301430
(1 row)
14311431

1432+
begin;
14321433
-- this perhaps should be rejected, but it isn't:
14331434
alter table tt14t drop column f3;
1434-
-- f3 is still in the viewbut will read as nulls
1435+
-- f3 is still in the view...
14351436
select pg_get_viewdef('tt14v', true);
14361437
pg_get_viewdef
14371438
--------------------------------
@@ -1441,12 +1442,40 @@ select pg_get_viewdef('tt14v', true);
14411442
FROM tt14f() t(f1, f3, f4);
14421443
(1 row)
14431444

1445+
-- but will fail at execution
1446+
select f1, f4 from tt14v;
1447+
f1 | f4
1448+
-----+----
1449+
foo | 42
1450+
(1 row)
1451+
14441452
select * from tt14v;
1445-
f1 | f3 | f4
1446-
-----+----+------
1447-
foo | | quux
1453+
ERROR: attribute 3 of type record has been dropped
1454+
rollback;
1455+
begin;
1456+
-- this perhaps should be rejected, but it isn't:
1457+
alter table tt14t alter column f4 type integer using f4::integer;
1458+
-- f4 is still in the view ...
1459+
select pg_get_viewdef('tt14v', true);
1460+
pg_get_viewdef
1461+
--------------------------------
1462+
SELECT t.f1, +
1463+
t.f3, +
1464+
t.f4 +
1465+
FROM tt14f() t(f1, f3, f4);
14481466
(1 row)
14491467

1468+
-- but will fail at execution
1469+
select f1, f3 from tt14v;
1470+
f1 | f3
1471+
-----+-----
1472+
foo | baz
1473+
(1 row)
1474+
1475+
select * from tt14v;
1476+
ERROR: attribute 4 of type record has wrong type
1477+
DETAIL: Table has type integer, but query expects text.
1478+
rollback;
14501479
-- check display of whole-row variables in some corner cases
14511480
create type nestedcomposite as (x int8_tbl);
14521481
create view tt15v as select row(i)::nestedcomposite from int8_tbl i;

‎src/test/regress/expected/rangefuncs.out

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,25 +1909,22 @@ select * from usersview;
19091909
id2 | 2 | email2 | 12 | t | 11 | 2
19101910
(2 rows)
19111911

1912-
alter table users drop column moredrop;
1913-
select * from usersview;
1914-
userid | seq | email | moredrop | enabled | generate_series | ordinality
1915-
--------+-----+--------+----------+---------+-----------------+------------
1916-
id | 1 | email | | t | 10 | 1
1917-
id2 | 2 | email2 | | t | 11 | 2
1918-
(2 rows)
1919-
19201912
alter table users add column junk text;
19211913
select * from usersview;
19221914
userid | seq | email | moredrop | enabled | generate_series | ordinality
19231915
--------+-----+--------+----------+---------+-----------------+------------
1924-
id | 1 | email | | t | 10 | 1
1925-
id2 | 2 | email2 | | t | 11 | 2
1916+
id | 1 | email |11 | t | 10 | 1
1917+
id2 | 2 | email2 |12 | t | 11 | 2
19261918
(2 rows)
19271919

1920+
begin;
1921+
alter table users drop column moredrop;
1922+
select * from usersview; -- expect clean failure
1923+
ERROR: attribute 5 of type record has been dropped
1924+
rollback;
19281925
alter table users alter column seq type numeric;
19291926
select * from usersview; -- expect clean failure
1930-
ERROR: attribute 2 has wrong type
1927+
ERROR: attribute 2of type recordhas wrong type
19311928
DETAIL: Table has type numeric, but query expects integer.
19321929
drop view usersview;
19331930
drop function get_first_user();

‎src/test/regress/sql/create_view.sql

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,11 +457,11 @@ alter table tt11 add column z int;
457457
select pg_get_viewdef('vv6', true);
458458

459459
--
460-
-- Checksomecases involving dropped columns in a function's rowtype result
460+
-- Check cases involving dropped/altered columns in a function's rowtype result
461461
--
462462

463463
createtablett14t (f1text, f2text, f3text, f4text);
464-
insert into tt14tvalues('foo','bar','baz','quux');
464+
insert into tt14tvalues('foo','bar','baz','42');
465465

466466
altertable tt14t drop column f2;
467467

@@ -483,13 +483,32 @@ create view tt14v as select t.* from tt14f() t;
483483
select pg_get_viewdef('tt14v', true);
484484
select*from tt14v;
485485

486+
begin;
487+
486488
-- this perhaps should be rejected, but it isn't:
487489
altertable tt14t drop column f3;
488490

489-
-- f3 is still in the viewbut will read as nulls
491+
-- f3 is still in the view...
490492
select pg_get_viewdef('tt14v', true);
493+
-- but will fail at execution
494+
select f1, f4from tt14v;
491495
select*from tt14v;
492496

497+
rollback;
498+
499+
begin;
500+
501+
-- this perhaps should be rejected, but it isn't:
502+
altertable tt14t alter column f4 typeinteger using f4::integer;
503+
504+
-- f4 is still in the view ...
505+
select pg_get_viewdef('tt14v', true);
506+
-- but will fail at execution
507+
select f1, f3from tt14v;
508+
select*from tt14v;
509+
510+
rollback;
511+
493512
-- check display of whole-row variables in some corner cases
494513

495514
createtypenestedcompositeas (x int8_tbl);

‎src/test/regress/sql/rangefuncs.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,11 +555,13 @@ SELECT * FROM ROWS FROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
555555
create temp view usersviewas
556556
SELECT*FROM ROWSFROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
557557

558-
select*from usersview;
559-
altertable users drop column moredrop;
560558
select*from usersview;
561559
altertable users add column junktext;
562560
select*from usersview;
561+
begin;
562+
altertable users drop column moredrop;
563+
select*from usersview;-- expect clean failure
564+
rollback;
563565
altertable users alter column seq typenumeric;
564566
select*from usersview;-- expect clean failure
565567

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp