aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/prep/prepunion.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/prep/prepunion.c')
-rw-r--r--src/backend/optimizer/prep/prepunion.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 7d75e1eda93..690b6bbab7f 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -51,6 +51,7 @@
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/selfuncs.h"
+#include "utils/syscache.h"
typedef struct
@@ -1895,9 +1896,11 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
List *vars = NIL;
TupleDesc old_tupdesc = RelationGetDescr(oldrelation);
TupleDesc new_tupdesc = RelationGetDescr(newrelation);
+ Oid new_relid = RelationGetRelid(newrelation);
int oldnatts = old_tupdesc->natts;
int newnatts = new_tupdesc->natts;
int old_attno;
+ int new_attno = 0;
for (old_attno = 0; old_attno < oldnatts; old_attno++)
{
@@ -1906,7 +1909,6 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
Oid atttypid;
int32 atttypmod;
Oid attcollation;
- int new_attno;
att = TupleDescAttr(old_tupdesc, old_attno);
if (att->attisdropped)
@@ -1939,29 +1941,25 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
* Otherwise we have to search for the matching column by name.
* There's no guarantee it'll have the same column position, because
* of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
- * However, in simple cases it will be the same column number, so try
- * that before we go groveling through all the columns.
- *
- * Note: the test for (att = ...) != NULL cannot fail, it's just a
- * notational device to include the assignment into the if-clause.
+ * However, in simple cases, the relative order of columns is mostly
+ * the same in both relations, so try the column of newrelation that
+ * follows immediately after the one that we just found, and if that
+ * fails, let syscache handle it.
*/
- if (old_attno < newnatts &&
- (att = TupleDescAttr(new_tupdesc, old_attno)) != NULL &&
- !att->attisdropped &&
- strcmp(attname, NameStr(att->attname)) == 0)
- new_attno = old_attno;
- else
+ if (new_attno >= newnatts ||
+ (att = TupleDescAttr(new_tupdesc, new_attno))->attisdropped ||
+ strcmp(attname, NameStr(att->attname)) != 0)
{
- for (new_attno = 0; new_attno < newnatts; new_attno++)
- {
- att = TupleDescAttr(new_tupdesc, new_attno);
- if (!att->attisdropped &&
- strcmp(attname, NameStr(att->attname)) == 0)
- break;
- }
- if (new_attno >= newnatts)
+ HeapTuple newtup;
+
+ newtup = SearchSysCacheAttName(new_relid, attname);
+ if (!newtup)
elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
attname, RelationGetRelationName(newrelation));
+ new_attno = ((Form_pg_attribute) GETSTRUCT(newtup))->attnum - 1;
+ ReleaseSysCache(newtup);
+
+ att = TupleDescAttr(new_tupdesc, new_attno);
}
/* Found it, check type and collation match */
@@ -1978,6 +1976,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
atttypmod,
attcollation,
0));
+ new_attno++;
}
*translated_vars = vars;