summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiroshi Inoue2000-03-09 05:00:26 +0000
committerHiroshi Inoue2000-03-09 05:00:26 +0000
commitfd9ff86bd9c4f1a96f3796212212b4099ca275de (patch)
treedb51e5e26579069c839261a7c6d21a3b329d0c3b
parent6513946cbbb0b06a9d764900a6db8ff88578f65c (diff)
Trial implementation of ALTER DROP COLUMN.
They are #ifdef'd. Add -D_DROP_COLUMN_HACK__ compile option to evaluate it.
-rw-r--r--src/backend/commands/command.c381
-rw-r--r--src/backend/commands/copy.c44
-rw-r--r--src/backend/commands/vacuum.c6
-rw-r--r--src/backend/optimizer/prep/preptlist.c37
-rw-r--r--src/backend/parser/parse_relation.c10
-rw-r--r--src/backend/parser/parse_target.c8
-rw-r--r--src/backend/utils/cache/relcache.c22
-rw-r--r--src/include/catalog/pg_attribute.h16
8 files changed, 514 insertions, 10 deletions
diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 620c601b17d..b75f3840a87 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -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__ */
}
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 85a50c10398..a91072522a5 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.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)
{
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index 3cd9b026519..f86c5bc1e22 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -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);
diff --git a/src/backend/optimizer/prep/preptlist.c b/src/backend/optimizer/prep/preptlist.c
index 8c6c2ceb8d9..22ed6f418f7 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.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:
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 02a3cd2de09..265642faaf3 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.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 */
diff --git a/src/backend/parser/parse_target.c b/src/backend/parser/parse_target.c
index 9d00e1789e1..e815efc9639 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.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;
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 74bcb10c69e..11ab6c750fd 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -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;
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index d7a1adb1c6a..54f3adc9ee1 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -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