On Sun, 2004-11-14 at 18:29 -0500, Tom Lane wrote: > Good analysis. We can't check earlier than DefineRelation AFAICS, > because earlier stages don't know about inherited columns. > > On reflection I suspect there are similar issues with SELECTs that have > more than 64K output columns. This probably has to be guarded against > in parser/analyze.c.
You're correct -- we also crash on extremely long SELECT statements. Another variant of the problem would be a CREATE TABLE that inherits from, say, 70 relations, each of which has 1,000 columns. Attached is a patch. Not entirely sure that the checks I added are in the right places, but at any rate this fixes the three identified problems for me. -Neil
--- src/backend/commands/tablecmds.c +++ src/backend/commands/tablecmds.c @@ -681,6 +681,23 @@ int child_attno; /* + * Check for and reject tables with too many columns. We perform + * this check relatively early for two reasons: (a) we don't run + * the risk of overflowing an AttrNumber in subsequent code (b) an + * O(n^2) algorithm is okay if we're processing <= 1600 columns, + * but could take minutes to execute if the user attempts to + * create a table with hundreds of thousands of columns. + * + * Note that we also need to check that any we do not exceed this + * figure after including columns from inherited relations. + */ + if (list_length(schema) > MaxHeapAttributeNumber) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_COLUMNS), + errmsg("tables can have at most %d columns", + MaxHeapAttributeNumber))); + + /* * Check for duplicate names in the explicit list of attributes. * * Although we might consider merging such entries in the same way that @@ -979,6 +996,16 @@ } schema = inhSchema; + + /* + * Check that we haven't exceeded the legal # of columns after + * merging in inherited columns. + */ + if (list_length(schema) > MaxHeapAttributeNumber) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_COLUMNS), + errmsg("tables can have at most %d columns", + MaxHeapAttributeNumber))); } /* --- src/backend/parser/parse_target.c +++ src/backend/parser/parse_target.c @@ -106,6 +106,17 @@ List *p_target = NIL; ListCell *o_target; + /* + * Reject tlists that are too long. Ultimately there is a + * correspondence between tlist entries and attributes in a tuple, + * so use MaxHeapAttributeNumber. + */ + if (list_length(targetlist) > MaxHeapAttributeNumber) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("target lists can have at most %d entries", + MaxHeapAttributeNumber))); + foreach(o_target, targetlist) { ResTarget *res = (ResTarget *) lfirst(o_target);
---------------------------(end of broadcast)--------------------------- TIP 5: Have you checked our extensive FAQ? http://www.postgresql.org/docs/faqs/FAQ.html