Trial implementation of ALTER DROP COLUMN.

They are #ifdef'd.
Add -D_DROP_COLUMN_HACK__ compile option
to evaluate it.
This commit is contained in:
Hiroshi Inoue 2000-03-09 05:00:26 +00:00
parent 6513946cbb
commit fd9ff86bd9
8 changed files with 514 additions and 10 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.69 2000/02/15 18:15:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.70 2000/03/09 05:00:23 inoue Exp $
*
* NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated
@ -43,6 +43,15 @@
#include "utils/syscache.h"
#include "utils/temprel.h"
#include "commands/trigger.h"
#ifdef _DROP_COLUMN_HACK__
#include "catalog/pg_index.h"
#include "catalog/pg_relcheck.h"
#include "commands/defrem.h"
#include "commands/comment.h"
#include "access/genam.h"
#include "optimizer/clauses.h"
#include "../parser/parse.h"
#endif /* _DROP_COLUMN_HACK__ */
/* ----------------
* PortalExecutorHeapMemory stuff
@ -668,6 +677,213 @@ drop_default(Oid relid, int16 attnum)
}
#ifdef _DROP_COLUMN_HACK__
/*
* ALTER TABLE DROP COLUMN trial implementation
*
*/
/*
* system table scan(index scan/sequential scan)
*/
typedef struct SysScanDescData
{
Relation heap_rel;
Relation irel;
HeapScanDesc scan;
IndexScanDesc iscan;
HeapTupleData tuple;
Buffer buffer;
} SysScanDescData, *SysScanDesc;
static void *
systable_beginscan(Relation rel, const char *indexRelname, int nkeys, ScanKey entry)
{
bool hasindex = (rel->rd_rel->relhasindex && !IsIgnoringSystemIndexes());
SysScanDesc sysscan;
sysscan = (SysScanDesc) palloc(sizeof(SysScanDescData));
sysscan->heap_rel = rel;
sysscan->irel = (Relation) NULL;
sysscan->tuple.t_datamcxt = NULL;
sysscan->tuple.t_data = NULL;
sysscan->buffer = InvalidBuffer;
if (hasindex)
{
sysscan->irel = index_openr((char *)indexRelname);
sysscan->iscan = index_beginscan(sysscan->irel, false, nkeys, entry);
}
else
sysscan->scan = heap_beginscan(rel, false, SnapshotNow, nkeys, entry);
return (void *) sysscan;
}
static void
systable_endscan(void *scan)
{
SysScanDesc sysscan = (SysScanDesc) scan;
if (sysscan->irel)
{
if (BufferIsValid(sysscan->buffer))
ReleaseBuffer(sysscan->buffer);
index_endscan(sysscan->iscan);
index_close(sysscan->irel);
}
else
heap_endscan(sysscan->scan);
pfree(scan);
}
static HeapTuple
systable_getnext(void *scan)
{
SysScanDesc sysscan = (SysScanDesc) scan;
HeapTuple htup = (HeapTuple) NULL;
RetrieveIndexResult indexRes;
if (sysscan->irel)
{
if (BufferIsValid(sysscan->buffer))
{
ReleaseBuffer(sysscan->buffer);
sysscan->buffer = InvalidBuffer;
}
while (indexRes = index_getnext(sysscan->iscan, ForwardScanDirection), indexRes != NULL)
{
sysscan->tuple.t_self = indexRes->heap_iptr;
heap_fetch(sysscan->heap_rel, SnapshotNow, &sysscan->tuple, &(sysscan->buffer));
pfree(indexRes);
if (sysscan->tuple.t_data != NULL)
{
htup = &sysscan->tuple;
break;
}
}
}
else
htup = heap_getnext(sysscan->scan, 0);
return htup;
}
/*
* find a specified attribute in a node entry
*/
static bool
find_attribute_walker(Node *node, int attnum)
{
if (node == NULL)
return false;
if (IsA(node, Var))
{
Var *var = (Var *) node;
if (var->varlevelsup == 0 && var->varno == 1 &&
var->varattno == attnum)
return true;
}
return expression_tree_walker(node, find_attribute_walker, (void *)attnum);
}
static bool
find_attribute_in_node(Node *node, int attnum)
{
return expression_tree_walker(node, find_attribute_walker, (void *)attnum);
}
/*
* Remove/check references for the column
*/
static bool
RemoveColumnReferences(Oid reloid, int attnum, bool checkonly, HeapTuple reltup)
{
Relation indexRelation, rcrel;
ScanKeyData entry;
HeapScanDesc scan;
void *sysscan;
HeapTuple htup, indexTuple;
Form_pg_index index;
Form_pg_relcheck relcheck;
Form_pg_class pgcform = (Form_pg_class) NULL;
int i;
bool checkok = true;
if (!checkonly)
pgcform = (Form_pg_class) GETSTRUCT (reltup);
/*
* Remove/check constraints here
*/
ScanKeyEntryInitialize(&entry, (bits16) 0x0, Anum_pg_relcheck_rcrelid,
(RegProcedure) F_OIDEQ, ObjectIdGetDatum(reloid));
rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
sysscan = systable_beginscan(rcrel, RelCheckIndex,1 ,&entry);
while (HeapTupleIsValid(htup = systable_getnext(sysscan)))
{
char *ccbin;
Node *node;
relcheck = (Form_pg_relcheck) GETSTRUCT(htup);
ccbin = textout(&relcheck->rcbin);
if (!ccbin)
continue;
node = stringToNode(ccbin);
pfree(ccbin);
if (find_attribute_in_node(node, attnum))
{
if (checkonly)
{
checkok = false;
elog(ERROR, "target column is used in a constraint");
}
else
{
heap_delete(rcrel, &htup->t_self, NULL);
pgcform->relchecks--;
}
}
}
systable_endscan(sysscan);
heap_close(rcrel, NoLock);
/*
* What to do with triggers/rules/views/procedues ?
*/
/*
* Remove/check indexes
*/
indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
ObjectIdGetDatum(reloid));
scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
{
index = (Form_pg_index) GETSTRUCT(indexTuple);
for (i = 0; i < INDEX_MAX_KEYS; i++)
{
if (index->indkey[i] == InvalidAttrNumber)
break;
else if (index->indkey[i] == attnum)
{
if (checkonly)
{
checkok = false;
elog(ERROR, "target column is used in an index");
}
else
{
htup = SearchSysCacheTuple(RELOID,
ObjectIdGetDatum(index->indexrelid),
0, 0, 0);
RemoveIndex(NameStr(((Form_pg_class) GETSTRUCT(htup))->relname));
}
break;
}
}
}
heap_endscan(scan);
heap_close(indexRelation, NoLock);
return checkok;
}
#endif /* _DROP_COLUMN_HACK__ */
/*
* ALTER TABLE DROP COLUMN
@ -677,7 +893,170 @@ AlterTableDropColumn(const char *relationName,
bool inh, const char *colName,
int behavior)
{
#ifdef _DROP_COLUMN_HACK__
Relation rel, attrdesc, adrel;
Oid myrelid, attoid;
HeapTuple reltup;
HeapTupleData classtuple;
Buffer buffer;
Form_pg_attribute attribute;
HeapTuple tup;
Relation idescs[Num_pg_attr_indices];
int attnum;
bool hasindex;
char dropColname[32];
void *sysscan;
ScanKeyData scankeys[2];
if (inh)
elog(ERROR, "ALTER TABLE / DROP COLUMN with inherit option is not supported yet");
/*
* permissions checking. this would normally be done in utility.c,
* but this particular routine is recursive.
*
* normally, only the owner of a class can change its schema.
*/
if (!allowSystemTableMods && IsSystemRelationName(relationName))
elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
relationName);
#ifndef NO_SECURITY
if (!pg_ownercheck(UserName, relationName, RELNAME))
elog(ERROR, "ALTER TABLE: permission denied");
#endif
/*
* Grab an exclusive lock on the target table, which we will NOT release
* until end of transaction.
*/
rel = heap_openr(relationName, AccessExclusiveLock);
myrelid = RelationGetRelid(rel);
heap_close(rel, NoLock); /* close rel but keep lock! */
/*
* What to do when rel has inheritors ?
*/
if (length(find_all_inheritors(myrelid)) > 1)
elog(ERROR, "ALTER TABLE: cannot drop a column on table that is inherited from");
/*
* lock the pg_class tuple for update
*/
reltup = SearchSysCacheTuple(RELNAME, PointerGetDatum(relationName),
0, 0, 0);
if (!HeapTupleIsValid(reltup))
elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
relationName);
rel = heap_openr(RelationRelationName, RowExclusiveLock);
classtuple.t_self = reltup->t_self;
switch (heap_mark4update(rel, &classtuple, &buffer))
{
case HeapTupleSelfUpdated:
case HeapTupleMayBeUpdated:
break;
default:
elog(ERROR, "couldn't lock pg_class tuple");
}
reltup = heap_copytuple(&classtuple);
ReleaseBuffer(buffer);
/*
* XXX is the following check sufficient?
*/
if (((Form_pg_class) GETSTRUCT(reltup))->relkind != RELKIND_RELATION)
{
elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table",
relationName);
}
attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
/*
* Get the target pg_attribute tuple
*/
tup = SearchSysCacheTupleCopy(ATTNAME,
ObjectIdGetDatum(reltup->t_data->t_oid),
PointerGetDatum(colName), 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "ALTER TABLE: column name \"%s\" doesn't exist in table \"%s\"",
colName, relationName);
attribute = (Form_pg_attribute) GETSTRUCT(tup);
if (attribute->attnum <= 0)
elog(ERROR, "ALTER TABLE: column name \"%s\" was already dropped", colName);
attnum = attribute->attnum;
attoid = tup->t_data->t_oid;
/*
* Check constraints/indices etc here
*/
if (behavior != CASCADE)
{
if (!RemoveColumnReferences(myrelid, attnum, true, NULL))
elog(ERROR, "the column is referenced");
}
/*
* change the target pg_attribute tuple
*/
sprintf(dropColname, "*already Dropped*%d", attnum);
namestrcpy(&(attribute->attname), dropColname);
ATTRIBUTE_DROP_COLUMN(attribute);
heap_update(attrdesc, &tup->t_self, tup, NULL);
hasindex = (!IsIgnoringSystemIndexes() && RelationGetForm(attrdesc)->relhasindex);
if (hasindex)
{
CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
CatalogIndexInsert(idescs, Num_pg_attr_indices,
attrdesc, tup);
CatalogCloseIndices(Num_pg_attr_indices, idescs);
}
heap_close(attrdesc, NoLock);
heap_freetuple(tup);
/* delete comments */
DeleteComments(attoid);
/* delete attrdef */
adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&scankeys[0], 0x0, Anum_pg_attrdef_adrelid,
F_OIDEQ, ObjectIdGetDatum(myrelid));
/* Oops pg_attrdef doesn't have (adrelid,adnum) index
ScanKeyEntryInitialize(&scankeys[1], 0x0, Anum_pg_attrdef_adnum,
F_INT2EQ, Int16GetDatum(attnum));
sysscan = systable_beginscan(adrel, AttrDefaultIndex, 2, scankeys);
*/
sysscan = systable_beginscan(adrel, AttrDefaultIndex, 1, scankeys);
while (HeapTupleIsValid(tup = systable_getnext(sysscan)))
{
if (((Form_pg_attrdef) GETSTRUCT(tup))->adnum == attnum)
{
heap_delete(adrel, &tup->t_self, NULL);
break;
}
}
systable_endscan(sysscan);
heap_close(adrel, NoLock);
/*
* Remove objects which reference this column
*/
if (behavior == CASCADE)
{
Relation ridescs[Num_pg_class_indices];
RemoveColumnReferences(myrelid, attnum, false, reltup);
/* update pg_class tuple */
heap_update(rel, &reltup->t_self, reltup, NULL);
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, ridescs);
CatalogIndexInsert(ridescs, Num_pg_class_indices, rel, reltup);
CatalogCloseIndices(Num_pg_class_indices, ridescs);
}
heap_freetuple(reltup);
heap_close(rel, NoLock);
#else
elog(ERROR, "ALTER TABLE / DROP COLUMN is not implemented");
#endif /* _DROP_COLUMN_HACK__ */
}

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.101 2000/02/13 18:59:50 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.102 2000/03/09 05:00:23 inoue Exp $
*
*-------------------------------------------------------------------------
*/
@ -394,6 +394,9 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_p
int32 attr_count,
i;
#ifdef _DROP_COLUMN_HACK__
bool *valid;
#endif /* _DROP_COLUMN_HACK__ */
Form_pg_attribute *attr;
FmgrInfo *out_functions;
Oid out_func_oid;
@ -425,8 +428,20 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_p
out_functions = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo));
elements = (Oid *) palloc(attr_count * sizeof(Oid));
typmod = (int32 *) palloc(attr_count * sizeof(int32));
#ifdef _DROP_COLUMN_HACK__
valid = (bool *) palloc(attr_count * sizeof(bool));
#endif /* _DROP_COLUMN_HACK__ */
for (i = 0; i < attr_count; i++)
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
{
valid[i] = false;
continue;
}
else
valid[i] = true;
#endif /* _DROP_COLUMN_HACK__ */
out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid);
fmgr_info(out_func_oid, &out_functions[i]);
elements[i] = GetTypeElement(attr[i]->atttypid);
@ -466,6 +481,14 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null_p
value = heap_getattr(tuple, i + 1, tupDesc, &isnull);
if (!binary)
{
#ifdef _DROP_COLUMN_HACK__
if (!valid[i])
{
if (i == attr_count - 1)
CopySendChar('\n', fp);
continue;
}
#endif /* _DROP_COLUMN_HACK__ */
if (!isnull)
{
string = (char *) (*fmgr_faddr(&out_functions[i]))
@ -692,6 +715,10 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
typmod = (int32 *) palloc(attr_count * sizeof(int32));
for (i = 0; i < attr_count; i++)
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
continue;
#endif /* _DROP_COLUMN_HACK__ */
in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
fmgr_info(in_func_oid, &in_functions[i]);
elements[i] = GetTypeElement(attr[i]->atttypid);
@ -718,6 +745,13 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
{
nulls[i] = ' ';
index_nulls[i] = ' ';
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
{
byval[i] = 'n';
continue;
}
#endif /* _DROP_COLUMN_HACK__ */
byval[i] = (bool) IsTypeByVal(attr[i]->atttypid);
}
@ -750,6 +784,14 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim, char *null
}
for (i = 0; i < attr_count && !done; i++)
{
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
{
values[i] = PointerGetDatum(NULL);
nulls[i] = 'n';
continue;
}
#endif /* _DROP_COLUMN_HACK__ */
string = CopyReadAttribute(fp, &isnull, delim, &newline, null_print);
if (isnull)
{

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.142 2000/03/08 23:41:00 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.143 2000/03/09 05:00:23 inoue Exp $
*
*-------------------------------------------------------------------------
*/
@ -2240,6 +2240,10 @@ vc_attrstats(Relation onerel, VRelStats *vacrelstats, HeapTuple tuple)
VacAttrStats *stats = &vacattrstats[i];
bool value_hit = true;
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(stats->attr))
continue;
#endif /* _DROP_COLUMN_HACK__ */
value = heap_getattr(tuple,
stats->attr->attnum, tupDesc, &isnull);

View File

@ -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.34 2000/01/26 05:56:39 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.35 2000/03/09 05:00:24 inoue Exp $
*
*-------------------------------------------------------------------------
*/
@ -189,10 +189,20 @@ expand_targetlist(List *tlist, int command_type,
{
case CMD_INSERT:
{
#ifdef _DROP_COLUMN_HACK__
Datum typedefault;
#else
Datum typedefault = get_typdefault(atttype);
#endif /* _DROP_COLUMN_HACK__ */
int typlen;
Const *temp_const;
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(att_tup))
typedefault = PointerGetDatum(NULL);
else
typedefault = get_typdefault(atttype);
#endif /* _DROP_COLUMN_HACK__ */
if (typedefault == PointerGetDatum(NULL))
typlen = 0;
else
@ -230,8 +240,25 @@ expand_targetlist(List *tlist, int command_type,
{
Var *temp_var;
#ifdef _DROP_COLUMN_HACK__
Node *temp_node = (Node *) NULL;
if (COLUMN_IS_DROPPED(att_tup))
{
temp_node = (Node *)makeConst(atttype, 0,
PointerGetDatum(NULL),
true,
false,
false, /* not a set */
false);
}
else
#endif /* _DROP_COLUMN_HACK__ */
temp_var = makeVar(result_relation, attrno, atttype,
atttypmod, 0);
#ifdef _DROP_COLUMN_HACK__
if (!temp_node)
temp_node = (Node *) temp_var;
#endif /* _DROP_COLUMN_HACK__ */
new_tle = makeTargetEntry(makeResdom(attrno,
atttype,
@ -239,8 +266,12 @@ expand_targetlist(List *tlist, int command_type,
pstrdup(attrname),
0,
(Oid) 0,
false),
(Node *) temp_var);
false),
#ifdef _DROP_COLUMN_HACK__
temp_node);
#else
(Node *) temp_var);
#endif /* _DROP_COLUMN_HACK__ */
break;
}
default:

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.35 2000/02/15 03:37:47 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.36 2000/03/09 05:00:24 inoue Exp $
*
*-------------------------------------------------------------------------
*/
@ -359,6 +359,10 @@ expandTable(ParseState *pstate, char *refname, bool getaliases)
{
char *attrname;
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(rel->rd_att->attrs[varattno]))
continue;
#endif /* _DROP_COLUMN_HACK__ */
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
attr->attrs = lappend(attr->attrs, makeString(attrname));
}
@ -404,6 +408,10 @@ expandAll(ParseState *pstate, char *relname, Attr *ref, int *this_resno)
Var *varnode;
TargetEntry *te = makeNode(TargetEntry);
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(rel->rd_att->attrs[varattno]))
continue;
#endif /* _DROP_COLUMN_HACK__ */
attrname = pstrdup(NameStr(rel->rd_att->attrs[varattno]->attname));
/* varattno is zero-based, so check that length() is always greater */

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.55 2000/02/15 03:37:47 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.56 2000/03/09 05:00:24 inoue Exp $
*
*-------------------------------------------------------------------------
*/
@ -355,6 +355,12 @@ checkInsertTargets(ParseState *pstate, List *cols, List **attrnos)
{
Ident *id = makeNode(Ident);
#ifdef _DROP_COLUMN_HACK__
if (COLUMN_IS_DROPPED(attr[i]))
{
continue;
}
#endif /* _DROP_COLUMN_HACK__ */
id->name = palloc(NAMEDATALEN);
StrNCpy(id->name, NameStr(attr[i]->attname), NAMEDATALEN);
id->indirection = NIL;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.91 2000/02/27 12:02:32 wieck Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.92 2000/03/09 05:00:25 inoue Exp $
*
*-------------------------------------------------------------------------
*/
@ -568,6 +568,9 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
AttrDefault *attrdef = NULL;
int ndef = 0;
int i;
#ifdef _DROP_COLUMN_HACK__
bool columnDropped;
#endif /* _DROP_COLUMN_HACK__ */
constr->has_not_null = false;
@ -575,12 +578,25 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
for (i = 1; i <= relation->rd_rel->relnatts; i++)
{
#ifdef _DROP_COLUMN_HACK__
columnDropped = false;
#endif /* _DROP_COLUMN_HACK__ */
atttup = (HeapTuple) AttributeRelidNumIndexScan(attrel,
RelationGetRelid(relation), i);
if (!HeapTupleIsValid(atttup))
#ifdef _DROP_COLUMN_HACK__
{
atttup = (HeapTuple) AttributeRelidNumIndexScan(attrel,
RelationGetRelid(relation), DROPPED_COLUMN_INDEX(i));
if (!HeapTupleIsValid(atttup))
#endif /* _DROP_COLUMN_HACK__ */
elog(ERROR, "cannot find attribute %d of relation %s", i,
RelationGetRelationName(relation));
#ifdef _DROP_COLUMN_HACK__
columnDropped = true;
}
#endif /* _DROP_COLUMN_HACK__ */
attp = (Form_pg_attribute) GETSTRUCT(atttup);
relation->rd_att->attrs[i - 1] =
@ -590,6 +606,10 @@ build_tupdesc_ind(RelationBuildDescInfo buildinfo,
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
#ifdef _DROP_COLUMN_HACK__
if (columnDropped)
continue;
#endif /* _DROP_COLUMN_HACK__ */
/* Update if this attribute have a constraint */
if (attp->attnotnull)
constr->has_not_null = true;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_attribute.h,v 1.53 2000/01/26 05:57:57 momjian Exp $
* $Id: pg_attribute.h,v 1.54 2000/03/09 05:00:26 inoue Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@ -178,6 +178,20 @@ typedef FormData_pg_attribute *Form_pg_attribute;
#define Anum_pg_attribute_atthasdef 15
#ifdef _DROP_COLUMN_HACK__
/*
* CONSTANT and MACROS for DROP COLUMN implementation
*/
#define DROP_COLUMN_OFFSET -20
#define COLUMN_IS_DROPPED(attribute) ((attribute)->attnum <= DROP_COLUMN_OFFSET)
#define DROPPED_COLUMN_INDEX(attidx) (DROP_COLUMN_OFFSET - attidx)
#define ATTRIBUTE_DROP_COLUMN(attribute) \
Assert((attribute)->attnum > 0); \
(attribute)->attnum = DROPPED_COLUMN_INDEX((attribute)->attnum); \
(attribute)->atttypid = (Oid) -1; \
(attribute)->attnotnull = false; \
(attribute)->atthasdef = false;
#endif /* _DROP_COLUMN_HACK__ */
/* ----------------
* SCHEMA_ macros for declaring hardcoded tuple descriptors.
* these are used in utils/cache/relcache.c