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:
parent
6513946cbb
commit
fd9ff86bd9
@ -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__ */
|
||||
}
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
22
src/backend/utils/cache/relcache.c
vendored
22
src/backend/utils/cache/relcache.c
vendored
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user