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

Commitd8f1c03

Browse files
committed
Force tuple conversion when the source has missing attributes.
Tuple conversion incorrectly concluded that no conversion was neededas long as all the attributes lined up. But if the source tuple has amissing attribute (from addition of a column with default), then thedestination tupdesc might not reflect the same default. The typicalsymptom was that the affected columns would be unexpectedly NULL.Repair by always forcing conversion if the source has missingattributes, which will be filled in by the deform operation. (Intheory we could optimize for when the destination has the samedefault, but that seemed overkill.)Backpatch to 11 where missing attributes were added.Per bug #16242.Vik Fearing (discovery, code, testing) and me (analysis, testcase).Discussion:https://postgr.es/m/16242-d1c9fca28445966b@postgresql.org
1 parent1265776 commitd8f1c03

File tree

3 files changed

+101
-8
lines changed

3 files changed

+101
-8
lines changed

‎src/backend/access/common/tupconvert.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,18 @@ convert_tuples_by_position(TupleDesc indesc,
149149
{
150150
for (i=0;i<n;i++)
151151
{
152-
Form_pg_attributeinatt;
153-
Form_pg_attributeoutatt;
152+
Form_pg_attributeinatt=TupleDescAttr(indesc,i);
153+
Form_pg_attributeoutatt=TupleDescAttr(outdesc,i);
154+
155+
/*
156+
* If the input column has a missing attribute, we need a
157+
* conversion.
158+
*/
159+
if (inatt->atthasmissing)
160+
{
161+
same= false;
162+
break;
163+
}
154164

155165
if (attrMap[i]== (i+1))
156166
continue;
@@ -160,8 +170,6 @@ convert_tuples_by_position(TupleDesc indesc,
160170
* also dropped, we needn't convert. However, attlen and attalign
161171
* must agree.
162172
*/
163-
inatt=TupleDescAttr(indesc,i);
164-
outatt=TupleDescAttr(outdesc,i);
165173
if (attrMap[i]==0&&
166174
inatt->attisdropped&&
167175
inatt->attlen==outatt->attlen&&
@@ -233,8 +241,18 @@ convert_tuples_by_name(TupleDesc indesc,
233241
same= true;
234242
for (i=0;i<n;i++)
235243
{
236-
Form_pg_attributeinatt;
237-
Form_pg_attributeoutatt;
244+
Form_pg_attributeinatt=TupleDescAttr(indesc,i);
245+
Form_pg_attributeoutatt=TupleDescAttr(outdesc,i);
246+
247+
/*
248+
* If the input column has a missing attribute, we need a
249+
* conversion.
250+
*/
251+
if (inatt->atthasmissing)
252+
{
253+
same= false;
254+
break;
255+
}
238256

239257
if (attrMap[i]== (i+1))
240258
continue;
@@ -244,8 +262,6 @@ convert_tuples_by_name(TupleDesc indesc,
244262
* also dropped, we needn't convert. However, attlen and attalign
245263
* must agree.
246264
*/
247-
inatt=TupleDescAttr(indesc,i);
248-
outatt=TupleDescAttr(outdesc,i);
249265
if (attrMap[i]==0&&
250266
inatt->attisdropped&&
251267
inatt->attlen==outatt->attlen&&

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4174,3 +4174,41 @@ alter table at_test_sql_partop attach partition at_test_sql_partop_1 for values
41744174
drop table at_test_sql_partop;
41754175
drop operator class at_test_sql_partop using btree;
41764176
drop function at_test_sql_partop;
4177+
/* Test case for bug #16242 */
4178+
-- We create a parent and child where the child has missing
4179+
-- non-null attribute values, and arrange to pass them through
4180+
-- tuple conversion from the child to the parent tupdesc
4181+
create table bar1 (a integer, b integer not null default 1)
4182+
partition by range (a);
4183+
create table bar2 (a integer);
4184+
insert into bar2 values (1);
4185+
alter table bar2 add column b integer not null default 1;
4186+
-- (at this point bar2 contains tuple with natts=1)
4187+
alter table bar1 attach partition bar2 default;
4188+
-- this works:
4189+
select * from bar1;
4190+
a | b
4191+
---+---
4192+
1 | 1
4193+
(1 row)
4194+
4195+
-- this exercises tuple conversion:
4196+
create function xtrig()
4197+
returns trigger language plpgsql
4198+
as $$
4199+
declare
4200+
r record;
4201+
begin
4202+
for r in select * from old loop
4203+
raise info 'a=%, b=%', r.a, r.b;
4204+
end loop;
4205+
return NULL;
4206+
end;
4207+
$$;
4208+
create trigger xtrig
4209+
after update on bar1
4210+
referencing old table as old
4211+
for each statement execute procedure xtrig();
4212+
update bar1 set a = a + 1;
4213+
INFO: a=1, b=1
4214+
/* End test case for bug #16242 */

‎src/test/regress/sql/alter_table.sql

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2763,3 +2763,42 @@ alter table at_test_sql_partop attach partition at_test_sql_partop_1 for values
27632763
droptable at_test_sql_partop;
27642764
dropoperator class at_test_sql_partop using btree;
27652765
dropfunction at_test_sql_partop;
2766+
2767+
2768+
/* Test case for bug #16242*/
2769+
2770+
-- We create a parent and child where the child has missing
2771+
-- non-null attribute values, and arrange to pass them through
2772+
-- tuple conversion from the child to the parent tupdesc
2773+
createtablebar1 (ainteger, bintegernot null default1)
2774+
partition by range (a);
2775+
createtablebar2 (ainteger);
2776+
insert into bar2values (1);
2777+
altertable bar2 add column bintegernot null default1;
2778+
-- (at this point bar2 contains tuple with natts=1)
2779+
altertable bar1 attach partition bar2 default;
2780+
2781+
-- this works:
2782+
select*from bar1;
2783+
2784+
-- this exercises tuple conversion:
2785+
createfunctionxtrig()
2786+
returns trigger language plpgsql
2787+
as $$
2788+
declare
2789+
r record;
2790+
begin
2791+
for rinselect*from old loop
2792+
raise info'a=%, b=%',r.a,r.b;
2793+
end loop;
2794+
returnNULL;
2795+
end;
2796+
$$;
2797+
createtriggerxtrig
2798+
afterupdateon bar1
2799+
referencing old tableas old
2800+
for each statement execute procedure xtrig();
2801+
2802+
update bar1set a= a+1;
2803+
2804+
/* End test case for bug #16242*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp