Bruce Momjian <br...@momjian.us> writes: > Using the queries in that URL, I see:
> CREATE TABLE test (data integer, data_array integer[5][5]); > CREATE TABLE test2 (LIKE test); > CREATE TABLE test3 AS SELECT * FROM test; > SELECT relname, attndims > FROM pg_class JOIN pg_attribute ON (pg_attribute.attrelid = > pg_class.oid) > WHERE attname = 'data_array'; > relname | attndims > ---------+---------- > test | 2 > --> test2 | 0 > --> test3 | 0 Yeah, that's not great. We don't have the ability to extract a number-of-dimensions from a result column of a SELECT, but we could at least take care to make attndims be 1 not 0 for an array type. And CREATE TABLE LIKE can easily do better. See attached draft. (We could simplify it a little bit if we decide to store only 1 or 0 in all cases.) > Interestingly, if I dump and restore with: > $ createdb test2; pg_dump test | sql test2 > and run the query again I get: > relname | attndims > ---------+---------- > test | 1 > test2 | 1 > test3 | 1 I looked at getting a better result here and decided that it didn't look very promising. pg_dump uses format_type() to build the type name to put in CREATE TABLE, and that doesn't have access to attndims. regards, tom lane
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c index 23cecd99c9..13fb6acfcf 100644 --- a/src/backend/commands/createas.c +++ b/src/backend/commands/createas.c @@ -183,7 +183,8 @@ create_ctas_nodata(List *tlist, IntoClause *into) col = makeColumnDef(colname, exprType((Node *) tle->expr), exprTypmod((Node *) tle->expr), - exprCollation((Node *) tle->expr)); + exprCollation((Node *) tle->expr), + -1 /* detect array-ness */ ); /* * It's possible that the column is of a collatable type but the @@ -492,10 +493,17 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo) else colname = NameStr(attribute->attname); + /* + * Note: we pass ndims as -1 not attribute->attndims because (a) the + * tupledesc we are given may not have accurate attndims, and (b) it + * seems best for this path to give results matching + * create_ctas_nodata. + */ col = makeColumnDef(colname, attribute->atttypid, attribute->atttypmod, - attribute->attcollation); + attribute->attcollation, + -1 /* detect array-ness */ ); /* * It's possible that the column is of a collatable type but the diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index b13ee2b745..d5ca4ed5cb 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -178,15 +178,18 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq) switch (i) { case SEQ_COL_LASTVAL: - coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid); + coldef = makeColumnDef("last_value", INT8OID, -1, + InvalidOid, 0); value[i - 1] = Int64GetDatumFast(seqdataform.last_value); break; case SEQ_COL_LOG: - coldef = makeColumnDef("log_cnt", INT8OID, -1, InvalidOid); + coldef = makeColumnDef("log_cnt", INT8OID, -1, + InvalidOid, 0); value[i - 1] = Int64GetDatum((int64) 0); break; case SEQ_COL_CALLED: - coldef = makeColumnDef("is_called", BOOLOID, -1, InvalidOid); + coldef = makeColumnDef("is_called", BOOLOID, -1, + InvalidOid, 0); value[i - 1] = BoolGetDatum(false); break; } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index d2420a9558..111d96b896 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -2741,7 +2741,9 @@ MergeAttributes(List *columns, const List *supers, char relpersistence, * Create new column definition */ newdef = makeColumnDef(attributeName, attribute->atttypid, - attribute->atttypmod, attribute->attcollation); + attribute->atttypmod, + attribute->attcollation, + attribute->attndims); newdef->storage = attribute->attstorage; newdef->generated = attribute->attgenerated; if (CompressionMethodIsValid(attribute->attcompression)) diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c index 6f0301555e..cd0919a935 100644 --- a/src/backend/commands/view.c +++ b/src/backend/commands/view.c @@ -64,7 +64,8 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace, ColumnDef *def = makeColumnDef(tle->resname, exprType((Node *) tle->expr), exprTypmod((Node *) tle->expr), - exprCollation((Node *) tle->expr)); + exprCollation((Node *) tle->expr), + -1 /* detect array-ness */ ); /* * It's possible that the column is of a collatable type but the diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index 007612563c..aad0e78e3d 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -512,15 +512,29 @@ makeTypeNameFromOid(Oid typeOid, int32 typmod) * build a ColumnDef node to represent a simple column definition. * * Type and collation are specified by OID. + * Typmod must be given in numeric form. + * + * ndims can be positive to select that number of array dimensions, + * or 0 if it's not an array, or -1 for this function to detect whether + * it's an array type. (In that case we will declare the column as having a + * single array dimension. This might not accurately reproduce the source of, + * say, CREATE TABLE AS; but we don't have the information to do better.) + * * Other properties are all basic to start with. */ ColumnDef * -makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid) +makeColumnDef(const char *colname, Oid typeOid, int32 typmod, + Oid collOid, int ndims) { ColumnDef *n = makeNode(ColumnDef); n->colname = pstrdup(colname); n->typeName = makeTypeNameFromOid(typeOid, typmod); + if (ndims < 0) + ndims = OidIsValid(get_element_type(typeOid)) ? 1 : 0; + while (ndims-- > 0) + n->typeName->arrayBounds = lappend(n->typeName->arrayBounds, + makeInteger(-1)); n->inhcount = 0; n->is_local = true; n->is_not_null = false; diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index ca028d2a66..d03bc06f3e 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1198,7 +1198,8 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla * Create a new column definition */ def = makeColumnDef(NameStr(attribute->attname), attribute->atttypid, - attribute->atttypmod, attribute->attcollation); + attribute->atttypmod, attribute->attcollation, + attribute->attndims); /* * Add to column list @@ -1637,7 +1638,8 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename) continue; n = makeColumnDef(NameStr(attr->attname), attr->atttypid, - attr->atttypmod, attr->attcollation); + attr->atttypmod, attr->attcollation, + attr->attndims); n->is_from_type = true; cxt->columns = lappend(cxt->columns, n); diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h index 5473ce9a28..3747805f69 100644 --- a/src/include/nodes/makefuncs.h +++ b/src/include/nodes/makefuncs.h @@ -75,7 +75,8 @@ extern TypeName *makeTypeNameFromNameList(List *names); extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod); extern ColumnDef *makeColumnDef(const char *colname, - Oid typeOid, int32 typmod, Oid collOid); + Oid typeOid, int32 typmod, Oid collOid, + int ndims); extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype, List *args, Oid funccollid, Oid inputcollid, CoercionForm fformat);