Skip to content

Commit 6d0d15c

Browse files
committed
Make the world at least somewhat safe for zero-column tables, and
remove the special case in ALTER DROP COLUMN to prohibit dropping a table's last column.
1 parent 23616b4 commit 6d0d15c

File tree

6 files changed

+64
-81
lines changed

6 files changed

+64
-81
lines changed

src/backend/access/common/tupdesc.c

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.90 2002/09/22 19:42:50 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.91 2002/09/28 20:00:18 tgl Exp $
1212
*
1313
* NOTES
1414
* some of the executor utility code such as "ExecTypeFromTL" should be
@@ -39,28 +39,34 @@
3939
TupleDesc
4040
CreateTemplateTupleDesc(int natts, bool hasoid)
4141
{
42-
uint32 size;
4342
TupleDesc desc;
4443

4544
/*
4645
* sanity checks
4746
*/
48-
AssertArg(natts >= 1);
47+
AssertArg(natts >= 0);
4948

5049
/*
5150
* allocate enough memory for the tuple descriptor and zero it as
5251
* TupleDescInitEntry assumes that the descriptor is filled with NULL
5352
* pointers.
5453
*/
55-
size = natts * sizeof(Form_pg_attribute);
5654
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
57-
desc->attrs = (Form_pg_attribute *) palloc(size);
58-
desc->constr = NULL;
59-
MemSet(desc->attrs, 0, size);
6055

6156
desc->natts = natts;
6257
desc->tdhasoid = hasoid;
6358

59+
if (natts > 0)
60+
{
61+
uint32 size = natts * sizeof(Form_pg_attribute);
62+
63+
desc->attrs = (Form_pg_attribute *) palloc(size);
64+
MemSet(desc->attrs, 0, size);
65+
}
66+
else
67+
desc->attrs = NULL;
68+
desc->constr = NULL;
69+
6470
return desc;
6571
}
6672

@@ -79,7 +85,7 @@ CreateTupleDesc(int natts, bool hasoid, Form_pg_attribute *attrs)
7985
/*
8086
* sanity checks
8187
*/
82-
AssertArg(natts >= 1);
88+
AssertArg(natts >= 0);
8389

8490
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
8591
desc->attrs = attrs;
@@ -108,17 +114,20 @@ CreateTupleDescCopy(TupleDesc tupdesc)
108114

109115
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
110116
desc->natts = tupdesc->natts;
111-
size = desc->natts * sizeof(Form_pg_attribute);
112-
desc->attrs = (Form_pg_attribute *) palloc(size);
113-
for (i = 0; i < desc->natts; i++)
117+
if (desc->natts > 0)
114118
{
115-
desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
116-
memcpy(desc->attrs[i],
117-
tupdesc->attrs[i],
118-
ATTRIBUTE_TUPLE_SIZE);
119-
desc->attrs[i]->attnotnull = false;
120-
desc->attrs[i]->atthasdef = false;
119+
size = desc->natts * sizeof(Form_pg_attribute);
120+
desc->attrs = (Form_pg_attribute *) palloc(size);
121+
for (i = 0; i < desc->natts; i++)
122+
{
123+
desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
124+
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
125+
desc->attrs[i]->attnotnull = false;
126+
desc->attrs[i]->atthasdef = false;
127+
}
121128
}
129+
else
130+
desc->attrs = NULL;
122131
desc->constr = NULL;
123132
desc->tdhasoid = tupdesc->tdhasoid;
124133

@@ -142,15 +151,18 @@ CreateTupleDescCopyConstr(TupleDesc tupdesc)
142151

143152
desc = (TupleDesc) palloc(sizeof(struct tupleDesc));
144153
desc->natts = tupdesc->natts;
145-
size = desc->natts * sizeof(Form_pg_attribute);
146-
desc->attrs = (Form_pg_attribute *) palloc(size);
147-
for (i = 0; i < desc->natts; i++)
154+
if (desc->natts > 0)
148155
{
149-
desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
150-
memcpy(desc->attrs[i],
151-
tupdesc->attrs[i],
152-
ATTRIBUTE_TUPLE_SIZE);
156+
size = desc->natts * sizeof(Form_pg_attribute);
157+
desc->attrs = (Form_pg_attribute *) palloc(size);
158+
for (i = 0; i < desc->natts; i++)
159+
{
160+
desc->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);
161+
memcpy(desc->attrs[i], tupdesc->attrs[i], ATTRIBUTE_TUPLE_SIZE);
162+
}
153163
}
164+
else
165+
desc->attrs = NULL;
154166
if (constr)
155167
{
156168
TupleConstr *cpy = (TupleConstr *) palloc(sizeof(TupleConstr));
@@ -197,7 +209,8 @@ FreeTupleDesc(TupleDesc tupdesc)
197209

198210
for (i = 0; i < tupdesc->natts; i++)
199211
pfree(tupdesc->attrs[i]);
200-
pfree(tupdesc->attrs);
212+
if (tupdesc->attrs)
213+
pfree(tupdesc->attrs);
201214
if (tupdesc->constr)
202215
{
203216
if (tupdesc->constr->num_defval > 0)
@@ -228,7 +241,6 @@ FreeTupleDesc(TupleDesc tupdesc)
228241
}
229242

230243
pfree(tupdesc);
231-
232244
}
233245

234246
/*
@@ -361,6 +373,7 @@ TupleDescInitEntry(TupleDesc desc,
361373
*/
362374
AssertArg(PointerIsValid(desc));
363375
AssertArg(attributeNumber >= 1);
376+
AssertArg(attributeNumber <= desc->natts);
364377

365378
/*
366379
* attributeName's are sometimes NULL, from resdom's. I don't know

src/backend/commands/tablecmds.c

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.44 2002/09/23 20:43:40 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.45 2002/09/28 20:00:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -2331,9 +2331,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
23312331
{
23322332
Relation rel;
23332333
AttrNumber attnum;
2334-
AttrNumber n;
23352334
TupleDesc tupleDesc;
2336-
bool success;
23372335
ObjectAddress object;
23382336

23392337
rel = heap_open(myrelid, AccessExclusiveLock);
@@ -2359,34 +2357,13 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
23592357
RelationGetRelationName(rel), colName);
23602358

23612359
/* Can't drop a system attribute */
2360+
/* XXX perhaps someday allow dropping OID? */
23622361
if (attnum < 0)
23632362
elog(ERROR, "ALTER TABLE: Cannot drop system attribute \"%s\"",
23642363
colName);
23652364

2366-
/*
2367-
* Make sure there will be at least one user column left in the
2368-
* relation after we drop this one. Zero-length tuples tend to
2369-
* confuse us.
2370-
*/
2371-
tupleDesc = RelationGetDescr(rel);
2372-
2373-
success = false;
2374-
for (n = 1; n <= tupleDesc->natts; n++)
2375-
{
2376-
Form_pg_attribute attribute = tupleDesc->attrs[n - 1];
2377-
2378-
if (!attribute->attisdropped && n != attnum)
2379-
{
2380-
success = true;
2381-
break;
2382-
}
2383-
}
2384-
2385-
if (!success)
2386-
elog(ERROR, "ALTER TABLE: Cannot drop last column from table \"%s\"",
2387-
RelationGetRelationName(rel));
2388-
23892365
/* Don't drop inherited columns */
2366+
tupleDesc = RelationGetDescr(rel);
23902367
if (tupleDesc->attrs[attnum - 1]->attinhcount > 0 && !recursing)
23912368
elog(ERROR, "ALTER TABLE: Cannot drop inherited column \"%s\"",
23922369
colName);

src/backend/executor/execTuples.c

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.59 2002/09/04 20:31:17 momjian Exp $
18+
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.60 2002/09/28 20:00:19 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -560,23 +560,14 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
560560
TupleDesc
561561
ExecTypeFromTL(List *targetList, bool hasoid)
562562
{
563-
List *tlitem;
564563
TupleDesc typeInfo;
565-
Resdom *resdom;
566-
Oid restype;
564+
List *tlitem;
567565
int len;
568566

569-
/*
570-
* examine targetlist - if empty then return NULL
571-
*/
572-
len = ExecTargetListLength(targetList);
573-
574-
if (len == 0)
575-
return NULL;
576-
577567
/*
578568
* allocate a new typeInfo
579569
*/
570+
len = ExecTargetListLength(targetList);
580571
typeInfo = CreateTemplateTupleDesc(len, hasoid);
581572

582573
/*
@@ -585,6 +576,8 @@ ExecTypeFromTL(List *targetList, bool hasoid)
585576
foreach(tlitem, targetList)
586577
{
587578
TargetEntry *tle = lfirst(tlitem);
579+
Resdom *resdom;
580+
Oid restype;
588581

589582
if (tle->resdom != NULL)
590583
{

src/backend/executor/nodeAgg.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
* Portions Copyright (c) 1994, Regents of the University of California
4747
*
4848
* IDENTIFICATION
49-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.87 2002/09/18 21:35:20 tgl Exp $
49+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.88 2002/09/28 20:00:19 tgl Exp $
5050
*
5151
*-------------------------------------------------------------------------
5252
*/
@@ -658,20 +658,20 @@ ExecAgg(Agg *node)
658658
if (inputTuple == NULL)
659659
{
660660
TupleDesc tupType;
661-
Datum *tupValue;
662-
char *null_array;
663-
AttrNumber attnum;
661+
Datum *dvalues;
662+
char *dnulls;
664663

665664
tupType = aggstate->csstate.css_ScanTupleSlot->ttc_tupleDescriptor;
666-
tupValue = projInfo->pi_tupValue;
667665
/* watch out for null input tuples, though... */
668-
if (tupType && tupValue)
666+
if (tupType && tupType->natts > 0)
669667
{
670-
null_array = (char *) palloc(sizeof(char) * tupType->natts);
671-
for (attnum = 0; attnum < tupType->natts; attnum++)
672-
null_array[attnum] = 'n';
673-
inputTuple = heap_formtuple(tupType, tupValue, null_array);
674-
pfree(null_array);
668+
dvalues = (Datum *) palloc(sizeof(Datum) * tupType->natts);
669+
dnulls = (char *) palloc(sizeof(char) * tupType->natts);
670+
MemSet(dvalues, 0, sizeof(Datum) * tupType->natts);
671+
MemSet(dnulls, 'n', sizeof(char) * tupType->natts);
672+
inputTuple = heap_formtuple(tupType, dvalues, dnulls);
673+
pfree(dvalues);
674+
pfree(dnulls);
675675
}
676676
}
677677
}

src/backend/parser/parse_target.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.90 2002/09/18 21:35:22 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.91 2002/09/28 20:00:19 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -386,6 +386,7 @@ static List *
386386
ExpandAllTables(ParseState *pstate)
387387
{
388388
List *target = NIL;
389+
bool found_table = false;
389390
List *ns;
390391

391392
foreach(ns, pstate->p_namespace)
@@ -413,11 +414,12 @@ ExpandAllTables(ParseState *pstate)
413414
if (!rte->inFromCl)
414415
continue;
415416

417+
found_table = true;
416418
target = nconc(target, expandRelAttrs(pstate, rte));
417419
}
418420

419421
/* Check for SELECT *; */
420-
if (target == NIL)
422+
if (!found_table)
421423
elog(ERROR, "Wildcard with no tables specified not allowed");
422424

423425
return target;

src/test/regress/expected/alter_table.out

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -939,11 +939,9 @@ drop table test2;
939939
alter table atacc1 drop c;
940940
alter table atacc1 drop d;
941941
alter table atacc1 drop b;
942-
ERROR: ALTER TABLE: Cannot drop last column from table "atacc1"
943942
select * from atacc1;
944-
b
945-
----
946-
21
943+
944+
--
947945
(1 row)
948946

949947
drop table atacc1;

0 commit comments

Comments
 (0)