aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/common/tupdesc.c9
-rw-r--r--src/backend/bootstrap/bootstrap.c51
-rw-r--r--src/backend/catalog/dependency.c5
-rw-r--r--src/backend/catalog/heap.c88
-rw-r--r--src/backend/catalog/pg_proc.c51
-rw-r--r--src/backend/commands/analyze.c27
-rw-r--r--src/backend/commands/comment.c6
-rw-r--r--src/backend/commands/copy.c581
-rw-r--r--src/backend/commands/indexcmds.c12
-rw-r--r--src/backend/commands/tablecmds.c202
-rw-r--r--src/backend/optimizer/prep/preptlist.c27
-rw-r--r--src/backend/optimizer/prep/prepunion.c15
-rw-r--r--src/backend/parser/analyze.c25
-rw-r--r--src/backend/parser/parse_func.c5
-rw-r--r--src/backend/parser/parse_relation.c151
-rw-r--r--src/backend/parser/parse_target.c10
-rw-r--r--src/backend/parser/parse_type.c6
-rw-r--r--src/backend/rewrite/rewriteDefine.c12
-rw-r--r--src/backend/rewrite/rewriteHandler.c6
-rw-r--r--src/backend/utils/adt/not_in.c29
-rw-r--r--src/backend/utils/cache/lsyscache.c37
-rw-r--r--src/backend/utils/cache/syscache.c67
-rw-r--r--src/bin/pg_dump/pg_dump.c53
-rw-r--r--src/bin/pg_dump/pg_dump.h3
-rw-r--r--src/bin/psql/describe.c4
-rw-r--r--src/bin/psql/tab-complete.c4
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/heap.h3
-rw-r--r--src/include/catalog/pg_attribute.h456
-rw-r--r--src/include/catalog/pg_class.h4
-rw-r--r--src/include/executor/executor.h3
-rw-r--r--src/include/parser/parse_relation.h4
-rw-r--r--src/include/utils/lsyscache.h5
-rw-r--r--src/include/utils/syscache.h6
-rw-r--r--src/pl/plpgsql/src/pl_comp.c7
-rw-r--r--src/test/regress/expected/alter_table.out294
-rw-r--r--src/test/regress/expected/copy2.out44
-rw-r--r--src/test/regress/sql/alter_table.sql160
-rw-r--r--src/test/regress/sql/copy2.sql6
39 files changed, 1678 insertions, 804 deletions
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index 1eb62dea91a..249be870002 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.82 2002/07/31 17:19:51 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.83 2002/08/02 18:15:04 tgl Exp $
*
* NOTES
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -111,7 +111,7 @@ CreateTupleDescCopy(TupleDesc tupdesc)
for (i = 0; i < desc->natts; i++)
{
desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
- memmove(desc->attrs[i],
+ memcpy(desc->attrs[i],
tupdesc->attrs[i],
ATTRIBUTE_TUPLE_SIZE);
desc->attrs[i]->attnotnull = false;
@@ -146,7 +146,7 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
for (i = 0; i < desc->natts; i++)
{
desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
- memmove(desc->attrs[i],
+ memcpy(desc->attrs[i],
tupdesc->attrs[i],
ATTRIBUTE_TUPLE_SIZE);
}
@@ -263,6 +263,8 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
return false;
if (attr1->attnotnull != attr2->attnotnull)
return false;
+ if (attr1->attisdropped != attr2->attisdropped)
+ return false;
}
if (tupdesc1->constr != NULL)
{
@@ -385,6 +387,7 @@ TupleDescInitEntry(TupleDesc desc,
att->attnotnull = false;
att->atthasdef = false;
+ att->attisdropped = false;
tuple = SearchSysCache(TYPEOID,
ObjectIdGetDatum(oidtypeid),
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 4300c0211da..f48c8389ce6 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.133 2002/07/20 05:16:56 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.134 2002/08/02 18:15:04 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -522,19 +522,6 @@ boot_openrel(char *relname)
(char *) boot_reldesc->rd_att->attrs[i],
ATTRIBUTE_TUPLE_SIZE);
- /* Some old pg_attribute tuples might not have attisset. */
-
- /*
- * If the attname is attisset, don't look for it - it may not be
- * defined yet.
- */
- if (namestrcmp(&attrtypes[i]->attname, "attisset") == 0)
- attrtypes[i]->attisset =
- get_attisset(RelationGetRelid(boot_reldesc),
- NameStr(attrtypes[i]->attname));
- else
- attrtypes[i]->attisset = false;
-
{
Form_pg_attribute at = attrtypes[i];
@@ -598,15 +585,19 @@ DefineAttr(char *name, char *type, int attnum)
closerel(relname);
}
- typeoid = gettype(type);
if (attrtypes[attnum] == (Form_pg_attribute) NULL)
attrtypes[attnum] = AllocateAttribute();
+ MemSet(attrtypes[attnum], 0, ATTRIBUTE_TUPLE_SIZE);
+
+ namestrcpy(&attrtypes[attnum]->attname, name);
+ elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
+ attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
+
+ typeoid = gettype(type);
+
if (Typ != (struct typmap **) NULL)
{
attrtypes[attnum]->atttypid = Ap->am_oid;
- namestrcpy(&attrtypes[attnum]->attname, name);
- elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
- attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
attlen = attrtypes[attnum]->attlen = Ap->am_typ.typlen;
attrtypes[attnum]->attbyval = Ap->am_typ.typbyval;
attrtypes[attnum]->attstorage = Ap->am_typ.typstorage;
@@ -615,9 +606,6 @@ DefineAttr(char *name, char *type, int attnum)
else
{
attrtypes[attnum]->atttypid = Procid[typeoid].oid;
- namestrcpy(&attrtypes[attnum]->attname, name);
- elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
- attrtypes[attnum]->attnum = 1 + attnum; /* fillatt */
attlen = attrtypes[attnum]->attlen = Procid[typeoid].len;
/*
@@ -656,6 +644,23 @@ DefineAttr(char *name, char *type, int attnum)
}
attrtypes[attnum]->attcacheoff = -1;
attrtypes[attnum]->atttypmod = -1;
+ /*
+ * Mark as "not null" if type is fixed-width and prior columns are too.
+ * This corresponds to case where column can be accessed directly via
+ * C struct declaration.
+ */
+ if (attlen > 0)
+ {
+ int i;
+
+ for (i = 0; i < attnum; i++)
+ {
+ if (attrtypes[i]->attlen <= 0)
+ break;
+ }
+ if (i == attnum)
+ attrtypes[attnum]->attnotnull = true;
+ }
}
@@ -896,8 +901,8 @@ gettype(char *type)
* AllocateAttribute
* ----------------
*/
-static Form_pg_attribute /* XXX */
-AllocateAttribute()
+static Form_pg_attribute
+AllocateAttribute(void)
{
Form_pg_attribute attribute = (Form_pg_attribute) malloc(ATTRIBUTE_TUPLE_SIZE);
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index ae88c4bf055..d51c8d589a9 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.7 2002/07/29 22:14:10 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.8 2002/08/02 18:15:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -567,7 +567,8 @@ doDeletion(const ObjectAddress *object)
else
{
if (object->objectSubId != 0)
- elog(ERROR, "DROP COLUMN not implemented yet");
+ RemoveAttributeById(object->objectId,
+ object->objectSubId);
else
heap_drop_with_catalog(object->objectId);
}
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 6045c17bb6a..ec9165c55b1 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.214 2002/07/31 17:19:51 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.215 2002/08/02 18:15:05 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -97,37 +97,37 @@ static void RemoveStatistics(Relation rel);
static FormData_pg_attribute a1 = {
0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
SelfItemPointerAttributeNumber, 0, -1, -1,
- false, 'p', false, 'i', true, false
+ false, 'p', false, 'i', true, false, false
};
static FormData_pg_attribute a2 = {
0, {"oid"}, OIDOID, 0, sizeof(Oid),
ObjectIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', true, false
+ true, 'p', false, 'i', true, false, false
};
static FormData_pg_attribute a3 = {
0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
MinTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', true, false
+ true, 'p', false, 'i', true, false, false
};
static FormData_pg_attribute a4 = {
0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
MinCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', true, false
+ true, 'p', false, 'i', true, false, false
};
static FormData_pg_attribute a5 = {
0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
MaxTransactionIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', true, false
+ true, 'p', false, 'i', true, false, false
};
static FormData_pg_attribute a6 = {
0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
MaxCommandIdAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', true, false
+ true, 'p', false, 'i', true, false, false
};
/*
@@ -139,7 +139,7 @@ static FormData_pg_attribute a6 = {
static FormData_pg_attribute a7 = {
0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
TableOidAttributeNumber, 0, -1, -1,
- true, 'p', false, 'i', true, false
+ true, 'p', false, 'i', true, false, false
};
static Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
@@ -893,6 +893,78 @@ DeleteAttributeTuples(Oid relid)
}
/*
+ * RemoveAttributeById
+ *
+ * This is the guts of ALTER TABLE DROP COLUMN: actually mark the attribute
+ * deleted in pg_attribute. (Everything else needed, such as getting rid
+ * of any pg_attrdef entry, is handled by dependency.c.)
+ */
+void
+RemoveAttributeById(Oid relid, AttrNumber attnum)
+{
+ Relation rel;
+ Relation attr_rel;
+ HeapTuple tuple;
+ Form_pg_attribute attStruct;
+ char newattname[NAMEDATALEN];
+
+ /*
+ * Grab an exclusive lock on the target table, which we will NOT
+ * release until end of transaction. (In the simple case where
+ * we are directly dropping this column, AlterTableDropColumn already
+ * did this ... but when cascading from a drop of some other object,
+ * we may not have any lock.)
+ */
+ rel = heap_open(relid, AccessExclusiveLock);
+
+ attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
+
+ tuple = SearchSysCacheCopy(ATTNUM,
+ ObjectIdGetDatum(relid),
+ Int16GetDatum(attnum),
+ 0, 0);
+ if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
+ elog(ERROR, "RemoveAttributeById: Failed to find attribute %d in relation %u",
+ attnum, relid);
+ attStruct = (Form_pg_attribute) GETSTRUCT(tuple);
+
+ /* Mark the attribute as dropped */
+ attStruct->attisdropped = true;
+
+ /* Remove any NOT NULL constraint the column may have */
+ attStruct->attnotnull = false;
+
+ /* We don't want to keep stats for it anymore */
+ attStruct->attstattarget = 0;
+
+ /* Change the column name to something that isn't likely to conflict */
+ snprintf(newattname, NAMEDATALEN, "........pg.dropped.%d........", attnum);
+ namestrcpy(&(attStruct->attname), newattname);
+
+ simple_heap_update(attr_rel, &tuple->t_self, tuple);
+
+ /* keep the system catalog indices current */
+ if (RelationGetForm(attr_rel)->relhasindex)
+ {
+ Relation idescs[Num_pg_attr_indices];
+
+ CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
+ CatalogIndexInsert(idescs, Num_pg_attr_indices, attr_rel, tuple);
+ CatalogCloseIndices(Num_pg_attr_indices, idescs);
+ }
+
+ /*
+ * Because updating the pg_attribute row will trigger a relcache flush
+ * for the target relation, we need not do anything else to notify
+ * other backends of the change.
+ */
+
+ heap_close(attr_rel, RowExclusiveLock);
+
+ heap_close(rel, NoLock);
+}
+
+/*
* RemoveAttrDefault
*
* If the specified relation/attribute has a default, remove it.
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index 2a11474e9f5..2624fdaf25d 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.81 2002/07/24 19:11:09 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.82 2002/08/02 18:15:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -327,9 +327,9 @@ checkretval(Oid rettype, List *queryTreeList)
Oid typerelid;
Oid restype;
Relation reln;
- Oid relid;
- int relnatts;
- int i;
+ int relnatts; /* physical number of columns in rel */
+ int rellogcols; /* # of nondeleted columns in rel */
+ int colindex; /* physical column index */
/* guard against empty function body; OK only if no return type */
if (queryTreeList == NIL)
@@ -404,42 +404,55 @@ checkretval(Oid rettype, List *queryTreeList)
/*
* By here, the procedure returns a tuple or set of tuples. This part
* of the typechecking is a hack. We look up the relation that is the
- * declared return type, and be sure that attributes 1 .. n in the
- * target list match the declared types.
+ * declared return type, and scan the non-deleted attributes to ensure
+ * that they match the datatypes of the non-resjunk columns.
*/
reln = heap_open(typerelid, AccessShareLock);
- relid = reln->rd_id;
relnatts = reln->rd_rel->relnatts;
+ rellogcols = 0; /* we'll count nondeleted cols as we go */
+ colindex = 0;
- if (tlistlen != relnatts)
- elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
- format_type_be(rettype), relnatts);
-
- /* expect attributes 1 .. n in order */
- i = 0;
foreach(tlistitem, tlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(tlistitem);
+ Form_pg_attribute attr;
Oid tletype;
Oid atttype;
if (tle->resdom->resjunk)
continue;
+
+ do {
+ colindex++;
+ if (colindex > relnatts)
+ elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
+ format_type_be(rettype), rellogcols);
+ attr = reln->rd_att->attrs[colindex - 1];
+ } while (attr->attisdropped);
+ rellogcols++;
+
tletype = exprType(tle->expr);
- atttype = reln->rd_att->attrs[i]->atttypid;
+ atttype = attr->atttypid;
if (!IsBinaryCompatible(tletype, atttype))
elog(ERROR, "function declared to return %s returns %s instead of %s at column %d",
format_type_be(rettype),
format_type_be(tletype),
format_type_be(atttype),
- i + 1);
- i++;
+ rellogcols);
+ }
+
+ for (;;)
+ {
+ colindex++;
+ if (colindex > relnatts)
+ break;
+ if (!reln->rd_att->attrs[colindex - 1]->attisdropped)
+ rellogcols++;
}
- /* this shouldn't happen, but let's just check... */
- if (i != relnatts)
+ if (tlistlen != rellogcols)
elog(ERROR, "function declared to return %s does not SELECT the right number of columns (%d)",
- format_type_be(rettype), relnatts);
+ format_type_be(rettype), rellogcols);
heap_close(reln, AccessShareLock);
}
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 55069aa6feb..9844a5df0a9 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.39 2002/07/31 17:19:51 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.40 2002/08/02 18:15:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,6 +27,7 @@
#include "commands/vacuum.h"
#include "miscadmin.h"
#include "parser/parse_oper.h"
+#include "parser/parse_relation.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/datum.h"
@@ -147,7 +148,6 @@ void
analyze_rel(Oid relid, VacuumStmt *vacstmt)
{
Relation onerel;
- Form_pg_attribute *attr;
int attr_cnt,
tcnt,
i;
@@ -234,9 +234,6 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
*
* Note that system attributes are never analyzed.
*/
- attr = onerel->rd_att->attrs;
- attr_cnt = onerel->rd_att->natts;
-
if (vacstmt->va_cols != NIL)
{
List *le;
@@ -248,15 +245,8 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
{
char *col = strVal(lfirst(le));
- for (i = 0; i < attr_cnt; i++)
- {
- if (namestrcmp(&(attr[i]->attname), col) == 0)
- break;
- }
- if (i >= attr_cnt)
- elog(ERROR, "ANALYZE: there is no attribute %s in %s",
- col, RelationGetRelationName(onerel));
- vacattrstats[tcnt] = examine_attribute(onerel, i + 1);
+ i = attnameAttNum(onerel, col, false);
+ vacattrstats[tcnt] = examine_attribute(onerel, i);
if (vacattrstats[tcnt] != NULL)
tcnt++;
}
@@ -264,12 +254,13 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
}
else
{
+ attr_cnt = onerel->rd_att->natts;
vacattrstats = (VacAttrStats **) palloc(attr_cnt *
sizeof(VacAttrStats *));
tcnt = 0;
- for (i = 0; i < attr_cnt; i++)
+ for (i = 1; i <= attr_cnt; i++)
{
- vacattrstats[tcnt] = examine_attribute(onerel, i + 1);
+ vacattrstats[tcnt] = examine_attribute(onerel, i);
if (vacattrstats[tcnt] != NULL)
tcnt++;
}
@@ -388,6 +379,10 @@ examine_attribute(Relation onerel, int attnum)
Oid ltopr = InvalidOid;
VacAttrStats *stats;
+ /* Don't analyze dropped columns */
+ if (attr->attisdropped)
+ return NULL;
+
/* Don't analyze column if user has specified not to */
if (attr->attstattarget == 0)
return NULL;
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index c5dee8f8af9..118c2c4b777 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
* Copyright (c) 1996-2001, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.53 2002/07/29 23:46:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.54 2002/08/02 18:15:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -382,8 +382,8 @@ CommentAttribute(List *qualname, char *comment)
attnum = get_attnum(RelationGetRelid(relation), attrname);
if (attnum == InvalidAttrNumber)
- elog(ERROR, "\"%s\" is not an attribute of class \"%s\"",
- attrname, RelationGetRelationName(relation));
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ RelationGetRelationName(relation), attrname);
/* Create the comment using the relation's oid */
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 19e17ed2873..2529b728230 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.161 2002/07/30 16:55:06 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.162 2002/08/02 18:15:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -31,6 +31,7 @@
#include "rewrite/rewriteHandler.h"
#include "libpq/libpq.h"
#include "miscadmin.h"
+#include "parser/parse_relation.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "utils/acl.h"
@@ -53,13 +54,15 @@ typedef enum CopyReadResult
} CopyReadResult;
/* non-export function prototypes */
-static void CopyTo(Relation rel, List *attlist, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
-static void CopyFrom(Relation rel, List *attlist, bool binary, bool oids, FILE *fp, char *delim, char *null_print);
+static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
+ FILE *fp, char *delim, char *null_print);
+static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
+ FILE *fp, char *delim, char *null_print);
static Oid GetInputFunction(Oid type);
static Oid GetTypeElement(Oid type);
static char *CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result);
static void CopyAttributeOut(FILE *fp, char *string, char *delim);
-static void CopyCheckAttlist(Relation rel, List *attlist);
+static List *CopyGetAttnums(Relation rel, List *attnamelist);
static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0";
@@ -275,7 +278,8 @@ DoCopy(const CopyStmt *stmt)
bool is_from = stmt->is_from;
bool pipe = (stmt->filename == NULL);
List *option;
- List *attlist = stmt->attlist;
+ List *attnamelist = stmt->attlist;
+ List *attnumlist;
bool binary = false;
bool oids = false;
char *delim = NULL;
@@ -374,6 +378,11 @@ DoCopy(const CopyStmt *stmt)
RelationGetRelationName(rel));
/*
+ * Generate or convert list of attributes to process
+ */
+ attnumlist = CopyGetAttnums(rel, attnamelist);
+
+ /*
* Set up variables to avoid per-attribute overhead.
*/
initStringInfo(&attribute_buf);
@@ -382,26 +391,6 @@ DoCopy(const CopyStmt *stmt)
server_encoding = GetDatabaseEncoding();
#endif
- if (attlist == NIL)
- {
- /* get list of attributes in the relation */
- TupleDesc desc = RelationGetDescr(rel);
- int i;
- for (i = 0; i < desc->natts; ++i)
- {
- Ident *id = makeNode(Ident);
- id->name = NameStr(desc->attrs[i]->attname);
- attlist = lappend(attlist,id);
- }
- }
- else
- {
- if (binary)
- elog(ERROR,"COPY: BINARY format cannot be used with specific column list");
-
- CopyCheckAttlist(rel, attlist);
- }
-
if (is_from)
{ /* copy from file to database */
if (rel->rd_rel->relkind != RELKIND_RELATION)
@@ -442,10 +431,10 @@ DoCopy(const CopyStmt *stmt)
if (S_ISDIR(st.st_mode))
{
FreeFile(fp);
- elog(ERROR, "COPY: %s is a directory.", filename);
+ elog(ERROR, "COPY: %s is a directory", filename);
}
}
- CopyFrom(rel, attlist, binary, oids, fp, delim, null_print);
+ CopyFrom(rel, attnumlist, binary, oids, fp, delim, null_print);
}
else
{ /* copy from database to file */
@@ -483,7 +472,7 @@ DoCopy(const CopyStmt *stmt)
*/
if (filename[0] != '/')
elog(ERROR, "Relative path not allowed for server side"
- " COPY command.");
+ " COPY command");
oumask = umask((mode_t) 022);
fp = AllocateFile(filename, PG_BINARY_W);
@@ -498,10 +487,10 @@ DoCopy(const CopyStmt *stmt)
if (S_ISDIR(st.st_mode))
{
FreeFile(fp);
- elog(ERROR, "COPY: %s is a directory.", filename);
+ elog(ERROR, "COPY: %s is a directory", filename);
}
}
- CopyTo(rel, attlist, binary, oids, fp, delim, null_print);
+ CopyTo(rel, attnumlist, binary, oids, fp, delim, null_print);
}
if (!pipe)
@@ -529,14 +518,14 @@ DoCopy(const CopyStmt *stmt)
* Copy from relation TO file.
*/
static void
-CopyTo(Relation rel, List *attlist, bool binary, bool oids,
+CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
FILE *fp, char *delim, char *null_print)
{
HeapTuple tuple;
TupleDesc tupDesc;
HeapScanDesc scandesc;
- int attr_count,
- i;
+ int num_phys_attrs;
+ int attr_count;
Form_pg_attribute *attr;
FmgrInfo *out_functions;
Oid *elements;
@@ -544,48 +533,33 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
int16 fld_size;
char *string;
Snapshot mySnapshot;
- int copy_attr_count;
- int *attmap;
- int p = 0;
List *cur;
tupDesc = rel->rd_att;
- attr_count = rel->rd_att->natts;
- attr = rel->rd_att->attrs;
-
- copy_attr_count = length(attlist);
- attmap = (int *) palloc(copy_attr_count * sizeof(int));
-
- foreach(cur, attlist)
- {
- const char *currAtt = strVal(lfirst(cur));
-
- for (i = 0; i < attr_count; i++)
- {
- if (namestrcmp(&attr[i]->attname, currAtt) == 0)
- {
- attmap[p++] = i;
- continue;
- }
- }
- }
+ attr = tupDesc->attrs;
+ num_phys_attrs = tupDesc->natts;
+ attr_count = length(attnumlist);
/*
+ * Get info about the columns we need to process.
+ *
* For binary copy we really only need isvarlena, but compute it
* all...
*/
- out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
- elements = (Oid *) palloc(attr_count * sizeof(Oid));
- isvarlena = (bool *) palloc(attr_count * sizeof(bool));
- for (i = 0; i < attr_count; i++)
+ out_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
+ elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
+ isvarlena = (bool *) palloc(num_phys_attrs * sizeof(bool));
+ foreach(cur, attnumlist)
{
+ int attnum = lfirsti(cur);
Oid out_func_oid;
- if (!getTypeOutputInfo(attr[i]->atttypid,
- &out_func_oid, &elements[i], &isvarlena[i]))
+ if (!getTypeOutputInfo(attr[attnum-1]->atttypid,
+ &out_func_oid, &elements[attnum-1],
+ &isvarlena[attnum-1]))
elog(ERROR, "COPY: couldn't lookup info for type %u",
- attr[i]->atttypid);
- fmgr_info(out_func_oid, &out_functions[i]);
+ attr[attnum-1]->atttypid);
+ fmgr_info(out_func_oid, &out_functions[attnum-1]);
}
if (binary)
@@ -650,14 +624,14 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
}
}
- for (i = 0; i < copy_attr_count; i++)
+ foreach(cur, attnumlist)
{
+ int attnum = lfirsti(cur);
Datum origvalue,
value;
bool isnull;
- int mi = attmap[i];
- origvalue = heap_getattr(tuple, mi + 1, tupDesc, &isnull);
+ origvalue = heap_getattr(tuple, attnum, tupDesc, &isnull);
if (!binary)
{
@@ -686,25 +660,25 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
* (or for binary case, becase we must output untoasted
* value).
*/
- if (isvarlena[mi])
+ if (isvarlena[attnum-1])
value = PointerGetDatum(PG_DETOAST_DATUM(origvalue));
else
value = origvalue;
if (!binary)
{
- string = DatumGetCString(FunctionCall3(&out_functions[mi],
+ string = DatumGetCString(FunctionCall3(&out_functions[attnum-1],
value,
- ObjectIdGetDatum(elements[mi]),
- Int32GetDatum(attr[mi]->atttypmod)));
+ ObjectIdGetDatum(elements[attnum-1]),
+ Int32GetDatum(attr[attnum-1]->atttypmod)));
CopyAttributeOut(fp, string, delim);
pfree(string);
}
else
{
- fld_size = attr[mi]->attlen;
+ fld_size = attr[attnum-1]->attlen;
CopySendData(&fld_size, sizeof(int16), fp);
- if (isvarlena[mi])
+ if (isvarlena[attnum-1])
{
/* varlena */
Assert(fld_size == -1);
@@ -712,7 +686,7 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
VARSIZE(value),
fp);
}
- else if (!attr[mi]->attbyval)
+ else if (!attr[attnum-1]->attbyval)
{
/* fixed-length pass-by-reference */
Assert(fld_size > 0);
@@ -767,36 +741,36 @@ CopyTo(Relation rel, List *attlist, bool binary, bool oids,
* Copy FROM file to relation.
*/
static void
-CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
+CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
FILE *fp, char *delim, char *null_print)
{
HeapTuple tuple;
TupleDesc tupDesc;
Form_pg_attribute *attr;
- AttrNumber attr_count, copy_attr_count, def_attr_count;
+ AttrNumber num_phys_attrs, attr_count, num_defaults;
FmgrInfo *in_functions;
Oid *elements;
int i;
+ List *cur;
Oid in_func_oid;
Datum *values;
char *nulls;
- int done = 0;
+ bool done = false;
ResultRelInfo *resultRelInfo;
EState *estate = CreateExecutorState(); /* for ExecConstraints() */
TupleTable tupleTable;
TupleTableSlot *slot;
bool file_has_oids;
- int *attmap = NULL;
- int *defmap = NULL;
- Node **defexprs = NULL; /* array of default att expressions */
+ int *defmap;
+ Node **defexprs; /* array of default att expressions */
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
- ExprDoneCond isdone;
+ MemoryContext oldcontext = CurrentMemoryContext;
tupDesc = RelationGetDescr(rel);
attr = tupDesc->attrs;
- attr_count = tupDesc->natts;
- copy_attr_count = length(attlist);
- def_attr_count = 0;
+ num_phys_attrs = tupDesc->natts;
+ attr_count = length(attnumlist);
+ num_defaults = 0;
/*
* We need a ResultRelInfo so we can use the regular executor's
@@ -819,50 +793,40 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, tupDesc, false);
- if (!binary)
+ /*
+ * pick up the input function and default expression (if any) for
+ * each attribute in the relation. (We don't actually use the
+ * input function if it's a binary copy.)
+ */
+ defmap = (int *) palloc(sizeof(int) * num_phys_attrs);
+ defexprs = (Node **) palloc(sizeof(Node *) * num_phys_attrs);
+ in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
+ elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
+
+ for (i = 0; i < num_phys_attrs; i++)
{
- /*
- * pick up the input function and default expression (if any) for
- * each attribute in the relation.
- */
- attmap = (int *) palloc(sizeof(int) * attr_count);
- defmap = (int *) palloc(sizeof(int) * attr_count);
- defexprs = (Node **) palloc(sizeof(Node *) * attr_count);
- in_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
- elements = (Oid *) palloc(attr_count * sizeof(Oid));
- for (i = 0; i < attr_count; i++)
- {
- List *l;
- int p = 0;
- bool specified = false;
+ /* We don't need info for dropped attributes */
+ if (attr[i]->attisdropped)
+ continue;
- in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
- fmgr_info(in_func_oid, &in_functions[i]);
- elements[i] = GetTypeElement(attr[i]->atttypid);
+ in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
+ fmgr_info(in_func_oid, &in_functions[i]);
+ elements[i] = GetTypeElement(attr[i]->atttypid);
- foreach(l, attlist)
- {
- if (namestrcmp(&attr[i]->attname, strVal(lfirst(l))) == 0)
- {
- attmap[p] = i;
- specified = true;
- continue;
- }
- p++;
- }
-
- /* if column not specified, use default value if one exists */
- if (! specified)
+ /* if column not specified, use default value if one exists */
+ if (!intMember(i + 1, attnumlist))
+ {
+ defexprs[num_defaults] = build_column_default(rel, i + 1);
+ if (defexprs[num_defaults] != NULL)
{
- defexprs[def_attr_count] = build_column_default(rel, i + 1);
-
- if (defexprs[def_attr_count] != NULL)
- {
- defmap[def_attr_count] = i;
- def_attr_count++;
- }
+ defmap[num_defaults] = i;
+ num_defaults++;
}
}
+ }
+
+ if (!binary)
+ {
file_has_oids = oids; /* must rely on user to tell us this... */
}
else
@@ -898,13 +862,10 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
if (CopyGetEof(fp))
elog(ERROR, "COPY BINARY: bogus file header (wrong length)");
}
-
- in_functions = NULL;
- elements = NULL;
}
- values = (Datum *) palloc(attr_count * sizeof(Datum));
- nulls = (char *) palloc(attr_count * sizeof(char));
+ values = (Datum *) palloc(num_phys_attrs * sizeof(Datum));
+ nulls = (char *) palloc(num_phys_attrs * sizeof(char));
copy_lineno = 0;
fe_eof = false;
@@ -914,58 +875,77 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
while (!done)
{
bool skip_tuple;
- Oid loaded_oid;
+ Oid loaded_oid = InvalidOid;
CHECK_FOR_INTERRUPTS();
copy_lineno++;
- /* Reset the per-output-tuple exprcontext */
+ /* Reset the per-tuple exprcontext */
ResetPerTupleExprContext(estate);
+ /* Switch to and reset per-tuple memory context, too */
+ MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
+ MemoryContextReset(CurrentMemoryContext);
+
/* Initialize all values for row to NULL */
- MemSet(values, 0, attr_count * sizeof(Datum));
- MemSet(nulls, 'n', attr_count * sizeof(char));
+ MemSet(values, 0, num_phys_attrs * sizeof(Datum));
+ MemSet(nulls, 'n', num_phys_attrs * sizeof(char));
if (!binary)
{
- CopyReadResult result;
+ CopyReadResult result = NORMAL_ATTR;
char *string;
if (file_has_oids)
{
string = CopyReadAttribute(fp, delim, &result);
- if (result == END_OF_FILE)
- done = 1;
- else if (string == NULL || strcmp(string, null_print) == 0)
- elog(ERROR, "COPY TEXT: NULL Oid");
+ if (result == END_OF_FILE && *string == '\0')
+ {
+ /* EOF at start of line: all is well */
+ done = true;
+ break;
+ }
+
+ if (strcmp(string, null_print) == 0)
+ elog(ERROR, "NULL Oid");
else
{
loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(string)));
if (loaded_oid == InvalidOid)
- elog(ERROR, "COPY TEXT: Invalid Oid");
+ elog(ERROR, "Invalid Oid");
}
}
- /*
- * here, we only try to read as many attributes as
- * were specified.
+ /*
+ * Loop to read the user attributes on the line.
*/
- for (i = 0; i < copy_attr_count && !done; i++)
+ foreach(cur, attnumlist)
{
- int m = attmap[i];
+ int attnum = lfirsti(cur);
+ int m = attnum - 1;
+
+ /*
+ * If prior attr on this line was ended by newline or EOF,
+ * complain.
+ */
+ if (result != NORMAL_ATTR)
+ elog(ERROR, "Missing data for column \"%s\"",
+ NameStr(attr[m]->attname));
string = CopyReadAttribute(fp, delim, &result);
- /* If we got an end-of-line before we expected, bail out */
- if (result == END_OF_LINE && i < (copy_attr_count - 1))
- elog(ERROR, "COPY TEXT: Missing data for attribute %d", i + 1);
+ if (result == END_OF_FILE && *string == '\0' &&
+ cur == attnumlist && !file_has_oids)
+ {
+ /* EOF at start of line: all is well */
+ done = true;
+ break; /* out of per-attr loop */
+ }
- if (result == END_OF_FILE)
- done = 1;
- else if (strcmp(string, null_print) == 0)
+ if (strcmp(string, null_print) == 0)
{
/* we read an SQL NULL, no need to do anything */
}
@@ -979,124 +959,149 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
}
}
- if (result == NORMAL_ATTR && !done)
- elog(ERROR, "COPY TEXT: Extra data encountered");
+ if (done)
+ break; /* out of per-row loop */
+
+ /* Complain if there are more fields on the input line */
+ if (result == NORMAL_ATTR)
+ elog(ERROR, "Extra data after last expected column");
/*
- * as above, we only try a default lookup if one is
- * known to be available
+ * If we got some data on the line, but it was ended by EOF,
+ * process the line normally but set flag to exit the loop
+ * when we return to the top.
*/
- for (i = 0; i < def_attr_count && !done; i++)
- {
- bool isnull;
- values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
- &isnull, &isdone);
-
- if (! isnull)
- nulls[defmap[i]] = ' ';
- }
+ if (result == END_OF_FILE)
+ done = true;
}
else
- { /* binary */
+ {
+ /* binary */
int16 fld_count,
fld_size;
CopyGetData(&fld_count, sizeof(int16), fp);
if (CopyGetEof(fp) || fld_count == -1)
- done = 1;
- else
{
- if (fld_count <= 0 || fld_count > attr_count)
- elog(ERROR, "COPY BINARY: tuple field count is %d, expected %d",
- (int) fld_count, attr_count);
+ done = true;
+ break;
+ }
+
+ if (fld_count != attr_count)
+ elog(ERROR, "COPY BINARY: tuple field count is %d, expected %d",
+ (int) fld_count, attr_count);
+
+ if (file_has_oids)
+ {
+ CopyGetData(&fld_size, sizeof(int16), fp);
+ if (CopyGetEof(fp))
+ elog(ERROR, "COPY BINARY: unexpected EOF");
+ if (fld_size != (int16) sizeof(Oid))
+ elog(ERROR, "COPY BINARY: sizeof(Oid) is %d, expected %d",
+ (int) fld_size, (int) sizeof(Oid));
+ CopyGetData(&loaded_oid, sizeof(Oid), fp);
+ if (CopyGetEof(fp))
+ elog(ERROR, "COPY BINARY: unexpected EOF");
+ if (loaded_oid == InvalidOid)
+ elog(ERROR, "COPY BINARY: Invalid Oid");
+ }
- if (file_has_oids)
+ i = 0;
+ foreach(cur, attnumlist)
+ {
+ int attnum = lfirsti(cur);
+
+ i++;
+
+ CopyGetData(&fld_size, sizeof(int16), fp);
+ if (CopyGetEof(fp))
+ elog(ERROR, "COPY BINARY: unexpected EOF");
+ if (fld_size == 0)
+ continue; /* it's NULL; nulls[attnum-1] already set */
+ if (fld_size != attr[attnum-1]->attlen)
+ elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
+ i, (int) fld_size, (int) attr[attnum-1]->attlen);
+ if (fld_size == -1)
{
- CopyGetData(&fld_size, sizeof(int16), fp);
+ /* varlena field */
+ int32 varlena_size;
+ Pointer varlena_ptr;
+
+ CopyGetData(&varlena_size, sizeof(int32), fp);
if (CopyGetEof(fp))
elog(ERROR, "COPY BINARY: unexpected EOF");
- if (fld_size != (int16) sizeof(Oid))
- elog(ERROR, "COPY BINARY: sizeof(Oid) is %d, expected %d",
- (int) fld_size, (int) sizeof(Oid));
- CopyGetData(&loaded_oid, sizeof(Oid), fp);
+ if (varlena_size < (int32) sizeof(int32))
+ elog(ERROR, "COPY BINARY: bogus varlena length");
+ varlena_ptr = (Pointer) palloc(varlena_size);
+ VARATT_SIZEP(varlena_ptr) = varlena_size;
+ CopyGetData(VARDATA(varlena_ptr),
+ varlena_size - sizeof(int32),
+ fp);
if (CopyGetEof(fp))
elog(ERROR, "COPY BINARY: unexpected EOF");
- if (loaded_oid == InvalidOid)
- elog(ERROR, "COPY BINARY: Invalid Oid");
+ values[attnum-1] = PointerGetDatum(varlena_ptr);
}
-
- for (i = 0; i < (int) fld_count; i++)
+ else if (!attr[attnum-1]->attbyval)
{
- CopyGetData(&fld_size, sizeof(int16), fp);
+ /* fixed-length pass-by-reference */
+ Pointer refval_ptr;
+
+ Assert(fld_size > 0);
+ refval_ptr = (Pointer) palloc(fld_size);
+ CopyGetData(refval_ptr, fld_size, fp);
if (CopyGetEof(fp))
elog(ERROR, "COPY BINARY: unexpected EOF");
- if (fld_size == 0)
- continue; /* it's NULL; nulls[i] already set */
- if (fld_size != attr[i]->attlen)
- elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
- i + 1, (int) fld_size, (int) attr[i]->attlen);
- if (fld_size == -1)
- {
- /* varlena field */
- int32 varlena_size;
- Pointer varlena_ptr;
-
- CopyGetData(&varlena_size, sizeof(int32), fp);
- if (CopyGetEof(fp))
- elog(ERROR, "COPY BINARY: unexpected EOF");
- if (varlena_size < (int32) sizeof(int32))
- elog(ERROR, "COPY BINARY: bogus varlena length");
- varlena_ptr = (Pointer) palloc(varlena_size);
- VARATT_SIZEP(varlena_ptr) = varlena_size;
- CopyGetData(VARDATA(varlena_ptr),
- varlena_size - sizeof(int32),
- fp);
- if (CopyGetEof(fp))
- elog(ERROR, "COPY BINARY: unexpected EOF");
- values[i] = PointerGetDatum(varlena_ptr);
- }
- else if (!attr[i]->attbyval)
- {
- /* fixed-length pass-by-reference */
- Pointer refval_ptr;
-
- Assert(fld_size > 0);
- refval_ptr = (Pointer) palloc(fld_size);
- CopyGetData(refval_ptr, fld_size, fp);
- if (CopyGetEof(fp))
- elog(ERROR, "COPY BINARY: unexpected EOF");
- values[i] = PointerGetDatum(refval_ptr);
- }
- else
- {
- /* pass-by-value */
- Datum datumBuf;
-
- /*
- * We need this horsing around because we don't
- * know how shorter data values are aligned within
- * a Datum.
- */
- Assert(fld_size > 0 && fld_size <= sizeof(Datum));
- CopyGetData(&datumBuf, fld_size, fp);
- if (CopyGetEof(fp))
- elog(ERROR, "COPY BINARY: unexpected EOF");
- values[i] = fetch_att(&datumBuf, true, fld_size);
- }
+ values[attnum-1] = PointerGetDatum(refval_ptr);
+ }
+ else
+ {
+ /* pass-by-value */
+ Datum datumBuf;
- nulls[i] = ' ';
+ /*
+ * We need this horsing around because we don't
+ * know how shorter data values are aligned within
+ * a Datum.
+ */
+ Assert(fld_size > 0 && fld_size <= sizeof(Datum));
+ CopyGetData(&datumBuf, fld_size, fp);
+ if (CopyGetEof(fp))
+ elog(ERROR, "COPY BINARY: unexpected EOF");
+ values[attnum-1] = fetch_att(&datumBuf, true, fld_size);
}
+
+ nulls[attnum-1] = ' ';
}
}
- if (done)
- break;
+ /*
+ * Now compute and insert any defaults available for the
+ * columns not provided by the input data. Anything not
+ * processed here or above will remain NULL.
+ */
+ for (i = 0; i < num_defaults; i++)
+ {
+ bool isnull;
+ values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
+ &isnull, NULL);
+ if (!isnull)
+ nulls[defmap[i]] = ' ';
+ }
+
+ /*
+ * And now we can form the input tuple.
+ */
tuple = heap_formtuple(tupDesc, values, nulls);
if (oids && file_has_oids)
HeapTupleSetOid(tuple, loaded_oid);
+ /*
+ * Triggers and stuff need to be invoked in query context.
+ */
+ MemoryContextSwitchTo(oldcontext);
+
skip_tuple = false;
/* BEFORE ROW INSERT Triggers */
@@ -1118,6 +1123,7 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
if (!skip_tuple)
{
+ /* Place tuple in tuple slot */
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
/*
@@ -1138,8 +1144,6 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
if (resultRelInfo->ri_TrigDesc)
ExecARInsertTriggers(estate, resultRelInfo, tuple);
}
-
- heap_freetuple(tuple);
}
/*
@@ -1147,6 +1151,8 @@ CopyFrom(Relation rel, List *attlist, bool binary, bool oids,
*/
copy_lineno = 0;
+ MemoryContextSwitchTo(oldcontext);
+
pfree(values);
pfree(nulls);
@@ -1197,12 +1203,11 @@ GetTypeElement(Oid type)
/*
* Read the value of a single attribute.
*
- * Results are returned in the status indicator, as well as the
- * return value. If a value was successfully read but there is
- * more to read before EOL, NORMAL_ATTR is set and the value read
- * is returned. If a value was read and we hit EOL, END_OF_LINE
- * is set and the value read is returned. If we hit the EOF,
- * END_OF_FILE is set and NULL is returned.
+ * *result is set to indicate what terminated the read:
+ * NORMAL_ATTR: column delimiter
+ * END_OF_LINE: newline
+ * END_OF_FILE: EOF indication
+ * In all cases, the string read up to the terminator is returned.
*
* Note: This function does not care about SQL NULL values -- it
* is the caller's responsibility to check if the returned string
@@ -1215,8 +1220,7 @@ static char *
CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
{
int c;
- int delimc = (unsigned char)delim[0];
-
+ int delimc = (unsigned char) delim[0];
#ifdef MULTIBYTE
int mblen;
unsigned char s[2];
@@ -1230,7 +1234,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
attribute_buf.len = 0;
attribute_buf.data[0] = '\0';
- /* set default */
+ /* set default status */
*result = NORMAL_ATTR;
for (;;)
@@ -1239,7 +1243,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
if (c == EOF)
{
*result = END_OF_FILE;
- return NULL;
+ goto copy_eof;
}
if (c == '\n')
{
@@ -1254,7 +1258,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
if (c == EOF)
{
*result = END_OF_FILE;
- return NULL;
+ goto copy_eof;
}
switch (c)
{
@@ -1286,7 +1290,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
if (c == EOF)
{
*result = END_OF_FILE;
- return NULL;
+ goto copy_eof;
}
CopyDonePeek(fp, c, false /* put back */ );
}
@@ -1296,7 +1300,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
if (c == EOF)
{
*result = END_OF_FILE;
- return NULL;
+ goto copy_eof;
}
CopyDonePeek(fp, c, false /* put back */ );
}
@@ -1336,7 +1340,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
if (c != '\n')
elog(ERROR, "CopyReadAttribute: end of record marker corrupted");
*result = END_OF_FILE;
- return NULL;
+ goto copy_eof;
}
}
appendStringInfoCharMacro(&attribute_buf, c);
@@ -1353,7 +1357,7 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
if (c == EOF)
{
*result = END_OF_FILE;
- return NULL;
+ goto copy_eof;
}
appendStringInfoCharMacro(&attribute_buf, c);
}
@@ -1361,6 +1365,8 @@ CopyReadAttribute(FILE *fp, const char *delim, CopyReadResult *result)
#endif
}
+copy_eof:
+
#ifdef MULTIBYTE
if (client_encoding != server_encoding)
{
@@ -1468,50 +1474,51 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim)
}
/*
- * CopyCheckAttlist: elog(ERROR,...) if the specified attlist
- * is not valid for the Relation
+ * CopyGetAttnums - build an integer list of attnums to be copied
+ *
+ * The input attnamelist is either the user-specified column list,
+ * or NIL if there was none (in which case we want all the non-dropped
+ * columns).
*/
-static void
-CopyCheckAttlist(Relation rel, List *attlist)
+static List *
+CopyGetAttnums(Relation rel, List *attnamelist)
{
- TupleDesc tupDesc;
- int attr_count;
- List *l;
-
- if (attlist == NIL)
- return;
-
- tupDesc = RelationGetDescr(rel);
- Assert(tupDesc != NULL);
-
- /*
- * make sure there aren't more columns specified than are in the table
- */
- attr_count = tupDesc->natts;
- if (attr_count < length(attlist))
- elog(ERROR, "COPY: Too many columns specified");
+ List *attnums = NIL;
- /*
- * make sure no columns are specified that don't exist in the table
- */
- foreach(l, attlist)
+ if (attnamelist == NIL)
{
- char *colName = strVal(lfirst(l));
- bool found = false;
- int i;
+ /* Generate default column list */
+ TupleDesc tupDesc = RelationGetDescr(rel);
+ Form_pg_attribute *attr = tupDesc->attrs;
+ int attr_count = tupDesc->natts;
+ int i;
for (i = 0; i < attr_count; i++)
{
- if (namestrcmp(&tupDesc->attrs[i]->attname, colName) == 0)
- {
- found = true;
- break;
- }
+ if (attr[i]->attisdropped)
+ continue;
+ attnums = lappendi(attnums, i + 1);
+ }
+ }
+ else
+ {
+ /* Validate the user-supplied list and extract attnums */
+ List *l;
+
+ foreach(l, attnamelist)
+ {
+ char *name = strVal(lfirst(l));
+ int attnum;
+
+ /* Lookup column name, elog on failure */
+ /* Note we disallow system columns here */
+ attnum = attnameAttNum(rel, name, false);
+ /* Check for duplicates */
+ if (intMember(attnum, attnums))
+ elog(ERROR, "Attribute \"%s\" specified more than once", name);
+ attnums = lappendi(attnums, attnum);
}
-
- if (!found)
- elog(ERROR, "COPY: Specified column \"%s\" does not exist",
- colName);
}
-}
+ return attnums;
+}
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 4049e7435c5..9edebc1e690 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.79 2002/07/29 23:46:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.80 2002/08/02 18:15:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -294,10 +294,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
HeapTuple tuple;
Form_pg_attribute att;
- tuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(relId),
- PointerGetDatum(arg),
- 0, 0);
+ tuple = SearchSysCacheAttName(relId, arg);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "DefineIndex: attribute \"%s\" not found", arg);
att = (Form_pg_attribute) GETSTRUCT(tuple);
@@ -387,10 +384,7 @@ NormIndexAttrs(IndexInfo *indexInfo,
if (attribute->name == NULL)
elog(ERROR, "missing attribute for define index");
- atttuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(relId),
- PointerGetDatum(attribute->name),
- 0, 0);
+ atttuple = SearchSysCacheAttName(relId, attribute->name);
if (!HeapTupleIsValid(atttuple))
elog(ERROR, "DefineIndex: attribute \"%s\" not found",
attribute->name);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index cfcf5d5ddfd..4972c09b4a4 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.25 2002/07/31 17:19:51 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.26 2002/08/02 18:15:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -503,7 +503,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
/*
* newattno[] will contain the child-table attribute numbers for
* the attributes of this parent table. (They are not the same
- * for parents after the first one.)
+ * for parents after the first one, nor if we have dropped columns.)
*/
newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
@@ -517,6 +517,19 @@ MergeAttributes(List *schema, List *supers, bool istemp,
TypeName *typename;
/*
+ * Ignore dropped columns in the parent.
+ */
+ if (attribute->attisdropped)
+ {
+ /*
+ * change_varattnos_of_a_node asserts that this is greater than
+ * zero, so if anything tries to use it, we should find out.
+ */
+ newattno[parent_attno - 1] = 0;
+ continue;
+ }
+
+ /*
* Does it conflict with some previously inherited column?
*/
exist_attno = findAttrByName(attributeName, inhSchema);
@@ -1062,17 +1075,17 @@ renameatt(Oid relid,
attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
- atttup = SearchSysCacheCopy(ATTNAME,
- ObjectIdGetDatum(relid),
- PointerGetDatum(oldattname),
- 0, 0);
+ atttup = SearchSysCacheCopyAttName(relid, oldattname);
if (!HeapTupleIsValid(atttup))
- elog(ERROR, "renameatt: attribute \"%s\" does not exist", oldattname);
+ elog(ERROR, "renameatt: attribute \"%s\" does not exist",
+ oldattname);
if (((Form_pg_attribute) GETSTRUCT(atttup))->attnum < 0)
- elog(ERROR, "renameatt: system attribute \"%s\" not renamed", oldattname);
+ elog(ERROR, "renameatt: system attribute \"%s\" may not be renamed",
+ oldattname);
/* should not already exist */
+ /* this test is deliberately not attisdropped-aware */
if (SearchSysCacheExists(ATTNAME,
ObjectIdGetDatum(relid),
PointerGetDatum(newattname),
@@ -1126,10 +1139,7 @@ renameatt(Oid relid,
* Okay, look to see if any column name of the index matches the
* old attribute name.
*/
- atttup = SearchSysCacheCopy(ATTNAME,
- ObjectIdGetDatum(indexoid),
- PointerGetDatum(oldattname),
- 0, 0);
+ atttup = SearchSysCacheCopyAttName(indexoid, oldattname);
if (!HeapTupleIsValid(atttup))
continue; /* Nope, so ignore it */
@@ -1634,6 +1644,10 @@ AlterTableAddColumn(Oid myrelid,
elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
RelationGetRelationName(rel));
+ /*
+ * this test is deliberately not attisdropped-aware, since if one tries
+ * to add a column matching a dropped column name, it's gonna fail anyway.
+ */
if (SearchSysCacheExists(ATTNAME,
ObjectIdGetDatum(myrelid),
PointerGetDatum(colDef->colname),
@@ -1681,6 +1695,7 @@ AlterTableAddColumn(Oid myrelid,
attribute->attnotnull = colDef->is_not_null;
attribute->atthasdef = (colDef->raw_default != NULL ||
colDef->cooked_default != NULL);
+ attribute->attisdropped = false;
ReleaseSysCache(typeTuple);
@@ -1821,17 +1836,11 @@ AlterTableAlterColumnDropNotNull(Oid myrelid,
/*
* get the number of the attribute
*/
- tuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(myrelid),
- PointerGetDatum(colName),
- 0, 0);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
+ attnum = get_attnum(myrelid, colName);
+ if (attnum == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
- attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
- ReleaseSysCache(tuple);
-
/* Prevent them from altering a system attribute */
if (attnum < 0)
elog(ERROR, "ALTER TABLE: Cannot alter system attribute \"%s\"",
@@ -1884,10 +1893,7 @@ AlterTableAlterColumnDropNotNull(Oid myrelid,
*/
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
- tuple = SearchSysCacheCopy(ATTNAME,
- ObjectIdGetDatum(myrelid),
- PointerGetDatum(colName),
- 0, 0);
+ tuple = SearchSysCacheCopyAttName(myrelid, colName);
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
@@ -1971,17 +1977,11 @@ AlterTableAlterColumnSetNotNull(Oid myrelid,
/*
* get the number of the attribute
*/
- tuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(myrelid),
- PointerGetDatum(colName),
- 0, 0);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
+ attnum = get_attnum(myrelid, colName);
+ if (attnum == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
- attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
- ReleaseSysCache(tuple);
-
/* Prevent them from altering a system attribute */
if (attnum < 0)
elog(ERROR, "ALTER TABLE: Cannot alter system attribute \"%s\"",
@@ -2014,10 +2014,7 @@ AlterTableAlterColumnSetNotNull(Oid myrelid,
*/
attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
- tuple = SearchSysCacheCopy(ATTNAME,
- ObjectIdGetDatum(myrelid),
- PointerGetDatum(colName),
- 0, 0);
+ tuple = SearchSysCacheCopyAttName(myrelid, colName);
if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
@@ -2051,7 +2048,6 @@ AlterTableAlterColumnDefault(Oid myrelid,
Node *newDefault)
{
Relation rel;
- HeapTuple tuple;
AttrNumber attnum;
rel = heap_open(myrelid, AccessExclusiveLock);
@@ -2106,16 +2102,15 @@ AlterTableAlterColumnDefault(Oid myrelid,
/*
* get the number of the attribute
*/
- tuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(myrelid),
- PointerGetDatum(colName),
- 0, 0);
- if (!HeapTupleIsValid(tuple))
- elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
+ attnum = get_attnum(myrelid, colName);
+ if (attnum == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
- attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
- ReleaseSysCache(tuple);
+ /* Prevent them from altering a system attribute */
+ if (attnum < 0)
+ elog(ERROR, "ALTER TABLE: Cannot alter system attribute \"%s\"",
+ colName);
/*
* Remove any old default for the column. We use RESTRICT here for
@@ -2254,10 +2249,7 @@ AlterTableAlterColumnFlags(Oid myrelid,
attrelation = heap_openr(AttributeRelationName, RowExclusiveLock);
- tuple = SearchSysCacheCopy(ATTNAME,
- ObjectIdGetDatum(myrelid),
- PointerGetDatum(colName),
- 0, 0);
+ tuple = SearchSysCacheCopyAttName(myrelid, colName);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
RelationGetRelationName(rel), colName);
@@ -2309,7 +2301,99 @@ AlterTableDropColumn(Oid myrelid,
bool inh, const char *colName,
DropBehavior behavior)
{
- elog(ERROR, "ALTER TABLE / DROP COLUMN is not implemented");
+ Relation rel;
+ AttrNumber attnum;
+ AttrNumber n;
+ TupleDesc tupleDesc;
+ bool success;
+ ObjectAddress object;
+
+ rel = heap_open(myrelid, AccessExclusiveLock);
+
+ if (rel->rd_rel->relkind != RELKIND_RELATION)
+ elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
+ RelationGetRelationName(rel));
+
+ if (!allowSystemTableMods
+ && IsSystemRelation(rel))
+ elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
+ RelationGetRelationName(rel));
+
+ if (!pg_class_ownercheck(myrelid, GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, RelationGetRelationName(rel));
+
+ /*
+ * get the number of the attribute
+ */
+ attnum = get_attnum(myrelid, colName);
+ if (attnum == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ RelationGetRelationName(rel), colName);
+
+ /* Can't drop a system attribute */
+ if (attnum < 0)
+ elog(ERROR, "ALTER TABLE: Cannot drop system attribute \"%s\"",
+ colName);
+
+ /*
+ * Make sure there will be at least one user column left in the relation
+ * after we drop this one. Zero-length tuples tend to confuse us.
+ */
+ tupleDesc = RelationGetDescr(rel);
+
+ success = false;
+ for (n = 1; n <= tupleDesc->natts; n++)
+ {
+ Form_pg_attribute attribute = tupleDesc->attrs[n - 1];
+
+ if (!attribute->attisdropped && n != attnum)
+ {
+ success = true;
+ break;
+ }
+ }
+
+ if (!success)
+ elog(ERROR, "ALTER TABLE: Cannot drop last column from table \"%s\"",
+ RelationGetRelationName(rel));
+
+ /*
+ * Propagate to children if desired
+ */
+ if (inh)
+ {
+ List *child,
+ *children;
+
+ /* this routine is actually in the planner */
+ children = find_all_inheritors(myrelid);
+
+ /*
+ * find_all_inheritors does the recursive search of the
+ * inheritance hierarchy, so all we have to do is process all of
+ * the relids in the list that it returns.
+ */
+ foreach(child, children)
+ {
+ Oid childrelid = lfirsti(child);
+
+ if (childrelid == myrelid)
+ continue;
+ AlterTableDropColumn(childrelid,
+ false, colName, behavior);
+ }
+ }
+
+ /*
+ * Perform the actual deletion
+ */
+ object.classId = RelOid_pg_class;
+ object.objectId = myrelid;
+ object.objectSubId = attnum;
+
+ performDeletion(&object, behavior);
+
+ heap_close(rel, NoLock); /* close rel, but keep lock! */
}
@@ -2722,8 +2806,13 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
foreach(l, fkconstraint->fk_attrs)
{
Ident *id = (Ident *) lfirst(l);
+ AttrNumber attno;
- fkattr[i++] = get_attnum(RelationGetRelid(rel), id->name);
+ attno = get_attnum(RelationGetRelid(rel), id->name);
+ if (attno == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ RelationGetRelationName(rel), id->name);
+ fkattr[i++] = attno;
}
/* The same for the referenced primary key attrs */
@@ -2733,8 +2822,13 @@ createForeignKeyConstraint(Relation rel, Relation pkrel,
foreach(l, fkconstraint->pk_attrs)
{
Ident *id = (Ident *) lfirst(l);
+ AttrNumber attno;
- pkattr[i++] = get_attnum(RelationGetRelid(pkrel), id->name);
+ attno = get_attnum(RelationGetRelid(pkrel), id->name);
+ if (attno == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ RelationGetRelationName(pkrel), id->name);
+ pkattr[i++] = attno;
}
/* Now we can make the pg_constraint entry */
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 1cc9f5af489..b7c0bac12c8 100644
--- a/src/backend/optimizer/prep/preptlist.c
+++ b/src/backend/optimizer/prep/preptlist.c
@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.53 2002/06/20 20:29:31 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.54 2002/08/02 18:15:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -165,6 +165,8 @@ expand_targetlist(List *tlist, int command_type,
*
* For UPDATE, generate a Var reference to the existing value of
* the attribute, so that it gets copied to the new tuple.
+ * But generate a NULL for dropped columns (we want to drop any
+ * old values).
*/
Oid atttype = att_tup->atttypid;
int32 atttypmod = att_tup->atttypmod;
@@ -182,11 +184,21 @@ expand_targetlist(List *tlist, int command_type,
false);
break;
case CMD_UPDATE:
- new_expr = (Node *) makeVar(result_relation,
- attrno,
- atttype,
- atttypmod,
- 0);
+ /* Insert NULLs for dropped columns */
+ if (att_tup->attisdropped)
+ new_expr = (Node *) makeConst(atttype,
+ att_tup->attlen,
+ (Datum) 0,
+ true, /* isnull */
+ att_tup->attbyval,
+ false, /* not a set */
+ false);
+ else
+ new_expr = (Node *) makeVar(result_relation,
+ attrno,
+ atttype,
+ atttypmod,
+ 0);
break;
default:
elog(ERROR, "expand_targetlist: unexpected command_type");
@@ -210,7 +222,8 @@ expand_targetlist(List *tlist, int command_type,
* the end of the new tlist, making sure they have resnos higher than
* the last real attribute. (Note: although the rewriter already did
* such renumbering, we have to do it again here in case we are doing
- * an UPDATE in an inheritance child table with more columns.)
+ * an UPDATE in a table with dropped columns, or an inheritance child
+ * table with extra columns.)
*/
while (tlist)
{
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 367ef4a58a7..f41466dbd5c 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.74 2002/06/20 20:29:31 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.75 2002/08/02 18:15:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -797,9 +797,16 @@ adjust_inherited_attrs_mutator(Node *node,
{
var->varno = context->new_rt_index;
if (var->varattno > 0)
- var->varattno = get_attnum(context->new_relid,
- get_attname(context->old_relid,
- var->varattno));
+ {
+ char *attname = get_attname(context->old_relid,
+ var->varattno);
+
+ var->varattno = get_attnum(context->new_relid, attname);
+ if (var->varattno == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ get_rel_name(context->new_relid), attname);
+ pfree(attname);
+ }
}
return (Node *) var;
}
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 6337b61f2ac..e3d8ce070bc 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.239 2002/07/16 22:12:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.240 2002/08/02 18:15:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1143,6 +1143,8 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
Form_pg_attribute inhattr = rel->rd_att->attrs[count];
char *inhname = NameStr(inhattr->attname);
+ if (inhattr->attisdropped)
+ continue;
if (strcmp(key->name, inhname) == 0)
{
found = true;
@@ -1178,10 +1180,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
/* ALTER TABLE case: does column already exist? */
HeapTuple atttuple;
- atttuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(cxt->relOid),
- PointerGetDatum(key->name),
- 0, 0);
+ atttuple = SearchSysCacheAttName(cxt->relOid, key->name);
if (HeapTupleIsValid(atttuple))
{
found = true;
@@ -2369,7 +2368,7 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
origTarget = (ResTarget *) lfirst(origTargetList);
updateTargetListEntry(pstate, tle, origTarget->name,
attnameAttNum(pstate->p_target_relation,
- origTarget->name),
+ origTarget->name, true),
origTarget->indirection);
origTargetList = lnext(origTargetList);
}
@@ -2820,11 +2819,14 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
inh->relname);
for (count = 0; count < rel->rd_att->natts; count++)
{
- char *name = NameStr(rel->rd_att->attrs[count]->attname);
+ Form_pg_attribute inhattr = rel->rd_att->attrs[count];
+ char *inhname = NameStr(inhattr->attname);
- if (strcmp(name, colname) == 0)
+ if (inhattr->attisdropped)
+ continue;
+ if (strcmp(inhname, colname) == 0)
{
- result = rel->rd_att->attrs[count]->atttypid;
+ result = inhattr->atttypid;
heap_close(rel, NoLock);
return result;
}
@@ -2836,10 +2838,7 @@ transformFkeyGetColType(CreateStmtContext *cxt, char *colname)
{
HeapTuple atttuple;
- atttuple = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(cxt->relOid),
- PointerGetDatum(colname),
- 0, 0);
+ atttuple = SearchSysCacheAttName(cxt->relOid, colname);
if (HeapTupleIsValid(atttuple))
{
result = ((Form_pg_attribute) GETSTRUCT(atttuple))->atttypid;
diff --git a/src/backend/parser/parse_func.c b/src/backend/parser/parse_func.c
index f92bbe8ac5c..677acf9d1a3 100644
--- a/src/backend/parser/parse_func.c
+++ b/src/backend/parser/parse_func.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.132 2002/06/20 20:29:32 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.133 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1150,6 +1150,9 @@ setup_field_select(Node *input, char *attname, Oid relid)
AttrNumber attno;
attno = get_attnum(relid, attname);
+ if (attno == InvalidAttrNumber)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ get_rel_name(relid), attname);
fselect->arg = input;
fselect->fieldnum = attno;
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 78a16ea08f8..99b639d73e3 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.70 2002/06/20 20:29:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.71 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -37,7 +37,9 @@ static Node *scanNameSpaceForRefname(ParseState *pstate, Node *nsnode,
static Node *scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte,
char *colname);
static bool isForUpdate(ParseState *pstate, char *refname);
-static int specialAttNum(char *a);
+static bool get_rte_attribute_is_dropped(RangeTblEntry *rte,
+ AttrNumber attnum);
+static int specialAttNum(const char *attname);
static void warnAutoRange(ParseState *pstate, RangeVar *relation);
@@ -267,12 +269,28 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, char *colname)
/*
* Scan the user column names (or aliases) for a match. Complain if
* multiple matches.
+ *
+ * Note: because eref->colnames may include names of dropped columns,
+ * we need to check for non-droppedness before accepting a match.
+ * This takes an extra cache lookup, but we can skip the lookup most
+ * of the time by exploiting the knowledge that dropped columns are
+ * assigned dummy names starting with '.', which is an unusual choice
+ * for actual column names.
+ *
+ * Should the user try to fool us by altering pg_attribute.attname
+ * for a dropped column, we'll still catch it by virtue of the checks
+ * in get_rte_attribute_type(), which is called by make_var(). That
+ * routine has to do a cache lookup anyway, so the check there is
+ * cheap.
*/
foreach(c, rte->eref->colnames)
{
attnum++;
if (strcmp(strVal(lfirst(c)), colname) == 0)
{
+ if (colname[0] == '.' && /* see note above */
+ get_rte_attribute_is_dropped(rte, attnum))
+ continue;
if (result)
elog(ERROR, "Column reference \"%s\" is ambiguous", colname);
result = (Node *) make_var(pstate, rte, attnum);
@@ -962,6 +980,9 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
{
Form_pg_attribute attr = rel->rd_att->attrs[varattno];
+ if (attr->attisdropped)
+ continue;
+
if (colnames)
{
char *label;
@@ -1051,6 +1072,9 @@ expandRTE(ParseState *pstate, RangeTblEntry *rte,
{
Form_pg_attribute attr = rel->rd_att->attrs[varattno];
+ if (attr->attisdropped)
+ continue;
+
if (colnames)
{
char *label;
@@ -1246,9 +1270,16 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
0, 0);
/* this shouldn't happen... */
if (!HeapTupleIsValid(tp))
- elog(ERROR, "Relation %s does not have attribute %d",
+ elog(ERROR, "Relation \"%s\" does not have attribute %d",
get_rel_name(rte->relid), attnum);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ /*
+ * If dropped column, pretend it ain't there. See notes
+ * in scanRTEForColumn.
+ */
+ if (att_tup->attisdropped)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ get_rel_name(rte->relid), NameStr(att_tup->attname));
*vartype = att_tup->atttypid;
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
@@ -1298,6 +1329,14 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
elog(ERROR, "Relation %s does not have attribute %d",
get_rel_name(funcrelid), attnum);
att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ /*
+ * If dropped column, pretend it ain't there. See notes
+ * in scanRTEForColumn.
+ */
+ if (att_tup->attisdropped)
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ get_rel_name(funcrelid),
+ NameStr(att_tup->attname));
*vartype = att_tup->atttypid;
*vartypmod = att_tup->atttypmod;
ReleaseSysCache(tp);
@@ -1330,6 +1369,86 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
}
/*
+ * get_rte_attribute_is_dropped
+ * Check whether attempted attribute ref is to a dropped column
+ */
+static bool
+get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum)
+{
+ bool result;
+
+ switch (rte->rtekind)
+ {
+ case RTE_RELATION:
+ {
+ /* Plain relation RTE --- get the attribute's type info */
+ HeapTuple tp;
+ Form_pg_attribute att_tup;
+
+ tp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(rte->relid),
+ Int16GetDatum(attnum),
+ 0, 0);
+ /* this shouldn't happen... */
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "Relation \"%s\" does not have attribute %d",
+ get_rel_name(rte->relid), attnum);
+ att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ result = att_tup->attisdropped;
+ ReleaseSysCache(tp);
+ }
+ break;
+ case RTE_SUBQUERY:
+ case RTE_JOIN:
+ /* Subselect and join RTEs never have dropped columns */
+ result = false;
+ break;
+ case RTE_FUNCTION:
+ {
+ /* Function RTE */
+ Oid funcrettype = exprType(rte->funcexpr);
+ Oid funcrelid = typeidTypeRelid(funcrettype);
+
+ if (OidIsValid(funcrelid))
+ {
+ /*
+ * Composite data type, i.e. a table's row type
+ * Same as ordinary relation RTE
+ */
+ HeapTuple tp;
+ Form_pg_attribute att_tup;
+
+ tp = SearchSysCache(ATTNUM,
+ ObjectIdGetDatum(funcrelid),
+ Int16GetDatum(attnum),
+ 0, 0);
+ /* this shouldn't happen... */
+ if (!HeapTupleIsValid(tp))
+ elog(ERROR, "Relation %s does not have attribute %d",
+ get_rel_name(funcrelid), attnum);
+ att_tup = (Form_pg_attribute) GETSTRUCT(tp);
+ result = att_tup->attisdropped;
+ ReleaseSysCache(tp);
+ }
+ else
+ {
+ /*
+ * Must be a base data type, i.e. scalar
+ */
+ result = false;
+ }
+ }
+ break;
+ default:
+ elog(ERROR, "get_rte_attribute_is_dropped: unsupported RTE kind %d",
+ (int) rte->rtekind);
+ result = false; /* keep compiler quiet */
+ }
+
+ return result;
+}
+
+/*
* given relation and att name, return id of variable
*
* This should only be used if the relation is already
@@ -1337,23 +1456,30 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
* for access to non-opened relations.
*/
int
-attnameAttNum(Relation rd, char *a)
+attnameAttNum(Relation rd, const char *attname, bool sysColOK)
{
int i;
for (i = 0; i < rd->rd_rel->relnatts; i++)
- if (namestrcmp(&(rd->rd_att->attrs[i]->attname), a) == 0)
+ {
+ Form_pg_attribute att = rd->rd_att->attrs[i];
+
+ if (namestrcmp(&(att->attname), attname) == 0 && !att->attisdropped)
return i + 1;
+ }
- if ((i = specialAttNum(a)) != InvalidAttrNumber)
+ if (sysColOK)
{
- if (i != ObjectIdAttributeNumber || rd->rd_rel->relhasoids)
- return i;
+ if ((i = specialAttNum(attname)) != InvalidAttrNumber)
+ {
+ if (i != ObjectIdAttributeNumber || rd->rd_rel->relhasoids)
+ return i;
+ }
}
/* on failure */
- elog(ERROR, "Relation '%s' does not have attribute '%s'",
- RelationGetRelationName(rd), a);
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ RelationGetRelationName(rd), attname);
return InvalidAttrNumber; /* lint */
}
@@ -1367,11 +1493,12 @@ attnameAttNum(Relation rd, char *a)
* at least in the case of "oid", which is now optional.
*/
static int
-specialAttNum(char *a)
+specialAttNum(const char *attname)
{
Form_pg_attribute sysatt;
- sysatt = SystemAttributeByName(a, true /* "oid" will be accepted */ );
+ sysatt = SystemAttributeByName(attname,
+ true /* "oid" will be accepted */ );
if (sysatt != NULL)
return sysatt->attnum;
return InvalidAttrNumber;
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 608ca7613dc..1e51f23d704 100644
--- a/src/backend/parser/parse_target.c
+++ b/src/backend/parser/parse_target.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.85 2002/06/20 20:29:33 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.86 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -385,8 +385,12 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
for (i = 0; i < numcol; i++)
{
- ResTarget *col = makeNode(ResTarget);
+ ResTarget *col;
+ if (attr[i]->attisdropped)
+ continue;
+
+ col = makeNode(ResTarget);
col->name = pstrdup(NameStr(attr[i]->attname));
col->indirection = NIL;
col->val = NULL;
@@ -407,7 +411,7 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
int attrno;
/* Lookup column name, elog on failure */
- attrno = attnameAttNum(pstate->p_target_relation, name);
+ attrno = attnameAttNum(pstate->p_target_relation, name, false);
/* Check for duplicates */
if (intMember(attrno, *attrnos))
elog(ERROR, "Attribute '%s' specified more than once", name);
diff --git a/src/backend/parser/parse_type.c b/src/backend/parser/parse_type.c
index 159428894e4..59c534a7ef3 100644
--- a/src/backend/parser/parse_type.c
+++ b/src/backend/parser/parse_type.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.46 2002/07/29 23:46:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_type.c,v 1.47 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -85,8 +85,8 @@ LookupTypeName(const TypeName *typename)
relid = RangeVarGetRelid(rel, false);
attnum = get_attnum(relid, field);
if (attnum == InvalidAttrNumber)
- elog(ERROR, "'%s' is not an attribute of class '%s'",
- field, rel->relname);
+ elog(ERROR, "Relation \"%s\" has no column \"%s\"",
+ rel->relname, field);
restype = get_atttype(relid, attnum);
/* this construct should never have an array indicator */
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 59d0744dcee..577ce2bd52d 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.75 2002/07/16 05:53:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.76 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -257,6 +257,16 @@ DefineQueryRewrite(RuleStmt *stmt)
attr = event_relation->rd_att->attrs[i - 1];
attname = NameStr(attr->attname);
+ /*
+ * Disallow dropped columns in the relation. This won't happen
+ * in the cases we actually care about (namely creating a view
+ * via CREATE TABLE then CREATE RULE). Trying to cope with it
+ * is much more trouble than it's worth, because we'd have to
+ * modify the rule to insert dummy NULLs at the right positions.
+ */
+ if (attr->attisdropped)
+ elog(ERROR, "cannot convert relation containing dropped columns to view");
+
if (strcmp(resdom->resname, attname) != 0)
elog(ERROR, "select rule's target entry %d has different column name from %s", i, attname);
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 0ae1e223baa..95ab639d0a7 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.104 2002/07/18 04:43:50 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.105 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -264,6 +264,10 @@ rewriteTargetList(Query *parsetree, Relation target_relation)
Form_pg_attribute att_tup = target_relation->rd_att->attrs[attrno-1];
TargetEntry *new_tle = NULL;
+ /* We can ignore deleted attributes */
+ if (att_tup->attisdropped)
+ continue;
+
/*
* Look for targetlist entries matching this attr. We match by
* resno, but the resname should match too.
diff --git a/src/backend/utils/adt/not_in.c b/src/backend/utils/adt/not_in.c
index 5982e434da3..7c6be4533eb 100644
--- a/src/backend/utils/adt/not_in.c
+++ b/src/backend/utils/adt/not_in.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.30 2002/06/20 20:29:37 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/not_in.c,v 1.31 2002/08/02 18:15:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,9 +28,9 @@
#include "access/heapam.h"
#include "catalog/namespace.h"
+#include "parser/parse_relation.h"
#include "utils/builtins.h"
-static int my_varattno(Relation rd, char *a);
/* ----------------------------------------------------------------
*
@@ -65,15 +65,10 @@ int4notin(PG_FUNCTION_ARGS)
relrv = makeRangeVarFromNameList(names);
/* Open the relation and get a relation descriptor */
-
relation_to_scan = heap_openrv(relrv, AccessShareLock);
/* Find the column to search */
-
- attrid = my_varattno(relation_to_scan, attribute);
- if (attrid < 0)
- elog(ERROR, "int4notin: unknown attribute %s for relation %s",
- attribute, RelationGetRelationName(relation_to_scan));
+ attrid = attnameAttNum(relation_to_scan, attribute, true);
scan_descriptor = heap_beginscan(relation_to_scan, SnapshotNow,
0, (ScanKey) NULL);
@@ -118,21 +113,3 @@ oidnotin(PG_FUNCTION_ARGS)
/* XXX assume oid maps to int4 */
return int4notin(fcinfo);
}
-
-/*
- * XXX
- * If varattno (in parser/catalog_utils.h) ever is added to
- * cinterface.a, this routine should go away
- */
-static int
-my_varattno(Relation rd, char *a)
-{
- int i;
-
- for (i = 0; i < rd->rd_rel->relnatts; i++)
- {
- if (namestrcmp(&rd->rd_att->attrs[i]->attname, a) == 0)
- return i + 1;
- }
- return -1;
-}
diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c
index e383ab892d1..9b5b4cd6f13 100644
--- a/src/backend/utils/cache/lsyscache.c
+++ b/src/backend/utils/cache/lsyscache.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.76 2002/07/12 18:43:18 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.77 2002/08/02 18:15:08 tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
@@ -115,16 +115,15 @@ get_attname(Oid relid, AttrNumber attnum)
*
* Given the relation id and the attribute name,
* return the "attnum" field from the attribute relation.
+ *
+ * Returns InvalidAttrNumber if the attr doesn't exist (or is dropped).
*/
AttrNumber
-get_attnum(Oid relid, char *attname)
+get_attnum(Oid relid, const char *attname)
{
HeapTuple tp;
- tp = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(relid),
- PointerGetDatum(attname),
- 0, 0);
+ tp = SearchSysCacheAttName(relid, attname);
if (HeapTupleIsValid(tp))
{
Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
@@ -166,32 +165,6 @@ get_atttype(Oid relid, AttrNumber attnum)
return InvalidOid;
}
-/* This routine uses the attname instead of the attnum because it
- * replaces the routine find_atttype, which is called sometimes when
- * only the attname, not the attno, is available.
- */
-bool
-get_attisset(Oid relid, char *attname)
-{
- HeapTuple tp;
-
- tp = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(relid),
- PointerGetDatum(attname),
- 0, 0);
- if (HeapTupleIsValid(tp))
- {
- Form_pg_attribute att_tup = (Form_pg_attribute) GETSTRUCT(tp);
- bool result;
-
- result = att_tup->attisset;
- ReleaseSysCache(tp);
- return result;
- }
- else
- return false;
-}
-
/*
* get_atttypmod
*
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 0e114f36968..c9b68b1d8d4 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.84 2002/07/25 10:07:12 ishii Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.85 2002/08/02 18:15:08 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@@ -622,6 +622,71 @@ GetSysCacheOid(int cacheId,
return result;
}
+
+/*
+ * SearchSysCacheAttName
+ *
+ * This routine is equivalent to SearchSysCache on the ATTNAME cache,
+ * except that it will return NULL if the found attribute is marked
+ * attisdropped. This is convenient for callers that want to act as
+ * though dropped attributes don't exist.
+ */
+HeapTuple
+SearchSysCacheAttName(Oid relid, const char *attname)
+{
+ HeapTuple tuple;
+
+ tuple = SearchSysCache(ATTNAME,
+ ObjectIdGetDatum(relid),
+ CStringGetDatum(attname),
+ 0, 0);
+ if (!HeapTupleIsValid(tuple))
+ return NULL;
+ if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
+ {
+ ReleaseSysCache(tuple);
+ return NULL;
+ }
+ return tuple;
+}
+
+/*
+ * SearchSysCacheCopyAttName
+ *
+ * As above, an attisdropped-aware version of SearchSysCacheCopy.
+ */
+HeapTuple
+SearchSysCacheCopyAttName(Oid relid, const char *attname)
+{
+ HeapTuple tuple,
+ newtuple;
+
+ tuple = SearchSysCacheAttName(relid, attname);
+ if (!HeapTupleIsValid(tuple))
+ return tuple;
+ newtuple = heap_copytuple(tuple);
+ ReleaseSysCache(tuple);
+ return newtuple;
+}
+
+/*
+ * SearchSysCacheExistsAttName
+ *
+ * As above, an attisdropped-aware version of SearchSysCacheExists.
+ */
+bool
+SearchSysCacheExistsAttName(Oid relid, const char *attname)
+{
+ HeapTuple tuple;
+
+ tuple = SearchSysCacheAttName(relid, attname);
+ if (!HeapTupleIsValid(tuple))
+ return false;
+ ReleaseSysCache(tuple);
+ return true;
+}
+
+
/*
* SysCacheGetAttr
*
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 7ca027e0105..0a44b4cbbcf 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.278 2002/07/31 17:19:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.279 2002/08/02 18:15:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -863,13 +863,15 @@ dumpClasses_nodumpData(Archive *fout, char *oid, void *dctxv)
{
appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;",
fmtQualifiedId(tbinfo->relnamespace->nspname,
- classname),column_list);
+ classname),
+ column_list);
}
else
{
appendPQExpBuffer(q, "COPY %s %s TO stdout;",
fmtQualifiedId(tbinfo->relnamespace->nspname,
- classname), column_list);
+ classname),
+ column_list);
}
res = PQexec(g_conn, q->data);
if (!res ||
@@ -1193,10 +1195,13 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
if (!dumpData)
{
/* Dump/restore using COPY */
+ const char *column_list;
+
dumpFn = dumpClasses_nodumpData;
+ column_list = fmtCopyColumnList(&(tblinfo[i]));
sprintf(copyBuf, "COPY %s %s %sFROM stdin;\n",
- fmtQualifiedId(tblinfo[i].relnamespace->nspname,tblinfo[i].relname),
- fmtCopyColumnList(&(tblinfo[i])),
+ fmtId(tblinfo[i].relname, force_quotes),
+ column_list,
(oids && tblinfo[i].hasoids) ? "WITH OIDS " : "");
copyStmt = copyBuf;
}
@@ -2347,6 +2352,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
int i_attstattarget;
int i_attnotnull;
int i_atthasdef;
+ int i_attisdropped;
PGresult *res;
int ntups;
bool hasdefaults;
@@ -2386,7 +2392,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
if (g_fout->remoteVersion >= 70300)
{
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, attstattarget, "
- "attnotnull, atthasdef, "
+ "attnotnull, atthasdef, attisdropped, "
"pg_catalog.format_type(atttypid,atttypmod) as atttypname "
"from pg_catalog.pg_attribute a "
"where attrelid = '%s'::pg_catalog.oid "
@@ -2402,7 +2408,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
* explicitly set or was just a default.
*/
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, "
- "attnotnull, atthasdef, "
+ "attnotnull, atthasdef, false as attisdropped, "
"format_type(atttypid,atttypmod) as atttypname "
"from pg_attribute a "
"where attrelid = '%s'::oid "
@@ -2414,7 +2420,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
{
/* format_type not available before 7.1 */
appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, "
- "attnotnull, atthasdef, "
+ "attnotnull, atthasdef, false as attisdropped, "
"(select typname from pg_type where oid = atttypid) as atttypname "
"from pg_attribute a "
"where attrelid = '%s'::oid "
@@ -2439,12 +2445,14 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
i_attstattarget = PQfnumber(res, "attstattarget");
i_attnotnull = PQfnumber(res, "attnotnull");
i_atthasdef = PQfnumber(res, "atthasdef");
+ i_attisdropped = PQfnumber(res, "attisdropped");
tblinfo[i].numatts = ntups;
tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *));
tblinfo[i].atttypnames = (char **) malloc(ntups * sizeof(char *));
tblinfo[i].atttypmod = (int *) malloc(ntups * sizeof(int));
tblinfo[i].attstattarget = (int *) malloc(ntups * sizeof(int));
+ tblinfo[i].attisdropped = (bool *) malloc(ntups * sizeof(bool));
tblinfo[i].notnull = (bool *) malloc(ntups * sizeof(bool));
tblinfo[i].adef_expr = (char **) malloc(ntups * sizeof(char *));
tblinfo[i].inhAttrs = (bool *) malloc(ntups * sizeof(bool));
@@ -2458,6 +2466,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
tblinfo[i].atttypnames[j] = strdup(PQgetvalue(res, j, i_atttypname));
tblinfo[i].atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
tblinfo[i].attstattarget[j] = atoi(PQgetvalue(res, j, i_attstattarget));
+ tblinfo[i].attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
tblinfo[i].notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
tblinfo[i].adef_expr[j] = NULL; /* fix below */
if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
@@ -4999,8 +5008,8 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
actual_atts = 0;
for (j = 0; j < tbinfo->numatts; j++)
{
- /* Is this one of the table's own attrs ? */
- if (!tbinfo->inhAttrs[j])
+ /* Is this one of the table's own attrs, and not dropped ? */
+ if (!tbinfo->inhAttrs[j] && !tbinfo->attisdropped[j])
{
/* Format properly if not first attr */
if (actual_atts > 0)
@@ -5161,7 +5170,8 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo)
*/
for (j = 0; j < tbinfo->numatts; j++)
{
- if (tbinfo->attstattarget[j] >= 0)
+ if (tbinfo->attstattarget[j] >= 0 &&
+ !tbinfo->attisdropped[j])
{
appendPQExpBuffer(q, "ALTER TABLE %s ",
fmtId(tbinfo->relname, force_quotes));
@@ -6274,7 +6284,7 @@ fmtQualifiedId(const char *schema, const char *id)
}
/*
- * return a column list clause for the qualified relname.
+ * return a column list clause for the given relation.
* returns an empty string if the remote server is older than
* 7.3.
*/
@@ -6284,9 +6294,11 @@ fmtCopyColumnList(const TableInfo* ti)
static PQExpBuffer q = NULL;
int numatts = ti->numatts;
char** attnames = ti->attnames;
+ bool* attisdropped = ti->attisdropped;
+ bool needComma;
int i;
- if (g_fout->remoteVersion < 70300 )
+ if (g_fout->remoteVersion < 70300)
return "";
if (q) /* first time through? */
@@ -6295,15 +6307,18 @@ fmtCopyColumnList(const TableInfo* ti)
q = createPQExpBuffer();
resetPQExpBuffer(q);
-
- appendPQExpBuffer(q,"(");
+
+ appendPQExpBuffer(q, "(");
+ needComma = false;
for (i = 0; i < numatts; i++)
{
- if( i > 0 )
- appendPQExpBuffer(q,",");
- appendPQExpBuffer(q, fmtId(attnames[i], force_quotes));
+ if (attisdropped[i])
+ continue;
+ if (needComma)
+ appendPQExpBuffer(q, ",");
+ appendPQExpBuffer(q, "%s", fmtId(attnames[i], force_quotes));
+ needComma = true;
}
appendPQExpBuffer(q, ")");
return q->data;
}
-
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 6a6322c9ca2..9a208f1e147 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_dump.h,v 1.93 2002/07/31 17:19:53 tgl Exp $
+ * $Id: pg_dump.h,v 1.94 2002/08/02 18:15:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -128,6 +128,7 @@ typedef struct _tableInfo
* all interesting tables so that we can tell which constraints were
* inherited.
*/
+ bool *attisdropped; /* true if attr is dropped; don't dump it */
bool *notnull; /* Not null constraints on attributes */
char **adef_expr; /* DEFAULT expressions */
bool *inhAttrs; /* true if each attribute is inherited */
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index d60483870a9..bff6c5b73d0 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.56 2002/07/20 05:57:31 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.57 2002/08/02 18:15:08 tgl Exp $
*/
#include "postgres_fe.h"
#include "describe.h"
@@ -536,7 +536,7 @@ describeTableDetails(const char *name, bool desc)
appendPQExpBuffer(&buf, "\nFROM pg_class c, pg_attribute a");
if (tableinfo.relkind == 'i')
appendPQExpBuffer(&buf, ", pg_index i");
- appendPQExpBuffer(&buf, "\nWHERE c.relname = '%s'\n AND a.attnum > 0 AND a.attrelid = c.oid", name);
+ appendPQExpBuffer(&buf, "\nWHERE c.relname = '%s'\n AND a.attnum > 0 AND NOT a.attisdropped AND a.attrelid = c.oid", name);
if (tableinfo.relkind == 'i')
appendPQExpBuffer(&buf, " AND a.attrelid = i.indexrelid");
appendPQExpBuffer(&buf, "\nORDER BY a.attnum");
diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c
index f60ccae324a..3eef1d55eee 100644
--- a/src/bin/psql/tab-complete.c
+++ b/src/bin/psql/tab-complete.c
@@ -3,7 +3,7 @@
*
* Copyright 2000 by PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.53 2002/07/31 17:19:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.54 2002/08/02 18:15:09 tgl Exp $
*/
/*----------------------------------------------------------------------
@@ -156,7 +156,7 @@ pgsql_thing_t words_after_create[] = {
#define Query_for_list_of_tables words_after_create[9].query
#define Query_for_list_of_indexes words_after_create[4].query
#define Query_for_list_of_databases words_after_create[1].query
-#define Query_for_list_of_attributes "SELECT a.attname FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c WHERE c.oid = a.attrelid and a.attnum>0 and substr(a.attname,1,%d)='%s' and c.relname='%s'"
+#define Query_for_list_of_attributes "SELECT a.attname FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c WHERE c.oid = a.attrelid and a.attnum>0 and not a.attisdropped and substr(a.attname,1,%d)='%s' and c.relname='%s'"
#define Query_for_list_of_users words_after_create[14].query
/* A couple of macros to ease typing. You can use these to complete the given
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 9dcd646e6f3..f3e36226b01 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.143 2002/07/25 10:07:12 ishii Exp $
+ * $Id: catversion.h,v 1.144 2002/08/02 18:15:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200207251
+#define CATALOG_VERSION_NO 200208011
#endif
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 3148fd32633..f45c61515ad 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: heap.h,v 1.54 2002/07/15 16:33:31 tgl Exp $
+ * $Id: heap.h,v 1.55 2002/08/02 18:15:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -63,6 +63,7 @@ extern int RemoveRelConstraints(Relation rel, const char *constrName,
extern void DeleteRelationTuple(Oid relid);
extern void DeleteAttributeTuples(Oid relid);
+extern void RemoveAttributeById(Oid relid, AttrNumber attnum);
extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
DropBehavior behavior, bool complain);
extern void RemoveAttrDefaultById(Oid attrdefId);
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 15945192a00..a888fcf523c 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_attribute.h,v 1.95 2002/07/31 17:19:54 tgl Exp $
+ * $Id: pg_attribute.h,v 1.96 2002/08/02 18:15:09 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -143,6 +143,9 @@ CATALOG(pg_attribute) BOOTSTRAP BKI_WITHOUT_OIDS
/* Has DEFAULT value or not */
bool atthasdef;
+
+ /* Is dropped (ie, logically invisible) or not */
+ bool attisdropped;
} FormData_pg_attribute;
/*
@@ -151,7 +154,7 @@ CATALOG(pg_attribute) BOOTSTRAP BKI_WITHOUT_OIDS
* because of alignment padding at the end of the struct.)
*/
#define ATTRIBUTE_TUPLE_SIZE \
- (offsetof(FormData_pg_attribute,atthasdef) + sizeof(bool))
+ (offsetof(FormData_pg_attribute,attisdropped) + sizeof(bool))
/* ----------------
* Form_pg_attribute corresponds to a pointer to a tuple with
@@ -165,7 +168,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
* ----------------
*/
-#define Natts_pg_attribute 15
+#define Natts_pg_attribute 16
#define Anum_pg_attribute_attrelid 1
#define Anum_pg_attribute_attname 2
#define Anum_pg_attribute_atttypid 3
@@ -181,6 +184,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
#define Anum_pg_attribute_attalign 13
#define Anum_pg_attribute_attnotnull 14
#define Anum_pg_attribute_atthasdef 15
+#define Anum_pg_attribute_attisdropped 16
@@ -211,264 +215,266 @@ typedef FormData_pg_attribute *Form_pg_attribute;
* ----------------
*/
#define Schema_pg_type \
-{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1247, {"typnamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typowner"}, 23, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typlen"}, 21, 0, 2, 4, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1247, {"typbyval"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typtype"}, 18, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typisdefined"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typdelim"}, 18, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typrelid"}, 26, 0, 4, 9, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typelem"}, 26, 0, 4, 10, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typinput"}, 24, 0, 4, 11, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typoutput"}, 24, 0, 4, 12, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typalign"}, 18, 0, 1, 13, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typstorage"}, 18, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typnotnull"}, 16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1247, {"typbasetype"}, 26, 0, 4, 16, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typtypmod"}, 23, 0, 4, 17, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typndims"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1247, {"typdefaultbin"}, 25, 0, -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false }, \
-{ 1247, {"typdefault"}, 25, 0, -1, 20, 0, -1, -1, false, 'x', false, 'i', false, false }
-
-
-DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i f f));
-DATA(insert ( 1247 typnamespace 26 0 4 2 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typowner 23 0 4 3 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typlen 21 0 2 4 0 -1 -1 t p f s f f));
-DATA(insert ( 1247 typbyval 16 0 1 5 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typtype 18 0 1 6 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typisdefined 16 0 1 7 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typdelim 18 0 1 8 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typrelid 26 0 4 9 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typelem 26 0 4 10 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typinput 24 0 4 11 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typoutput 24 0 4 12 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typalign 18 0 1 13 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typstorage 18 0 1 14 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typnotnull 16 0 1 15 0 -1 -1 t p f c f f));
-DATA(insert ( 1247 typbasetype 26 0 4 16 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typtypmod 23 0 4 17 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typndims 23 0 4 18 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 typdefaultbin 25 0 -1 19 0 -1 -1 f x f i f f));
-DATA(insert ( 1247 typdefault 25 0 -1 20 0 -1 -1 f x f i f f));
-DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
-DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+{ 1247, {"typname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typnamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typowner"}, 23, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typlen"}, 21, 0, 2, 4, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1247, {"typbyval"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typtype"}, 18, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typisdefined"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typdelim"}, 18, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typrelid"}, 26, 0, 4, 9, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typelem"}, 26, 0, 4, 10, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typinput"}, 24, 0, 4, 11, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typoutput"}, 24, 0, 4, 12, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typalign"}, 18, 0, 1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typstorage"}, 18, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typnotnull"}, 16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1247, {"typbasetype"}, 26, 0, 4, 16, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typtypmod"}, 23, 0, 4, 17, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typndims"}, 23, 0, 4, 18, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1247, {"typdefaultbin"}, 25, 0, -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false, false }, \
+{ 1247, {"typdefault"}, 25, 0, -1, 20, 0, -1, -1, false, 'x', false, 'i', false, false, false }
+
+
+DATA(insert ( 1247 typname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1247 typnamespace 26 0 4 2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typowner 23 0 4 3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typlen 21 0 2 4 0 -1 -1 t p f s t f f));
+DATA(insert ( 1247 typbyval 16 0 1 5 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typtype 18 0 1 6 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typisdefined 16 0 1 7 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typdelim 18 0 1 8 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typrelid 26 0 4 9 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typelem 26 0 4 10 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typinput 24 0 4 11 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typoutput 24 0 4 12 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typalign 18 0 1 13 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typstorage 18 0 1 14 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typnotnull 16 0 1 15 0 -1 -1 t p f c t f f));
+DATA(insert ( 1247 typbasetype 26 0 4 16 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typtypmod 23 0 4 17 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typndims 23 0 4 18 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 typdefaultbin 25 0 -1 19 0 -1 -1 f x f i f f f));
+DATA(insert ( 1247 typdefault 25 0 -1 20 0 -1 -1 f x f i f f f));
+DATA(insert ( 1247 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1247 oid 26 0 4 -2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_database
* ----------------
*/
-DATA(insert ( 1262 datname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i f f));
-DATA(insert ( 1262 datdba 23 0 4 2 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 encoding 23 0 4 3 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 datistemplate 16 0 1 4 0 -1 -1 t p f c f f));
-DATA(insert ( 1262 datallowconn 16 0 1 5 0 -1 -1 t p f c f f));
-DATA(insert ( 1262 datlastsysoid 26 0 4 6 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 datvacuumxid 28 0 4 7 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 datfrozenxid 28 0 4 8 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 datname 19 0 NAMEDATALEN 1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1262 datdba 23 0 4 2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 encoding 23 0 4 3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 datistemplate 16 0 1 4 0 -1 -1 t p f c t f f));
+DATA(insert ( 1262 datallowconn 16 0 1 5 0 -1 -1 t p f c t f f));
+DATA(insert ( 1262 datlastsysoid 26 0 4 6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 datvacuumxid 28 0 4 7 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 datfrozenxid 28 0 4 8 0 -1 -1 t p f i t f f));
/* do not mark datpath as toastable; GetRawDatabaseInfo won't cope */
-DATA(insert ( 1262 datpath 25 0 -1 9 0 -1 -1 f p f i f f));
-DATA(insert ( 1262 datconfig 1009 0 -1 10 0 -1 -1 f x f i f f));
-DATA(insert ( 1262 datacl 1034 0 -1 11 0 -1 -1 f x f i f f));
-DATA(insert ( 1262 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
-DATA(insert ( 1262 oid 26 0 4 -2 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1262 datpath 25 0 -1 9 0 -1 -1 f p f i t f f));
+DATA(insert ( 1262 datconfig 1009 0 -1 10 0 -1 -1 f x f i f f f));
+DATA(insert ( 1262 datacl 1034 0 -1 11 0 -1 -1 f x f i f f f));
+DATA(insert ( 1262 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1262 oid 26 0 4 -2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1262 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_proc
* ----------------
*/
#define Schema_pg_proc \
-{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1255, {"pronamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1255, {"proowner"}, 23, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1255, {"prolang"}, 26, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1255, {"proisagg"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1255, {"prosecdef"}, 16, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1255, {"proisstrict"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1255, {"proretset"}, 16, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1255, {"provolatile"}, 18, 0, 1, 9, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1255, {"pronargs"}, 21, 0, 2, 10, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1255, {"prorettype"}, 26, 0, 4, 11, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1255, {"prosrc"}, 25, 0, -1, 13, 0, -1, -1, false, 'x', false, 'i', false, false }, \
-{ 1255, {"probin"}, 17, 0, -1, 14, 0, -1, -1, false, 'x', false, 'i', false, false }, \
-{ 1255, {"proacl"}, 1034, 0, -1, 15, 0, -1, -1, false, 'x', false, 'i', false, false }
-
-DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i f f));
-DATA(insert ( 1255 pronamespace 26 0 4 2 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 proowner 23 0 4 3 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 prolang 26 0 4 4 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 proisagg 16 0 1 5 0 -1 -1 t p f c f f));
-DATA(insert ( 1255 prosecdef 16 0 1 6 0 -1 -1 t p f c f f));
-DATA(insert ( 1255 proisstrict 16 0 1 7 0 -1 -1 t p f c f f));
-DATA(insert ( 1255 proretset 16 0 1 8 0 -1 -1 t p f c f f));
-DATA(insert ( 1255 provolatile 18 0 1 9 0 -1 -1 t p f c f f));
-DATA(insert ( 1255 pronargs 21 0 2 10 0 -1 -1 t p f s f f));
-DATA(insert ( 1255 prorettype 26 0 4 11 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 12 0 -1 -1 f p f i f f));
-DATA(insert ( 1255 prosrc 25 0 -1 13 0 -1 -1 f x f i f f));
-DATA(insert ( 1255 probin 17 0 -1 14 0 -1 -1 f x f i f f));
-DATA(insert ( 1255 proacl 1034 0 -1 15 0 -1 -1 f x f i f f));
-DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
-DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+{ 1255, {"proname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false }, \
+{ 1255, {"pronamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1255, {"proowner"}, 23, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1255, {"prolang"}, 26, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1255, {"proisagg"}, 16, 0, 1, 5, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1255, {"prosecdef"}, 16, 0, 1, 6, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1255, {"proisstrict"}, 16, 0, 1, 7, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1255, {"proretset"}, 16, 0, 1, 8, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1255, {"provolatile"}, 18, 0, 1, 9, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1255, {"pronargs"}, 21, 0, 2, 10, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1255, {"prorettype"}, 26, 0, 4, 11, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1255, {"proargtypes"}, 30, 0, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', false, 'i', true, false, false }, \
+{ 1255, {"prosrc"}, 25, 0, -1, 13, 0, -1, -1, false, 'x', false, 'i', false, false, false }, \
+{ 1255, {"probin"}, 17, 0, -1, 14, 0, -1, -1, false, 'x', false, 'i', false, false, false }, \
+{ 1255, {"proacl"}, 1034, 0, -1, 15, 0, -1, -1, false, 'x', false, 'i', false, false, false }
+
+DATA(insert ( 1255 proname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1255 pronamespace 26 0 4 2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 proowner 23 0 4 3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 prolang 26 0 4 4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 proisagg 16 0 1 5 0 -1 -1 t p f c t f f));
+DATA(insert ( 1255 prosecdef 16 0 1 6 0 -1 -1 t p f c t f f));
+DATA(insert ( 1255 proisstrict 16 0 1 7 0 -1 -1 t p f c t f f));
+DATA(insert ( 1255 proretset 16 0 1 8 0 -1 -1 t p f c t f f));
+DATA(insert ( 1255 provolatile 18 0 1 9 0 -1 -1 t p f c t f f));
+DATA(insert ( 1255 pronargs 21 0 2 10 0 -1 -1 t p f s t f f));
+DATA(insert ( 1255 prorettype 26 0 4 11 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 proargtypes 30 0 INDEX_MAX_KEYS*4 12 0 -1 -1 f p f i t f f));
+DATA(insert ( 1255 prosrc 25 0 -1 13 0 -1 -1 f x f i f f f));
+DATA(insert ( 1255 probin 17 0 -1 14 0 -1 -1 f x f i f f f));
+DATA(insert ( 1255 proacl 1034 0 -1 15 0 -1 -1 f x f i f f f));
+DATA(insert ( 1255 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1255 oid 26 0 4 -2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_shadow
* ----------------
*/
-DATA(insert ( 1260 usename 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i f f));
-DATA(insert ( 1260 usesysid 23 -1 4 2 0 -1 -1 t p f i f f));
-DATA(insert ( 1260 usecreatedb 16 0 1 3 0 -1 -1 t p f c f f));
-DATA(insert ( 1260 usesuper 16 0 1 4 0 -1 -1 t p f c f f));
-DATA(insert ( 1260 usecatupd 16 0 1 5 0 -1 -1 t p f c f f));
-DATA(insert ( 1260 passwd 25 0 -1 6 0 -1 -1 f x f i f f));
-DATA(insert ( 1260 valuntil 702 0 4 7 0 -1 -1 t p f i f f));
-DATA(insert ( 1260 useconfig 1009 0 -1 8 0 -1 -1 f x f i f f));
-DATA(insert ( 1260 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
+DATA(insert ( 1260 usename 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1260 usesysid 23 -1 4 2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1260 usecreatedb 16 0 1 3 0 -1 -1 t p f c t f f));
+DATA(insert ( 1260 usesuper 16 0 1 4 0 -1 -1 t p f c t f f));
+DATA(insert ( 1260 usecatupd 16 0 1 5 0 -1 -1 t p f c t f f));
+DATA(insert ( 1260 passwd 25 0 -1 6 0 -1 -1 f x f i f f f));
+DATA(insert ( 1260 valuntil 702 0 4 7 0 -1 -1 t p f i f f f));
+DATA(insert ( 1260 useconfig 1009 0 -1 8 0 -1 -1 f x f i f f f));
+DATA(insert ( 1260 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
/* no OIDs in pg_shadow */
-DATA(insert ( 1260 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1260 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1260 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1260 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1260 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1260 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1260 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1260 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1260 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1260 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_group
* ----------------
*/
-DATA(insert ( 1261 groname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i f f));
-DATA(insert ( 1261 grosysid 23 -1 4 2 0 -1 -1 t p f i f f));
-DATA(insert ( 1261 grolist 1007 0 -1 3 0 -1 -1 f x f i f f));
-DATA(insert ( 1261 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
+DATA(insert ( 1261 groname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1261 grosysid 23 -1 4 2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1261 grolist 1007 0 -1 3 0 -1 -1 f x f i f f f));
+DATA(insert ( 1261 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
/* no OIDs in pg_group */
-DATA(insert ( 1261 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1261 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1261 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1261 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1261 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1261 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1261 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1261 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1261 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1261 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_attribute
* ----------------
*/
#define Schema_pg_attribute \
-{ 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1249, {"atttypid"}, 26, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"attstattarget"}, 23, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"attlen"}, 21, 0, 2, 5, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1249, {"attnum"}, 21, 0, 2, 6, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1249, {"attndims"}, 23, 0, 4, 7, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"attcacheoff"}, 23, 0, 4, 8, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"atttypmod"}, 23, 0, 4, 9, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1249, {"attbyval"}, 16, 0, 1, 10, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1249, {"attstorage"}, 18, 0, 1, 11, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1249, {"attisset"}, 16, 0, 1, 12, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1249, {"attalign"}, 18, 0, 1, 13, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1249, {"attnotnull"}, 16, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1249, {"atthasdef"}, 16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', false, false }
-
-DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p f i f f));
-DATA(insert ( 1249 atttypid 26 0 4 3 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 attstattarget 23 0 4 4 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 attlen 21 0 2 5 0 -1 -1 t p f s f f));
-DATA(insert ( 1249 attnum 21 0 2 6 0 -1 -1 t p f s f f));
-DATA(insert ( 1249 attndims 23 0 4 7 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 attcacheoff 23 0 4 8 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 atttypmod 23 0 4 9 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 attbyval 16 0 1 10 0 -1 -1 t p f c f f));
-DATA(insert ( 1249 attstorage 18 0 1 11 0 -1 -1 t p f c f f));
-DATA(insert ( 1249 attisset 16 0 1 12 0 -1 -1 t p f c f f));
-DATA(insert ( 1249 attalign 18 0 1 13 0 -1 -1 t p f c f f));
-DATA(insert ( 1249 attnotnull 16 0 1 14 0 -1 -1 t p f c f f));
-DATA(insert ( 1249 atthasdef 16 0 1 15 0 -1 -1 t p f c f f));
-DATA(insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
+{ 1249, {"attrelid"}, 26, -1, 4, 1, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1249, {"attname"}, 19, -1, NAMEDATALEN, 2, 0, -1, -1, false, 'p', false, 'i', true, false, false }, \
+{ 1249, {"atttypid"}, 26, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1249, {"attstattarget"}, 23, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1249, {"attlen"}, 21, 0, 2, 5, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1249, {"attnum"}, 21, 0, 2, 6, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1249, {"attndims"}, 23, 0, 4, 7, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1249, {"attcacheoff"}, 23, 0, 4, 8, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1249, {"atttypmod"}, 23, 0, 4, 9, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1249, {"attbyval"}, 16, 0, 1, 10, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1249, {"attstorage"}, 18, 0, 1, 11, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1249, {"attisset"}, 16, 0, 1, 12, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1249, {"attalign"}, 18, 0, 1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1249, {"attnotnull"}, 16, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1249, {"atthasdef"}, 16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1249, {"attisdropped"}, 16, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', true, false, false }
+
+DATA(insert ( 1249 attrelid 26 -1 4 1 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 attname 19 -1 NAMEDATALEN 2 0 -1 -1 f p f i t f f));
+DATA(insert ( 1249 atttypid 26 0 4 3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 attstattarget 23 0 4 4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 attlen 21 0 2 5 0 -1 -1 t p f s t f f));
+DATA(insert ( 1249 attnum 21 0 2 6 0 -1 -1 t p f s t f f));
+DATA(insert ( 1249 attndims 23 0 4 7 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 attcacheoff 23 0 4 8 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 atttypmod 23 0 4 9 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 attbyval 16 0 1 10 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 attstorage 18 0 1 11 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 attisset 16 0 1 12 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 attalign 18 0 1 13 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 attnotnull 16 0 1 14 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 atthasdef 16 0 1 15 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 attisdropped 16 0 1 16 0 -1 -1 t p f c t f f));
+DATA(insert ( 1249 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
/* no OIDs in pg_attribute */
-DATA(insert ( 1249 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+DATA(insert ( 1249 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_class
* ----------------
*/
#define Schema_pg_class \
-{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1259, {"relnamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"reltype"}, 26, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relowner"}, 23, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relam"}, 26, 0, 4, 5, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relfilenode"}, 26, 0, 4, 6, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relpages"}, 23, 0, 4, 7, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"reltuples"}, 700, 0, 4, 8, 0, -1, -1, false, 'p', false, 'i', false, false }, \
-{ 1259, {"reltoastrelid"}, 26, 0, 4, 9, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"reltoastidxid"}, 26, 0, 4, 10, 0, -1, -1, true, 'p', false, 'i', false, false }, \
-{ 1259, {"relhasindex"}, 16, 0, 1, 11, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relisshared"}, 16, 0, 1, 12, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relkind"}, 18, 0, 1, 13, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relnatts"}, 21, 0, 2, 14, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relchecks"}, 21, 0, 2, 15, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"reltriggers"}, 21, 0, 2, 16, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relukeys"}, 21, 0, 2, 17, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relfkeys"}, 21, 0, 2, 18, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relrefs"}, 21, 0, 2, 19, 0, -1, -1, true, 'p', false, 's', false, false }, \
-{ 1259, {"relhasoids"}, 16, 0, 1, 20, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhaspkey"}, 16, 0, 1, 21, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhasrules"}, 16, 0, 1, 22, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relhassubclass"},16, 0, 1, 23, 0, -1, -1, true, 'p', false, 'c', false, false }, \
-{ 1259, {"relacl"}, 1034, 0, -1, 24, 0, -1, -1, false, 'x', false, 'i', false, false }
-
-DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i f f));
-DATA(insert ( 1259 relnamespace 26 0 4 2 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 reltype 26 0 4 3 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relowner 23 0 4 4 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relam 26 0 4 5 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relfilenode 26 0 4 6 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relpages 23 0 4 7 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 reltuples 700 0 4 8 0 -1 -1 f p f i f f));
-DATA(insert ( 1259 reltoastrelid 26 0 4 9 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 reltoastidxid 26 0 4 10 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 relhasindex 16 0 1 11 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relisshared 16 0 1 12 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relkind 18 0 1 13 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relnatts 21 0 2 14 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relchecks 21 0 2 15 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 reltriggers 21 0 2 16 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relukeys 21 0 2 17 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relfkeys 21 0 2 18 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relrefs 21 0 2 19 0 -1 -1 t p f s f f));
-DATA(insert ( 1259 relhasoids 16 0 1 20 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relhaspkey 16 0 1 21 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relhasrules 16 0 1 22 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relhassubclass 16 0 1 23 0 -1 -1 t p f c f f));
-DATA(insert ( 1259 relacl 1034 0 -1 24 0 -1 -1 f x f i f f));
-DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i f f));
-DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 cmin 29 0 4 -4 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p f i f f));
-DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
+{ 1259, {"relname"}, 19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false }, \
+{ 1259, {"relnamespace"}, 26, 0, 4, 2, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"reltype"}, 26, 0, 4, 3, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"relowner"}, 23, 0, 4, 4, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"relam"}, 26, 0, 4, 5, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"relfilenode"}, 26, 0, 4, 6, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"relpages"}, 23, 0, 4, 7, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"reltuples"}, 700, 0, 4, 8, 0, -1, -1, false, 'p', false, 'i', true, false, false }, \
+{ 1259, {"reltoastrelid"}, 26, 0, 4, 9, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"reltoastidxid"}, 26, 0, 4, 10, 0, -1, -1, true, 'p', false, 'i', true, false, false }, \
+{ 1259, {"relhasindex"}, 16, 0, 1, 11, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relisshared"}, 16, 0, 1, 12, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relkind"}, 18, 0, 1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relnatts"}, 21, 0, 2, 14, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1259, {"relchecks"}, 21, 0, 2, 15, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1259, {"reltriggers"}, 21, 0, 2, 16, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1259, {"relukeys"}, 21, 0, 2, 17, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1259, {"relfkeys"}, 21, 0, 2, 18, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1259, {"relrefs"}, 21, 0, 2, 19, 0, -1, -1, true, 'p', false, 's', true, false, false }, \
+{ 1259, {"relhasoids"}, 16, 0, 1, 20, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relhaspkey"}, 16, 0, 1, 21, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relhasrules"}, 16, 0, 1, 22, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relhassubclass"},16, 0, 1, 23, 0, -1, -1, true, 'p', false, 'c', true, false, false }, \
+{ 1259, {"relacl"}, 1034, 0, -1, 24, 0, -1, -1, false, 'x', false, 'i', false, false, false }
+
+DATA(insert ( 1259 relname 19 -1 NAMEDATALEN 1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1259 relnamespace 26 0 4 2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 reltype 26 0 4 3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 relowner 23 0 4 4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 relam 26 0 4 5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 relfilenode 26 0 4 6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 relpages 23 0 4 7 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 reltuples 700 0 4 8 0 -1 -1 f p f i t f f));
+DATA(insert ( 1259 reltoastrelid 26 0 4 9 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 reltoastidxid 26 0 4 10 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 relhasindex 16 0 1 11 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relisshared 16 0 1 12 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relkind 18 0 1 13 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relnatts 21 0 2 14 0 -1 -1 t p f s t f f));
+DATA(insert ( 1259 relchecks 21 0 2 15 0 -1 -1 t p f s t f f));
+DATA(insert ( 1259 reltriggers 21 0 2 16 0 -1 -1 t p f s t f f));
+DATA(insert ( 1259 relukeys 21 0 2 17 0 -1 -1 t p f s t f f));
+DATA(insert ( 1259 relfkeys 21 0 2 18 0 -1 -1 t p f s t f f));
+DATA(insert ( 1259 relrefs 21 0 2 19 0 -1 -1 t p f s t f f));
+DATA(insert ( 1259 relhasoids 16 0 1 20 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relhaspkey 16 0 1 21 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relhasrules 16 0 1 22 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relhassubclass 16 0 1 23 0 -1 -1 t p f c t f f));
+DATA(insert ( 1259 relacl 1034 0 -1 24 0 -1 -1 f x f i f f f));
+DATA(insert ( 1259 ctid 27 0 6 -1 0 -1 -1 f p f i t f f));
+DATA(insert ( 1259 oid 26 0 4 -2 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 xmin 28 0 4 -3 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 cmin 29 0 4 -4 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p f i t f f));
+DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p f i t f f));
/* ----------------
* pg_xactlock - this is not a real relation, but is a placeholder
@@ -478,6 +484,6 @@ DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p f i f f));
* table; and this entry is just to link to that one.
* ----------------
*/
-DATA(insert ( 376 xactlockfoo 26 0 4 1 0 -1 -1 t p f i f f));
+DATA(insert ( 376 xactlockfoo 26 0 4 1 0 -1 -1 t p f i t f f));
#endif /* PG_ATTRIBUTE_H */
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 827769029f3..2d5011e6d62 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_class.h,v 1.69 2002/07/24 19:11:12 petere Exp $
+ * $Id: pg_class.h,v 1.70 2002/08/02 18:15:09 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -136,7 +136,7 @@ typedef FormData_pg_class *Form_pg_class;
DATA(insert OID = 1247 ( pg_type PGNSP 71 PGUID 0 1247 0 0 0 0 f f r 20 0 0 0 0 0 t f f f _null_ ));
DESCR("");
-DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 15 0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 1249 ( pg_attribute PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 16 0 0 0 0 0 f f f f _null_ ));
DESCR("");
DATA(insert OID = 1255 ( pg_proc PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 15 0 0 0 0 0 t f f f _null_ ));
DESCR("");
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 9eb7367f2e3..2fdb5bc210c 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: executor.h,v 1.72 2002/07/20 15:12:55 tgl Exp $
+ * $Id: executor.h,v 1.73 2002/08/02 18:15:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -159,7 +159,6 @@ extern void ExecAssignScanType(CommonScanState *csstate,
TupleDesc tupDesc, bool shouldFree);
extern void ExecAssignScanTypeFromOuterPlan(Plan *node,
CommonScanState *csstate);
-extern Form_pg_attribute ExecGetTypeInfo(Relation relDesc);
extern ExprContext *MakeExprContext(TupleTableSlot *slot,
MemoryContext queryContext);
diff --git a/src/include/parser/parse_relation.h b/src/include/parser/parse_relation.h
index 5ff6d74e364..a34e2a5619f 100644
--- a/src/include/parser/parse_relation.h
+++ b/src/include/parser/parse_relation.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parse_relation.h,v 1.34 2002/06/20 20:29:51 momjian Exp $
+ * $Id: parse_relation.h,v 1.35 2002/08/02 18:15:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -58,7 +58,7 @@ extern RangeTblEntry *addImplicitRTE(ParseState *pstate, RangeVar *relation);
extern void expandRTE(ParseState *pstate, RangeTblEntry *rte,
List **colnames, List **colvars);
extern List *expandRelAttrs(ParseState *pstate, RangeTblEntry *rte);
-extern int attnameAttNum(Relation rd, char *a);
+extern int attnameAttNum(Relation rd, const char *attname, bool sysColOK);
extern Name attnumAttName(Relation rd, int attid);
extern Oid attnumTypeId(Relation rd, int attid);
diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h
index dcc310aab5e..ab06031b2c6 100644
--- a/src/include/utils/lsyscache.h
+++ b/src/include/utils/lsyscache.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: lsyscache.h,v 1.55 2002/07/12 18:43:19 tgl Exp $
+ * $Id: lsyscache.h,v 1.56 2002/08/02 18:15:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,9 +18,8 @@
extern bool op_in_opclass(Oid opno, Oid opclass);
extern bool op_requires_recheck(Oid opno, Oid opclass);
extern char *get_attname(Oid relid, AttrNumber attnum);
-extern AttrNumber get_attnum(Oid relid, char *attname);
+extern AttrNumber get_attnum(Oid relid, const char *attname);
extern Oid get_atttype(Oid relid, AttrNumber attnum);
-extern bool get_attisset(Oid relid, char *attname);
extern int32 get_atttypmod(Oid relid, AttrNumber attnum);
extern void get_atttypetypmod(Oid relid, AttrNumber attnum,
Oid *typid, int32 *typmod);
diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h
index e8c70fa00be..b9a17c7453e 100644
--- a/src/include/utils/syscache.h
+++ b/src/include/utils/syscache.h
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: syscache.h,v 1.51 2002/07/25 10:07:13 ishii Exp $
+ * $Id: syscache.h,v 1.52 2002/08/02 18:15:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -78,6 +78,10 @@ extern bool SearchSysCacheExists(int cacheId,
extern Oid GetSysCacheOid(int cacheId,
Datum key1, Datum key2, Datum key3, Datum key4);
+extern HeapTuple SearchSysCacheAttName(Oid relid, const char *attname);
+extern HeapTuple SearchSysCacheCopyAttName(Oid relid, const char *attname);
+extern bool SearchSysCacheExistsAttName(Oid relid, const char *attname);
+
extern Datum SysCacheGetAttr(int cacheId, HeapTuple tup,
AttrNumber attributeNumber, bool *isNull);
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 8f6ff87cf6c..bc95eba1ed1 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.42 2002/06/15 19:54:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.43 2002/08/02 18:15:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -1037,10 +1037,7 @@ plpgsql_parse_dblwordtype(char *string)
/*
* Fetch the named table field and it's type
*/
- attrtup = SearchSysCache(ATTNAME,
- ObjectIdGetDatum(classOid),
- PointerGetDatum(word2),
- 0, 0);
+ attrtup = SearchSysCacheAttName(classOid, word2);
if (!HeapTupleIsValid(attrtup))
{
ReleaseSysCache(classtup);
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 2dc64f3ccfa..741b012c289 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -635,9 +635,9 @@ delete from atacc1;
alter table atacc1 alter test set not null;
-- try altering a non-existent column, should fail
alter table atacc1 alter bar set not null;
-ERROR: ALTER TABLE: relation "atacc1" has no column "bar"
+ERROR: Relation "atacc1" has no column "bar"
alter table atacc1 alter bar drop not null;
-ERROR: ALTER TABLE: relation "atacc1" has no column "bar"
+ERROR: Relation "atacc1" has no column "bar"
-- try altering the oid column, should fail
alter table atacc1 alter oid set not null;
ERROR: ALTER TABLE: Cannot alter system attribute "oid"
@@ -707,7 +707,7 @@ ERROR: pg_atoi: error in "wrong_datatype": can't parse "wrong_datatype"
alter table def_test alter column c2 set default 20;
-- set defaults on a non-existent column: this should fail
alter table def_test alter column c3 set default 30;
-ERROR: ALTER TABLE: relation "def_test" has no column "c3"
+ERROR: Relation "def_test" has no column "c3"
-- set defaults on views: we need to create a view, add a rule
-- to allow insertions into it, and then alter the view to add
-- a default
@@ -735,3 +735,291 @@ select * from def_view_test;
drop rule def_view_test_ins on def_view_test;
drop view def_view_test;
drop table def_test;
+-- alter table / drop column tests
+-- try altering system catalogs, should fail
+alter table pg_class drop column relname;
+ERROR: ALTER TABLE: relation "pg_class" is a system catalog
+-- try altering non-existent table, should fail
+alter table foo drop column bar;
+ERROR: Relation "foo" does not exist
+-- test dropping columns
+create table atacc1 (a int4 not null, b int4, c int4 not null, d int4);
+insert into atacc1 values (1, 2, 3, 4);
+alter table atacc1 drop a;
+alter table atacc1 drop a;
+ERROR: Relation "atacc1" has no column "a"
+-- SELECTs
+select * from atacc1;
+ b | c | d
+---+---+---
+ 2 | 3 | 4
+(1 row)
+
+select * from atacc1 order by a;
+ERROR: Attribute "a" not found
+select * from atacc1 order by "........pg.dropped.1........";
+ERROR: Attribute "........pg.dropped.1........" not found
+select * from atacc1 group by a;
+ERROR: Attribute "a" not found
+select * from atacc1 group by "........pg.dropped.1........";
+ERROR: Attribute "........pg.dropped.1........" not found
+select atacc1.* from atacc1;
+ b | c | d
+---+---+---
+ 2 | 3 | 4
+(1 row)
+
+select a from atacc1;
+ERROR: Attribute "a" not found
+select atacc1.a from atacc1;
+ERROR: No such attribute atacc1.a
+select b,c,d from atacc1;
+ b | c | d
+---+---+---
+ 2 | 3 | 4
+(1 row)
+
+select a,b,c,d from atacc1;
+ERROR: Attribute "a" not found
+select * from atacc1 where a = 1;
+ERROR: Attribute "a" not found
+select "........pg.dropped.1........" from atacc1;
+ERROR: Attribute "........pg.dropped.1........" not found
+select atacc1."........pg.dropped.1........" from atacc1;
+ERROR: No such attribute atacc1.........pg.dropped.1........
+select "........pg.dropped.1........",b,c,d from atacc1;
+ERROR: Attribute "........pg.dropped.1........" not found
+select * from atacc1 where "........pg.dropped.1........" = 1;
+ERROR: Attribute "........pg.dropped.1........" not found
+-- UPDATEs
+update atacc1 set a = 3;
+ERROR: Relation "atacc1" has no column "a"
+update atacc1 set b = 2 where a = 3;
+ERROR: Attribute "a" not found
+update atacc1 set "........pg.dropped.1........" = 3;
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+update atacc1 set b = 2 where "........pg.dropped.1........" = 3;
+ERROR: Attribute "........pg.dropped.1........" not found
+-- INSERTs
+insert into atacc1 values (10, 11, 12, 13);
+ERROR: INSERT has more expressions than target columns
+insert into atacc1 values (default, 11, 12, 13);
+ERROR: INSERT has more expressions than target columns
+insert into atacc1 values (11, 12, 13);
+insert into atacc1 (a) values (10);
+ERROR: Relation "atacc1" has no column "a"
+insert into atacc1 (a) values (default);
+ERROR: Relation "atacc1" has no column "a"
+insert into atacc1 (a,b,c,d) values (10,11,12,13);
+ERROR: Relation "atacc1" has no column "a"
+insert into atacc1 (a,b,c,d) values (default,11,12,13);
+ERROR: Relation "atacc1" has no column "a"
+insert into atacc1 (b,c,d) values (11,12,13);
+insert into atacc1 ("........pg.dropped.1........") values (10);
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+insert into atacc1 ("........pg.dropped.1........") values (default);
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+insert into atacc1 ("........pg.dropped.1........",b,c,d) values (10,11,12,13);
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+insert into atacc1 ("........pg.dropped.1........",b,c,d) values (default,11,12,13);
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+-- DELETEs
+delete from atacc1 where a = 3;
+ERROR: Attribute "a" not found
+delete from atacc1 where "........pg.dropped.1........" = 3;
+ERROR: Attribute "........pg.dropped.1........" not found
+delete from atacc1;
+-- try dropping a non-existent column, should fail
+alter table atacc1 drop bar;
+ERROR: Relation "atacc1" has no column "bar"
+-- try dropping the oid column, should fail
+alter table atacc1 drop oid;
+ERROR: ALTER TABLE: Cannot drop system attribute "oid"
+-- try creating a view and altering that, should fail
+create view myview as select * from atacc1;
+select * from myview;
+ b | c | d
+---+---+---
+(0 rows)
+
+alter table myview drop d;
+ERROR: ALTER TABLE: relation "myview" is not a table
+drop view myview;
+-- test some commands to make sure they fail on the dropped column
+analyze atacc1(a);
+ERROR: Relation "atacc1" has no column "a"
+analyze atacc1("........pg.dropped.1........");
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+vacuum analyze atacc1(a);
+ERROR: Relation "atacc1" has no column "a"
+vacuum analyze atacc1("........pg.dropped.1........");
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+comment on column atacc1.a is 'testing';
+ERROR: Relation "atacc1" has no column "a"
+comment on column atacc1."........pg.dropped.1........" is 'testing';
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 alter a set storage plain;
+ERROR: ALTER TABLE: relation "atacc1" has no column "a"
+alter table atacc1 alter "........pg.dropped.1........" set storage plain;
+ERROR: ALTER TABLE: relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 alter a set statistics 0;
+ERROR: ALTER TABLE: relation "atacc1" has no column "a"
+alter table atacc1 alter "........pg.dropped.1........" set statistics 0;
+ERROR: ALTER TABLE: relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 alter a set default 3;
+ERROR: Relation "atacc1" has no column "a"
+alter table atacc1 alter "........pg.dropped.1........" set default 3;
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 alter a drop default;
+ERROR: Relation "atacc1" has no column "a"
+alter table atacc1 alter "........pg.dropped.1........" drop default;
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 alter a set not null;
+ERROR: Relation "atacc1" has no column "a"
+alter table atacc1 alter "........pg.dropped.1........" set not null;
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 alter a drop not null;
+ERROR: Relation "atacc1" has no column "a"
+alter table atacc1 alter "........pg.dropped.1........" drop not null;
+ERROR: Relation "atacc1" has no column "........pg.dropped.1........"
+alter table atacc1 rename a to x;
+ERROR: renameatt: attribute "a" does not exist
+alter table atacc1 rename "........pg.dropped.1........" to x;
+ERROR: renameatt: attribute "........pg.dropped.1........" does not exist
+alter table atacc1 add primary key(a);
+ERROR: ALTER TABLE: column "a" named in key does not exist
+alter table atacc1 add primary key("........pg.dropped.1........");
+ERROR: ALTER TABLE: column "........pg.dropped.1........" named in key does not exist
+alter table atacc1 add unique(a);
+ERROR: ALTER TABLE: column "a" named in key does not exist
+alter table atacc1 add unique("........pg.dropped.1........");
+ERROR: ALTER TABLE: column "........pg.dropped.1........" named in key does not exist
+alter table atacc1 add check (a > 3);
+ERROR: Attribute "a" not found
+alter table atacc1 add check ("........pg.dropped.1........" > 3);
+ERROR: Attribute "........pg.dropped.1........" not found
+create table atacc2 (id int4 unique);
+NOTICE: CREATE TABLE / UNIQUE will create implicit index 'atacc2_id_key' for table 'atacc2'
+alter table atacc1 add foreign key (a) references atacc2(id);
+NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
+ERROR: ALTER TABLE: column "a" referenced in foreign key constraint does not exist
+alter table atacc1 add foreign key ("........pg.dropped.1........") references atacc2(id);
+NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
+ERROR: ALTER TABLE: column "........pg.dropped.1........" referenced in foreign key constraint does not exist
+alter table atacc2 add foreign key (id) references atacc1(a);
+NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
+ERROR: UNIQUE constraint matching given keys for referenced table "atacc1" not found
+alter table atacc2 add foreign key (id) references atacc1("........pg.dropped.1........");
+NOTICE: ALTER TABLE will create implicit trigger(s) for FOREIGN KEY check(s)
+ERROR: UNIQUE constraint matching given keys for referenced table "atacc1" not found
+drop table atacc2;
+create index "testing_idx" on atacc1(a);
+ERROR: DefineIndex: attribute "a" not found
+create index "testing_idx" on atacc1("........pg.dropped.1........");
+ERROR: DefineIndex: attribute "........pg.dropped.1........" not found
+-- test create as and select into
+insert into atacc1 values (21, 22, 23);
+create table test1 as select * from atacc1;
+select * from test1;
+ b | c | d
+----+----+----
+ 21 | 22 | 23
+(1 row)
+
+drop table test1;
+select * into test2 from atacc1;
+select * from test2;
+ b | c | d
+----+----+----
+ 21 | 22 | 23
+(1 row)
+
+drop table test2;
+-- try dropping all columns
+alter table atacc1 drop c;
+alter table atacc1 drop d;
+alter table atacc1 drop b;
+ERROR: ALTER TABLE: Cannot drop last column from table "atacc1"
+select * from atacc1;
+ b
+----
+ 21
+(1 row)
+
+drop table atacc1;
+-- test inheritance
+create table parent (a int, b int, c int);
+insert into parent values (1, 2, 3);
+alter table parent drop a;
+create table child (d varchar(255)) inherits (parent);
+insert into child values (12, 13, 'testing');
+select * from parent;
+ b | c
+----+----
+ 2 | 3
+ 12 | 13
+(2 rows)
+
+select * from child;
+ b | c | d
+----+----+---------
+ 12 | 13 | testing
+(1 row)
+
+alter table parent drop c;
+select * from parent;
+ b
+----
+ 2
+ 12
+(2 rows)
+
+select * from child;
+ b | d
+----+---------
+ 12 | testing
+(1 row)
+
+drop table child;
+drop table parent;
+-- test copy in/out
+create table test (a int4, b int4, c int4);
+insert into test values (1,2,3);
+alter table test drop a;
+copy test to stdout;
+2 3
+copy test(a) to stdout;
+ERROR: Relation "test" has no column "a"
+copy test("........pg.dropped.1........") to stdout;
+ERROR: Relation "test" has no column "........pg.dropped.1........"
+copy test from stdin;
+ERROR: copy: line 1, Extra data after last expected column
+lost synchronization with server, resetting connection
+select * from test;
+ b | c
+---+---
+ 2 | 3
+(1 row)
+
+copy test from stdin;
+select * from test;
+ b | c
+----+----
+ 2 | 3
+ 21 | 22
+(2 rows)
+
+copy test(a) from stdin;
+ERROR: Relation "test" has no column "a"
+copy test("........pg.dropped.1........") from stdin;
+ERROR: Relation "test" has no column "........pg.dropped.1........"
+copy test(b,c) from stdin;
+select * from test;
+ b | c
+----+----
+ 2 | 3
+ 21 | 22
+ 31 | 32
+(3 rows)
+
+drop table test;
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index e4f806c8a56..58a5b6eb22a 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -29,26 +29,44 @@ COPY x (b, d) from stdin;
COPY x (a, b, c, d, e) from stdin;
-- non-existent column in column list: should fail
COPY x (xyz) from stdin;
-ERROR: COPY: Specified column "xyz" does not exist
+ERROR: Relation "x" has no column "xyz"
-- too many columns in column list: should fail
COPY x (a, b, c, d, e, d, c) from stdin;
-ERROR: COPY: Too many columns specified
+ERROR: Attribute "d" specified more than once
-- missing data: should fail
COPY x from stdin;
-ERROR: copy: line 1, COPY TEXT: Missing data for attribute 1
+ERROR: copy: line 1, Missing data for column "b"
lost synchronization with server, resetting connection
COPY x from stdin;
-ERROR: copy: line 1, COPY TEXT: Missing data for attribute 4
+ERROR: copy: line 1, Missing data for column "e"
lost synchronization with server, resetting connection
COPY x from stdin;
-ERROR: copy: line 1, COPY TEXT: Missing data for attribute 4
+ERROR: copy: line 1, Missing data for column "e"
lost synchronization with server, resetting connection
-- extra data: should fail
COPY x from stdin;
-ERROR: copy: line 1, COPY TEXT: Extra data encountered
+ERROR: copy: line 1, Extra data after last expected column
lost synchronization with server, resetting connection
-- various COPY options: delimiters, oids, NULL string
COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x';
+-- check results of copy in
+SELECT * FROM x;
+ a | b | c | d | e
+-------+----+-------+--------+----------------------
+ 10000 | 21 | 31 | 41 | before trigger fired
+ 10001 | 22 | 32 | 42 | before trigger fired
+ 10002 | 23 | 33 | 43 | before trigger fired
+ 10003 | 24 | 34 | 44 | before trigger fired
+ 10004 | 25 | 35 | 45 | before trigger fired
+ 10005 | 26 | 36 | 46 | before trigger fired
+ 6 | | 45 | 80 | before trigger fired
+ 1 | 1 | stuff | test_1 | after trigger fired
+ 2 | 2 | stuff | test_2 | after trigger fired
+ 3 | 3 | stuff | test_3 | after trigger fired
+ 4 | 4 | stuff | test_4 | after trigger fired
+ 5 | 5 | stuff | test_5 | after trigger fired
+(12 rows)
+
-- COPY w/ oids on a table w/o oids should fail
CREATE TABLE no_oids (
a int,
@@ -61,6 +79,7 @@ COPY no_oids FROM stdin WITH OIDS;
ERROR: COPY: table "no_oids" does not have OIDs
COPY no_oids TO stdout WITH OIDS;
ERROR: COPY: table "no_oids" does not have OIDs
+-- check copy out
COPY x TO stdout;
10000 21 31 41 before trigger fired
10001 22 32 42 before trigger fired
@@ -87,6 +106,19 @@ stuff after trigger fired
stuff after trigger fired
stuff after trigger fired
stuff after trigger fired
+COPY x (b, e) TO stdout WITH NULL 'I''m null';
+21 before trigger fired
+22 before trigger fired
+23 before trigger fired
+24 before trigger fired
+25 before trigger fired
+26 before trigger fired
+I'm null before trigger fired
+1 after trigger fired
+2 after trigger fired
+3 after trigger fired
+4 after trigger fired
+5 after trigger fired
DROP TABLE x;
DROP FUNCTION fn_x_before();
DROP FUNCTION fn_x_after();
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index f39998073d7..8946d2b15b3 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -571,3 +571,163 @@ select * from def_view_test;
drop rule def_view_test_ins on def_view_test;
drop view def_view_test;
drop table def_test;
+
+-- alter table / drop column tests
+-- try altering system catalogs, should fail
+alter table pg_class drop column relname;
+
+-- try altering non-existent table, should fail
+alter table foo drop column bar;
+
+-- test dropping columns
+create table atacc1 (a int4 not null, b int4, c int4 not null, d int4);
+insert into atacc1 values (1, 2, 3, 4);
+alter table atacc1 drop a;
+alter table atacc1 drop a;
+
+-- SELECTs
+select * from atacc1;
+select * from atacc1 order by a;
+select * from atacc1 order by "........pg.dropped.1........";
+select * from atacc1 group by a;
+select * from atacc1 group by "........pg.dropped.1........";
+select atacc1.* from atacc1;
+select a from atacc1;
+select atacc1.a from atacc1;
+select b,c,d from atacc1;
+select a,b,c,d from atacc1;
+select * from atacc1 where a = 1;
+select "........pg.dropped.1........" from atacc1;
+select atacc1."........pg.dropped.1........" from atacc1;
+select "........pg.dropped.1........",b,c,d from atacc1;
+select * from atacc1 where "........pg.dropped.1........" = 1;
+
+-- UPDATEs
+update atacc1 set a = 3;
+update atacc1 set b = 2 where a = 3;
+update atacc1 set "........pg.dropped.1........" = 3;
+update atacc1 set b = 2 where "........pg.dropped.1........" = 3;
+
+-- INSERTs
+insert into atacc1 values (10, 11, 12, 13);
+insert into atacc1 values (default, 11, 12, 13);
+insert into atacc1 values (11, 12, 13);
+insert into atacc1 (a) values (10);
+insert into atacc1 (a) values (default);
+insert into atacc1 (a,b,c,d) values (10,11,12,13);
+insert into atacc1 (a,b,c,d) values (default,11,12,13);
+insert into atacc1 (b,c,d) values (11,12,13);
+insert into atacc1 ("........pg.dropped.1........") values (10);
+insert into atacc1 ("........pg.dropped.1........") values (default);
+insert into atacc1 ("........pg.dropped.1........",b,c,d) values (10,11,12,13);
+insert into atacc1 ("........pg.dropped.1........",b,c,d) values (default,11,12,13);
+
+-- DELETEs
+delete from atacc1 where a = 3;
+delete from atacc1 where "........pg.dropped.1........" = 3;
+delete from atacc1;
+
+-- try dropping a non-existent column, should fail
+alter table atacc1 drop bar;
+
+-- try dropping the oid column, should fail
+alter table atacc1 drop oid;
+
+-- try creating a view and altering that, should fail
+create view myview as select * from atacc1;
+select * from myview;
+alter table myview drop d;
+drop view myview;
+
+-- test some commands to make sure they fail on the dropped column
+analyze atacc1(a);
+analyze atacc1("........pg.dropped.1........");
+vacuum analyze atacc1(a);
+vacuum analyze atacc1("........pg.dropped.1........");
+comment on column atacc1.a is 'testing';
+comment on column atacc1."........pg.dropped.1........" is 'testing';
+alter table atacc1 alter a set storage plain;
+alter table atacc1 alter "........pg.dropped.1........" set storage plain;
+alter table atacc1 alter a set statistics 0;
+alter table atacc1 alter "........pg.dropped.1........" set statistics 0;
+alter table atacc1 alter a set default 3;
+alter table atacc1 alter "........pg.dropped.1........" set default 3;
+alter table atacc1 alter a drop default;
+alter table atacc1 alter "........pg.dropped.1........" drop default;
+alter table atacc1 alter a set not null;
+alter table atacc1 alter "........pg.dropped.1........" set not null;
+alter table atacc1 alter a drop not null;
+alter table atacc1 alter "........pg.dropped.1........" drop not null;
+alter table atacc1 rename a to x;
+alter table atacc1 rename "........pg.dropped.1........" to x;
+alter table atacc1 add primary key(a);
+alter table atacc1 add primary key("........pg.dropped.1........");
+alter table atacc1 add unique(a);
+alter table atacc1 add unique("........pg.dropped.1........");
+alter table atacc1 add check (a > 3);
+alter table atacc1 add check ("........pg.dropped.1........" > 3);
+create table atacc2 (id int4 unique);
+alter table atacc1 add foreign key (a) references atacc2(id);
+alter table atacc1 add foreign key ("........pg.dropped.1........") references atacc2(id);
+alter table atacc2 add foreign key (id) references atacc1(a);
+alter table atacc2 add foreign key (id) references atacc1("........pg.dropped.1........");
+drop table atacc2;
+create index "testing_idx" on atacc1(a);
+create index "testing_idx" on atacc1("........pg.dropped.1........");
+
+-- test create as and select into
+insert into atacc1 values (21, 22, 23);
+create table test1 as select * from atacc1;
+select * from test1;
+drop table test1;
+select * into test2 from atacc1;
+select * from test2;
+drop table test2;
+
+-- try dropping all columns
+alter table atacc1 drop c;
+alter table atacc1 drop d;
+alter table atacc1 drop b;
+select * from atacc1;
+
+drop table atacc1;
+
+-- test inheritance
+create table parent (a int, b int, c int);
+insert into parent values (1, 2, 3);
+alter table parent drop a;
+create table child (d varchar(255)) inherits (parent);
+insert into child values (12, 13, 'testing');
+
+select * from parent;
+select * from child;
+alter table parent drop c;
+select * from parent;
+select * from child;
+
+drop table child;
+drop table parent;
+
+-- test copy in/out
+create table test (a int4, b int4, c int4);
+insert into test values (1,2,3);
+alter table test drop a;
+copy test to stdout;
+copy test(a) to stdout;
+copy test("........pg.dropped.1........") to stdout;
+copy test from stdin;
+10 11 12
+\.
+select * from test;
+copy test from stdin;
+21 22
+\.
+select * from test;
+copy test(a) from stdin;
+copy test("........pg.dropped.1........") from stdin;
+copy test(b,c) from stdin;
+31 32
+\.
+select * from test;
+drop table test;
+
diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql
index b0ccfe67160..4f0d50247f1 100644
--- a/src/test/regress/sql/copy2.sql
+++ b/src/test/regress/sql/copy2.sql
@@ -76,6 +76,9 @@ COPY x (b, c, d, e) from stdin with oids delimiter ',' null 'x';
500000,x,45,80,90
\.
+-- check results of copy in
+SELECT * FROM x;
+
-- COPY w/ oids on a table w/o oids should fail
CREATE TABLE no_oids (
a int,
@@ -89,8 +92,11 @@ INSERT INTO no_oids (a, b) VALUES (20, 30);
COPY no_oids FROM stdin WITH OIDS;
COPY no_oids TO stdout WITH OIDS;
+-- check copy out
COPY x TO stdout;
COPY x (c, e) TO stdout;
+COPY x (b, e) TO stdout WITH NULL 'I''m null';
+
DROP TABLE x;
DROP FUNCTION fn_x_before();
DROP FUNCTION fn_x_after();