Skip to content

Commit 115296a

Browse files
committed
borrow make_inh_translation_list() from postgres
1 parent dd4b33b commit 115296a

File tree

1 file changed

+81
-54
lines changed

1 file changed

+81
-54
lines changed

src/pg_pathman.c

Lines changed: 81 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,8 @@ static bool pull_var_param(const WalkerContext *ctx,
7474

7575

7676
/* Misc */
77-
static List *make_inh_translation_list_simplified(Relation oldrelation,
78-
Relation newrelation,
79-
Index newvarno);
77+
static void make_inh_translation_list(Relation oldrelation, Relation newrelation,
78+
Index newvarno, List **translated_vars);
8079

8180

8281
/* Copied from allpaths.h */
@@ -165,79 +164,107 @@ _PG_init(void)
165164
}
166165

167166
/*
168-
* Build the list of translations from parent Vars to child Vars
169-
* for an inheritance child.
167+
* make_inh_translation_list
168+
* Build the list of translations from parent Vars to child Vars for
169+
* an inheritance child.
170170
*
171-
* NOTE: Inspired by function make_inh_translation_list().
171+
* For paranoia's sake, we match type/collation as well as attribute name.
172+
*
173+
* NOTE: borrowed from prepunion.c
172174
*/
173-
static List *
174-
make_inh_translation_list_simplified(Relation oldrelation,
175-
Relation newrelation,
176-
Index newvarno)
175+
static void
176+
make_inh_translation_list(Relation oldrelation, Relation newrelation,
177+
Index newvarno, List **translated_vars)
177178
{
178179
List *vars = NIL;
179180
TupleDesc old_tupdesc = RelationGetDescr(oldrelation);
180181
TupleDesc new_tupdesc = RelationGetDescr(newrelation);
181-
int oldnatts = RelationGetNumberOfAttributes(oldrelation);
182-
int newnatts = RelationGetNumberOfAttributes(newrelation);
182+
int oldnatts = old_tupdesc->natts;
183+
int newnatts = new_tupdesc->natts;
183184
int old_attno;
184185

185-
/* Amounts of attributes must match */
186-
if (oldnatts != newnatts)
187-
goto inh_translation_list_error;
188-
189-
/* We expect that parent and partition have an identical tupdesc */
190186
for (old_attno = 0; old_attno < oldnatts; old_attno++)
191187
{
192-
Form_pg_attribute old_att,
193-
new_att;
194-
Oid atttypid;
195-
int32 atttypmod;
196-
Oid attcollation;
197-
198-
old_att = old_tupdesc->attrs[old_attno];
199-
new_att = new_tupdesc->attrs[old_attno];
200-
201-
/* Attribute definitions must match */
202-
if (old_att->attisdropped != new_att->attisdropped ||
203-
old_att->atttypid != new_att->atttypid ||
204-
old_att->atttypmod != new_att->atttypmod ||
205-
old_att->attcollation != new_att->attcollation ||
206-
strcmp(NameStr(old_att->attname), NameStr(new_att->attname)) != 0)
188+
Form_pg_attribute att;
189+
char *attname;
190+
Oid atttypid;
191+
int32 atttypmod;
192+
Oid attcollation;
193+
int new_attno;
194+
195+
att = old_tupdesc->attrs[old_attno];
196+
if (att->attisdropped)
207197
{
208-
goto inh_translation_list_error;
198+
/* Just put NULL into this list entry */
199+
vars = lappend(vars, NULL);
200+
continue;
209201
}
202+
attname = NameStr(att->attname);
203+
atttypid = att->atttypid;
204+
atttypmod = att->atttypmod;
205+
attcollation = att->attcollation;
210206

211-
if (old_att->attisdropped)
207+
/*
208+
* When we are generating the "translation list" for the parent table
209+
* of an inheritance set, no need to search for matches.
210+
*/
211+
if (oldrelation == newrelation)
212212
{
213-
/* Just put NULL into this list entry */
214-
vars = lappend(vars, NULL);
213+
vars = lappend(vars, makeVar(newvarno,
214+
(AttrNumber) (old_attno + 1),
215+
atttypid,
216+
atttypmod,
217+
attcollation,
218+
0));
215219
continue;
216220
}
217221

218-
atttypid = old_att->atttypid;
219-
atttypmod = old_att->atttypmod;
220-
attcollation = old_att->attcollation;
222+
/*
223+
* Otherwise we have to search for the matching column by name.
224+
* There's no guarantee it'll have the same column position, because
225+
* of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
226+
* However, in simple cases it will be the same column number, so try
227+
* that before we go groveling through all the columns.
228+
*
229+
* Note: the test for (att = ...) != NULL cannot fail, it's just a
230+
* notational device to include the assignment into the if-clause.
231+
*/
232+
if (old_attno < newnatts &&
233+
(att = new_tupdesc->attrs[old_attno]) != NULL &&
234+
!att->attisdropped && att->attinhcount != 0 &&
235+
strcmp(attname, NameStr(att->attname)) == 0)
236+
new_attno = old_attno;
237+
else
238+
{
239+
for (new_attno = 0; new_attno < newnatts; new_attno++)
240+
{
241+
att = new_tupdesc->attrs[new_attno];
242+
if (!att->attisdropped && att->attinhcount != 0 &&
243+
strcmp(attname, NameStr(att->attname)) == 0)
244+
break;
245+
}
246+
if (new_attno >= newnatts)
247+
elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
248+
attname, RelationGetRelationName(newrelation));
249+
}
250+
251+
/* Found it, check type and collation match */
252+
if (atttypid != att->atttypid || atttypmod != att->atttypmod)
253+
elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
254+
attname, RelationGetRelationName(newrelation));
255+
if (attcollation != att->attcollation)
256+
elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's collation",
257+
attname, RelationGetRelationName(newrelation));
221258

222259
vars = lappend(vars, makeVar(newvarno,
223-
(AttrNumber) (old_attno + 1),
260+
(AttrNumber) (new_attno + 1),
224261
atttypid,
225262
atttypmod,
226263
attcollation,
227264
0));
228265
}
229266

230-
/* Everything's ok */
231-
return vars;
232-
233-
/* We end up here if any attribute differs */
234-
inh_translation_list_error:
235-
elog(ERROR, "partition \"%s\" must have exact"
236-
"same structure as parent \"%s\"",
237-
RelationGetRelationName(newrelation),
238-
RelationGetRelationName(oldrelation));
239-
240-
return NIL; /* keep compiler happy */
267+
*translated_vars = vars;
241268
}
242269

243270
/*
@@ -295,9 +322,9 @@ append_child_relation(PlannerInfo *root, Relation parent_relation,
295322
appinfo->parent_relid = parent_rti;
296323
appinfo->child_relid = childRTindex;
297324
appinfo->parent_reloid = parent_rte->relid;
298-
appinfo->translated_vars = make_inh_translation_list_simplified(parent_relation,
299-
child_relation,
300-
childRTindex);
325+
326+
make_inh_translation_list(parent_relation, child_relation, childRTindex,
327+
&appinfo->translated_vars);
301328

302329
/* Now append 'appinfo' to 'root->append_rel_list' */
303330
root->append_rel_list = lappend(root->append_rel_list, appinfo);

0 commit comments

Comments
 (0)