mirror of
https://github.com/postgres/postgres.git
synced 2025-06-03 00:02:26 -04:00
Fix foreign keys on system columns.
This commit is contained in:
parent
57dd2ce78a
commit
01b73d3f27
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.144 2001/10/12 00:07:14 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.145 2001/10/23 17:39:02 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* The PerformAddAttribute() code, like most of the relation
|
* The PerformAddAttribute() code, like most of the relation
|
||||||
@ -1347,9 +1347,7 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
bool istemp = is_temp_rel_name(relationName);
|
bool istemp = is_temp_rel_name(relationName);
|
||||||
List *indexoidlist;
|
List *indexoidlist;
|
||||||
List *indexoidscan;
|
List *indexoidscan;
|
||||||
Form_pg_attribute *rel_attrs;
|
int num_keys;
|
||||||
int num_keys = 0;
|
|
||||||
int keys_matched = 0;
|
|
||||||
bool index_found = false;
|
bool index_found = false;
|
||||||
bool index_found_unique = false;
|
bool index_found_unique = false;
|
||||||
bool index_found_primary = false;
|
bool index_found_primary = false;
|
||||||
@ -1394,15 +1392,9 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
* constraint
|
* constraint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rel_attrs = rel->rd_att->attrs;
|
|
||||||
|
|
||||||
/* Retrieve the oids of all indices on the relation */
|
|
||||||
indexoidlist = RelationGetIndexList(rel);
|
|
||||||
index_found = false;
|
|
||||||
index_found_unique = false;
|
|
||||||
index_found_primary = false;
|
|
||||||
|
|
||||||
/* Loop over all indices on the relation */
|
/* Loop over all indices on the relation */
|
||||||
|
indexoidlist = RelationGetIndexList(rel);
|
||||||
|
|
||||||
foreach(indexoidscan, indexoidlist)
|
foreach(indexoidscan, indexoidlist)
|
||||||
{
|
{
|
||||||
Oid indexoid = lfirsti(indexoidscan);
|
Oid indexoid = lfirsti(indexoidscan);
|
||||||
@ -1424,43 +1416,41 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
* Make sure this index has the same number of
|
* Make sure this index has the same number of
|
||||||
* keys as the constraint -- It obviously won't match otherwise.
|
* keys as the constraint -- It obviously won't match otherwise.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
|
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
|
||||||
|
;
|
||||||
num_keys = length(constr->keys);
|
num_keys = length(constr->keys);
|
||||||
keys_matched = 0;
|
|
||||||
|
|
||||||
if (i == num_keys)
|
if (i == num_keys)
|
||||||
{
|
{
|
||||||
/* Loop over each key in the constraint and check that there is a
|
/* Loop over each key in the constraint and check that there is a
|
||||||
corresponding key in the index. */
|
corresponding key in the index. */
|
||||||
|
int keys_matched = 0;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
foreach(keyl, constr->keys)
|
foreach(keyl, constr->keys)
|
||||||
{
|
{
|
||||||
Ident *key = lfirst(keyl);
|
Ident *key = lfirst(keyl);
|
||||||
|
int keyno = indexStruct->indkey[i];
|
||||||
|
|
||||||
/* Look at key[i] in the index and check that it is over the same column
|
/* Look at key[i] in the index and check that it is over the same column
|
||||||
as key[i] in the constraint. This is to differentiate between (a,b)
|
as key[i] in the constraint. This is to differentiate between (a,b)
|
||||||
and (b,a) */
|
and (b,a) */
|
||||||
if (i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0)
|
if (namestrcmp(attnumAttName(rel, keyno),
|
||||||
{
|
key->name) == 0)
|
||||||
int keyno = indexStruct->indkey[i];
|
keys_matched++;
|
||||||
|
else
|
||||||
if (keyno > 0)
|
break;
|
||||||
{
|
|
||||||
char *name = NameStr(rel_attrs[keyno - 1]->attname);
|
|
||||||
if (strcmp(name, key->name) == 0) keys_matched++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else elog(ERROR, "ALTER TABLE/ADD CONSTRAINT: Key \"%u[%u]\" not found", indexoid, i);
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (keys_matched == num_keys) {
|
if (keys_matched == num_keys) {
|
||||||
index_found = true;
|
index_found = true;
|
||||||
index_found_unique = indexStruct->indisunique;
|
index_found_unique = indexStruct->indisunique;
|
||||||
index_found_primary = indexStruct->indisprimary;
|
index_found_primary = indexStruct->indisprimary;
|
||||||
if (index_found_unique || index_found_primary) break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReleaseSysCache(indexTuple);
|
ReleaseSysCache(indexTuple);
|
||||||
|
if (index_found_unique || index_found_primary)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
freeList(indexoidlist);
|
freeList(indexoidlist);
|
||||||
@ -1504,18 +1494,6 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
Trigger trig;
|
Trigger trig;
|
||||||
List *list;
|
List *list;
|
||||||
int count;
|
int count;
|
||||||
List *indexoidlist,
|
|
||||||
*indexoidscan;
|
|
||||||
Form_pg_attribute *rel_attrs = NULL;
|
|
||||||
int i;
|
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
Oid fktypoid[INDEX_MAX_KEYS];
|
|
||||||
Oid pktypoid[INDEX_MAX_KEYS];
|
|
||||||
int attloc;
|
|
||||||
|
|
||||||
for (i=0; i<INDEX_MAX_KEYS; i++)
|
|
||||||
fktypoid[i]=pktypoid[i]=0;
|
|
||||||
|
|
||||||
if (is_temp_rel_name(fkconstraint->pktable_name) &&
|
if (is_temp_rel_name(fkconstraint->pktable_name) &&
|
||||||
!is_temp_rel_name(relationName))
|
!is_temp_rel_name(relationName))
|
||||||
@ -1530,140 +1508,21 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
|
if (pkrel->rd_rel->relkind != RELKIND_RELATION)
|
||||||
elog(ERROR, "referenced table \"%s\" not a relation",
|
elog(ERROR, "referenced table \"%s\" not a relation",
|
||||||
fkconstraint->pktable_name);
|
fkconstraint->pktable_name);
|
||||||
|
heap_close(pkrel, NoLock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* First we check for limited correctness of the constraint.
|
||||||
|
*
|
||||||
|
* NOTE: we assume parser has already checked for existence
|
||||||
|
* of an appropriate unique index on the referenced relation,
|
||||||
|
* and that the column datatypes are comparable.
|
||||||
|
*
|
||||||
* Scan through each tuple, calling the RI_FKey_Match_Ins
|
* Scan through each tuple, calling the RI_FKey_Match_Ins
|
||||||
* (insert trigger) as if that tuple had just been
|
* (insert trigger) as if that tuple had just been
|
||||||
* inserted. If any of those fail, it should elog(ERROR)
|
* inserted. If any of those fail, it should elog(ERROR)
|
||||||
* and that's that.
|
* and that's that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* First we check for limited correctness of the
|
|
||||||
* constraint
|
|
||||||
*/
|
|
||||||
|
|
||||||
rel_attrs = pkrel->rd_att->attrs;
|
|
||||||
indexoidlist = RelationGetIndexList(pkrel);
|
|
||||||
|
|
||||||
foreach(indexoidscan, indexoidlist)
|
|
||||||
{
|
|
||||||
Oid indexoid = lfirsti(indexoidscan);
|
|
||||||
HeapTuple indexTuple;
|
|
||||||
Form_pg_index indexStruct;
|
|
||||||
|
|
||||||
indexTuple = SearchSysCache(INDEXRELID,
|
|
||||||
ObjectIdGetDatum(indexoid),
|
|
||||||
0, 0, 0);
|
|
||||||
if (!HeapTupleIsValid(indexTuple))
|
|
||||||
elog(ERROR, "transformFkeyGetPrimaryKey: index %u not found",
|
|
||||||
indexoid);
|
|
||||||
indexStruct = (Form_pg_index) GETSTRUCT(indexTuple);
|
|
||||||
|
|
||||||
if (indexStruct->indisunique)
|
|
||||||
{
|
|
||||||
List *attrl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure this index has the same number of
|
|
||||||
* keys -- It obviously won't match otherwise.
|
|
||||||
*/
|
|
||||||
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++);
|
|
||||||
if (i != length(fkconstraint->pk_attrs))
|
|
||||||
found = false;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
attloc=0;
|
|
||||||
/* go through the fkconstraint->pk_attrs list */
|
|
||||||
foreach(attrl, fkconstraint->pk_attrs)
|
|
||||||
{
|
|
||||||
Ident *attr = lfirst(attrl);
|
|
||||||
|
|
||||||
found = false;
|
|
||||||
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
|
|
||||||
{
|
|
||||||
int pkattno = indexStruct->indkey[i];
|
|
||||||
|
|
||||||
if (pkattno > 0)
|
|
||||||
{
|
|
||||||
char *name = NameStr(rel_attrs[pkattno - 1]->attname);
|
|
||||||
|
|
||||||
if (strcmp(name, attr->name) == 0)
|
|
||||||
{
|
|
||||||
/* We get the type of this attribute here and
|
|
||||||
* store it so we can use it later for making
|
|
||||||
* sure the types are comparable.
|
|
||||||
*/
|
|
||||||
pktypoid[attloc++]=rel_attrs[pkattno-1]->atttypid;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReleaseSysCache(indexTuple);
|
|
||||||
if (found)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found)
|
|
||||||
elog(ERROR, "UNIQUE constraint matching given keys for referenced table \"%s\" not found",
|
|
||||||
fkconstraint->pktable_name);
|
|
||||||
|
|
||||||
freeList(indexoidlist);
|
|
||||||
heap_close(pkrel, NoLock);
|
|
||||||
|
|
||||||
rel_attrs = rel->rd_att->attrs;
|
|
||||||
if (fkconstraint->fk_attrs != NIL)
|
|
||||||
{
|
|
||||||
List *fkattrs;
|
|
||||||
Ident *fkattr;
|
|
||||||
|
|
||||||
found = false;
|
|
||||||
attloc = 0;
|
|
||||||
foreach(fkattrs, fkconstraint->fk_attrs)
|
|
||||||
{
|
|
||||||
int count;
|
|
||||||
|
|
||||||
found = false;
|
|
||||||
fkattr = lfirst(fkattrs);
|
|
||||||
for (count = 0; count < rel->rd_att->natts; count++)
|
|
||||||
{
|
|
||||||
char *name = NameStr(rel->rd_att->attrs[count]->attname);
|
|
||||||
|
|
||||||
if (strcmp(name, fkattr->name) == 0)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Here once again we get the types, this
|
|
||||||
* time for the fk table's attributes
|
|
||||||
*/
|
|
||||||
fktypoid[attloc++]=rel->rd_att->attrs[count]->atttypid;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found)
|
|
||||||
elog(ERROR, "columns referenced in foreign key constraint not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i < INDEX_MAX_KEYS && fktypoid[i] !=0; i++) {
|
|
||||||
/*
|
|
||||||
* fktypoid[i] is the foreign key table's i'th element's type oid
|
|
||||||
* pktypoid[i] is the primary key table's i'th element's type oid
|
|
||||||
* We let oper() do our work for us, including elog(ERROR) if the
|
|
||||||
* types can't compare with =
|
|
||||||
*/
|
|
||||||
Operator o=oper("=", fktypoid[i], pktypoid[i], false);
|
|
||||||
ReleaseSysCache(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
trig.tgoid = 0;
|
trig.tgoid = 0;
|
||||||
if (fkconstraint->constr_name)
|
if (fkconstraint->constr_name)
|
||||||
trig.tgname = fkconstraint->constr_name;
|
trig.tgname = fkconstraint->constr_name;
|
||||||
@ -1706,7 +1565,6 @@ AlterTableAddConstraint(char *relationName,
|
|||||||
trig.tgnargs = count - 1;
|
trig.tgnargs = count - 1;
|
||||||
|
|
||||||
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
|
scan = heap_beginscan(rel, false, SnapshotNow, 0, NULL);
|
||||||
AssertState(scan != NULL);
|
|
||||||
|
|
||||||
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
|
||||||
{
|
{
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.202 2001/10/22 22:49:02 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.203 2001/10/23 17:39:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -2428,7 +2428,6 @@ getSetColTypes(ParseState *pstate, Node *node)
|
|||||||
/*
|
/*
|
||||||
* transformUpdateStmt -
|
* transformUpdateStmt -
|
||||||
* transforms an update statement
|
* transforms an update statement
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static Query *
|
static Query *
|
||||||
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||||
@ -2802,17 +2801,15 @@ static void
|
|||||||
transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||||
{
|
{
|
||||||
Relation pkrel;
|
Relation pkrel;
|
||||||
Form_pg_attribute *pkrel_attrs;
|
|
||||||
List *indexoidlist,
|
List *indexoidlist,
|
||||||
*indexoidscan;
|
*indexoidscan;
|
||||||
int i;
|
int i;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the referenced table and get the attributes list
|
* Open the referenced table
|
||||||
*/
|
*/
|
||||||
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
|
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
|
||||||
pkrel_attrs = pkrel->rd_att->attrs;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the list of index OIDs for the table from the relcache, and
|
* Get the list of index OIDs for the table from the relcache, and
|
||||||
@ -2827,6 +2824,7 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
|||||||
HeapTuple indexTuple;
|
HeapTuple indexTuple;
|
||||||
Form_pg_index indexStruct;
|
Form_pg_index indexStruct;
|
||||||
|
|
||||||
|
found = false;
|
||||||
indexTuple = SearchSysCache(INDEXRELID,
|
indexTuple = SearchSysCache(INDEXRELID,
|
||||||
ObjectIdGetDatum(indexoid),
|
ObjectIdGetDatum(indexoid),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
@ -2837,16 +2835,14 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
|||||||
|
|
||||||
if (indexStruct->indisunique)
|
if (indexStruct->indisunique)
|
||||||
{
|
{
|
||||||
List *attrl;
|
|
||||||
int attnum=0;
|
|
||||||
|
|
||||||
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
|
for (i = 0; i < INDEX_MAX_KEYS && indexStruct->indkey[i] != 0; i++)
|
||||||
;
|
;
|
||||||
if (i != length(fkconstraint->pk_attrs))
|
if (i == length(fkconstraint->pk_attrs))
|
||||||
found = false;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* go through the fkconstraint->pk_attrs list */
|
/* go through the fkconstraint->pk_attrs list */
|
||||||
|
List *attrl;
|
||||||
|
int attnum = 0;
|
||||||
|
|
||||||
foreach(attrl, fkconstraint->pk_attrs)
|
foreach(attrl, fkconstraint->pk_attrs)
|
||||||
{
|
{
|
||||||
Ident *attr = lfirst(attrl);
|
Ident *attr = lfirst(attrl);
|
||||||
@ -2856,16 +2852,12 @@ transformFkeyCheckAttrs(FkConstraint *fkconstraint, Oid *pktypoid)
|
|||||||
{
|
{
|
||||||
int pkattno = indexStruct->indkey[i];
|
int pkattno = indexStruct->indkey[i];
|
||||||
|
|
||||||
if (pkattno > 0)
|
if (namestrcmp(attnumAttName(pkrel, pkattno),
|
||||||
|
attr->name) == 0)
|
||||||
{
|
{
|
||||||
char *name = NameStr(pkrel_attrs[pkattno - 1]->attname);
|
pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
|
||||||
|
found = true;
|
||||||
if (strcmp(name, attr->name) == 0)
|
break;
|
||||||
{
|
|
||||||
pktypoid[attnum++]=pkrel_attrs[pkattno-1]->atttypid;
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
@ -2896,7 +2888,6 @@ static void
|
|||||||
transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
||||||
{
|
{
|
||||||
Relation pkrel;
|
Relation pkrel;
|
||||||
Form_pg_attribute *pkrel_attrs;
|
|
||||||
List *indexoidlist,
|
List *indexoidlist,
|
||||||
*indexoidscan;
|
*indexoidscan;
|
||||||
HeapTuple indexTuple = NULL;
|
HeapTuple indexTuple = NULL;
|
||||||
@ -2905,10 +2896,9 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
|||||||
int attnum=0;
|
int attnum=0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open the referenced table and get the attributes list
|
* Open the referenced table
|
||||||
*/
|
*/
|
||||||
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
|
pkrel = heap_openr(fkconstraint->pktable_name, AccessShareLock);
|
||||||
pkrel_attrs = pkrel->rd_att->attrs;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the list of index OIDs for the table from the relcache, and
|
* Get the list of index OIDs for the table from the relcache, and
|
||||||
@ -2952,10 +2942,10 @@ transformFkeyGetPrimaryKey(FkConstraint *fkconstraint, Oid *pktypoid)
|
|||||||
int pkattno = indexStruct->indkey[i];
|
int pkattno = indexStruct->indkey[i];
|
||||||
Ident *pkattr = makeNode(Ident);
|
Ident *pkattr = makeNode(Ident);
|
||||||
|
|
||||||
pkattr->name = pstrdup(NameStr(pkrel_attrs[pkattno-1]->attname));
|
pkattr->name = pstrdup(NameStr(*attnumAttName(pkrel, pkattno)));
|
||||||
pkattr->indirection = NIL;
|
pkattr->indirection = NIL;
|
||||||
pkattr->isRel = false;
|
pkattr->isRel = false;
|
||||||
pktypoid[attnum++] = pkrel_attrs[pkattno-1]->atttypid;
|
pktypoid[attnum++] = attnumTypeId(pkrel, pkattno);
|
||||||
|
|
||||||
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
|
fkconstraint->pk_attrs = lappend(fkconstraint->pk_attrs, pkattr);
|
||||||
}
|
}
|
||||||
@ -3023,6 +3013,7 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
|
|||||||
List *cols;
|
List *cols;
|
||||||
List *inher;
|
List *inher;
|
||||||
Oid result;
|
Oid result;
|
||||||
|
Form_pg_attribute sysatt;
|
||||||
|
|
||||||
/* First look for column among the newly-created columns */
|
/* First look for column among the newly-created columns */
|
||||||
foreach(cols, cxt->columns)
|
foreach(cols, cxt->columns)
|
||||||
@ -3040,6 +3031,10 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Perhaps it's a system column name */
|
||||||
|
sysatt = SystemAttributeByName(colname, cxt->hasoids);
|
||||||
|
if (sysatt)
|
||||||
|
return sysatt->atttypid;
|
||||||
/* Look for column among inherited columns (if CREATE TABLE case) */
|
/* Look for column among inherited columns (if CREATE TABLE case) */
|
||||||
foreach(inher, cxt->inhRelnames)
|
foreach(inher, cxt->inhRelnames)
|
||||||
{
|
{
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.57 2001/10/22 22:47:57 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.58 2001/10/23 17:39:02 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -938,7 +938,7 @@ attnameAttNum(Relation rd, char *a)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < rd->rd_rel->relnatts; i++)
|
for (i = 0; i < rd->rd_rel->relnatts; i++)
|
||||||
if (!namestrcmp(&(rd->rd_att->attrs[i]->attname), a))
|
if (namestrcmp(&(rd->rd_att->attrs[i]->attname), a) == 0)
|
||||||
return i + 1;
|
return i + 1;
|
||||||
|
|
||||||
if ((i = specialAttNum(a)) != InvalidAttrNumber)
|
if ((i = specialAttNum(a)) != InvalidAttrNumber)
|
||||||
@ -974,6 +974,28 @@ specialAttNum(char *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* given attribute id, return name of that attribute
|
||||||
|
*
|
||||||
|
* This should only be used if the relation is already
|
||||||
|
* heap_open()'ed. Use the cache version get_atttype()
|
||||||
|
* for access to non-opened relations.
|
||||||
|
*/
|
||||||
|
Name
|
||||||
|
attnumAttName(Relation rd, int attid)
|
||||||
|
{
|
||||||
|
if (attid <= 0)
|
||||||
|
{
|
||||||
|
Form_pg_attribute sysatt;
|
||||||
|
|
||||||
|
sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
|
||||||
|
return &sysatt->attname;
|
||||||
|
}
|
||||||
|
if (attid > rd->rd_att->natts)
|
||||||
|
elog(ERROR, "attnumAttName: invalid attribute number %d", attid);
|
||||||
|
return &rd->rd_att->attrs[attid - 1]->attname;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* given attribute id, return type of that attribute
|
* given attribute id, return type of that attribute
|
||||||
*
|
*
|
||||||
@ -991,10 +1013,8 @@ attnumTypeId(Relation rd, int attid)
|
|||||||
sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
|
sysatt = SystemAttributeDefinition(attid, rd->rd_rel->relhasoids);
|
||||||
return sysatt->atttypid;
|
return sysatt->atttypid;
|
||||||
}
|
}
|
||||||
|
if (attid > rd->rd_att->natts)
|
||||||
/*
|
elog(ERROR, "attnumTypeId: invalid attribute number %d", attid);
|
||||||
* -1 because attid is 1-based
|
|
||||||
*/
|
|
||||||
return rd->rd_att->attrs[attid - 1]->atttypid;
|
return rd->rd_att->attrs[attid - 1]->atttypid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $Id: parse_relation.h,v 1.24 2001/08/10 18:57:41 tgl Exp $
|
* $Id: parse_relation.h,v 1.25 2001/10/23 17:39:03 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -45,6 +45,7 @@ extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte);
|
|||||||
extern List *expandJoinAttrs(ParseState *pstate, JoinExpr *join,
|
extern List *expandJoinAttrs(ParseState *pstate, JoinExpr *join,
|
||||||
int sublevels_up);
|
int sublevels_up);
|
||||||
extern int attnameAttNum(Relation rd, char *a);
|
extern int attnameAttNum(Relation rd, char *a);
|
||||||
|
extern Name attnumAttName(Relation rd, int attid);
|
||||||
extern Oid attnumTypeId(Relation rd, int attid);
|
extern Oid attnumTypeId(Relation rd, int attid);
|
||||||
|
|
||||||
#endif /* PARSE_RELATION_H */
|
#endif /* PARSE_RELATION_H */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user