diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index e91920ca14..56ea7f4eca 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -185,9 +185,13 @@ create_ctas_nodata(List *tlist, IntoClause *into)
 			else
 				colname = tle->resname;
 
+			/*
+			 * Var doesn't have an ndims structure member, so we don't
+			 * have access to the original attndims, equals 0.
+			 */
 			col = makeColumnDef(colname,
 								exprType((Node *) tle->expr),
-								exprTypmod((Node *) tle->expr),
+								exprTypmod((Node *) tle->expr), 0,
 								exprCollation((Node *) tle->expr));
 
 			/*
@@ -494,9 +498,15 @@ intorel_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
 		else
 			colname = NameStr(attribute->attname);
 
+		/*
+		 * TupleDescData doesn't have an ndims structure member, so
+		 * we don't have access to the original attndims;
+		 * attribute->attndims equals 0.
+		 */
 		col = makeColumnDef(colname,
 							attribute->atttypid,
 							attribute->atttypmod,
+							attribute->attndims,
 							attribute->attcollation);
 
 		/*
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 47acdf5166..f497cfad46 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -177,15 +177,15 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
 		switch (i)
 		{
 			case SEQ_COL_LASTVAL:
-				coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid);
+				coldef = makeColumnDef("last_value", INT8OID, -1, 0, InvalidOid);
 				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, 0, InvalidOid);
 				value[i - 1] = Int64GetDatum((int64) 0);
 				break;
 			case SEQ_COL_CALLED:
-				coldef = makeColumnDef("is_called", BOOLOID, -1, InvalidOid);
+				coldef = makeColumnDef("is_called", BOOLOID, -1, 0, InvalidOid);
 				value[i - 1] = BoolGetDatum(false);
 				break;
 		}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 323d9bf870..99d406416d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -2845,7 +2845,8 @@ MergeAttributes(List *columns, const List *supers, char relpersistence,
 				 * No, create a new inherited column
 				 */
 				def = makeColumnDef(attributeName, attribute->atttypid,
-									attribute->atttypmod, attribute->attcollation);
+									attribute->atttypmod, attribute->attndims,
+									attribute->attcollation);
 				def->inhcount = 1;
 				def->is_local = false;
 				/* mark attnotnull if parent has it and it's not NO INHERIT */
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 9bd77546b9..f99b9e003f 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -69,7 +69,7 @@ DefineVirtualRelation(RangeVar *relation, List *tlist, bool replace,
 		{
 			ColumnDef  *def = makeColumnDef(tle->resname,
 											exprType((Node *) tle->expr),
-											exprTypmod((Node *) tle->expr),
+											exprTypmod((Node *) tle->expr), 0,
 											exprCollation((Node *) tle->expr));
 
 			/*
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index c6fb571982..32f819d84b 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -479,6 +479,24 @@ makeTypeNameFromOid(Oid typeOid, int32 typmod)
 	n->typeOid = typeOid;
 	n->typemod = typmod;
 	n->location = -1;
+
+	return n;
+}
+
+/*
+ * makeTypeNameFromOid -
+ *	build a TypeName node to represent a type already known by OID/typmod/ndims
+ */
+TypeName *
+makeTypeNameWithNdimsFromOid(Oid typeOid, int32 typmod, int16 ndims)
+{
+	int i;
+	TypeName   *n = makeTypeNameFromOid(typeOid, typmod);
+
+	n->arrayBounds = NIL;
+	for (i = 0; i < ndims; i++)
+		n->arrayBounds = lcons_int(-1, n->arrayBounds);
+
 	return n;
 }
 
@@ -490,12 +508,13 @@ makeTypeNameFromOid(Oid typeOid, int32 typmod)
  * 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, int16 ndims,
+			  Oid collOid)
 {
 	ColumnDef  *n = makeNode(ColumnDef);
 
 	n->colname = pstrdup(colname);
-	n->typeName = makeTypeNameFromOid(typeOid, typmod);
+	n->typeName = makeTypeNameWithNdimsFromOid(typeOid, typmod, ndims);
 	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 cf0d432ab1..43f3b358eb 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1078,7 +1078,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->attndims,
+							attribute->attcollation);
 
 		/*
 		 * For constraints, ONLY the not-null constraint is inherited by the
@@ -1615,7 +1616,8 @@ transformOfType(CreateStmtContext *cxt, TypeName *ofTypename)
 			continue;
 
 		n = makeColumnDef(NameStr(attr->attname), attr->atttypid,
-						  attr->atttypmod, attr->attcollation);
+						  attr->atttypmod, attr->attndims,
+						  attr->attcollation);
 		n->is_from_type = true;
 
 		cxt->columns = lappend(cxt->columns, n);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 34fd0a86e9..dd571e250b 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -8471,7 +8471,12 @@ getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
 						 "a.attlen,\n"
 						 "a.attalign,\n"
 						 "a.attislocal,\n"
-						 "pg_catalog.format_type(t.oid, a.atttypmod) AS atttypname,\n"
+						 "(pg_catalog.format_type(t.oid, a.atttypmod) || "
+						 /*
+						  * format_type() supplies one "[]" for arrays,
+						  * and we add if needed.
+						  */
+						 " repeat('[]', a.attndims - 1)) AS atttypname,\n"
 						 "array_to_string(a.attoptions, ', ') AS attoptions,\n"
 						 "CASE WHEN a.attcollation <> t.typcollation "
 						 "THEN a.attcollation ELSE 0 END AS attcollation,\n"
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 5077e7b358..9eda1d72a4 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -1848,7 +1848,8 @@ describeOneTableDetails(const char *schemaname,
 	cols = 0;
 	printfPQExpBuffer(&buf, "SELECT a.attname");
 	attname_col = cols++;
-	appendPQExpBufferStr(&buf, ",\n  pg_catalog.format_type(a.atttypid, a.atttypmod)");
+	/* format_type() supplies one "[]" for arrays, and we add if needed. */
+	appendPQExpBufferStr(&buf, ",\n  pg_catalog.format_type(a.atttypid, a.atttypmod) || repeat('[]', a.attndims - 1)");
 	atttype_col = cols++;
 
 	if (show_column_details)
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 3180703005..f723edb38d 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -72,9 +72,10 @@ extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location);
 extern TypeName *makeTypeName(char *typnam);
 extern TypeName *makeTypeNameFromNameList(List *names);
 extern TypeName *makeTypeNameFromOid(Oid typeOid, int32 typmod);
+extern TypeName *makeTypeNameWithNdimsFromOid(Oid typeOid, int32 typmod, int16 ndims);
 
-extern ColumnDef *makeColumnDef(const char *colname,
-								Oid typeOid, int32 typmod, Oid collOid);
+extern ColumnDef *makeColumnDef(const char *colname, Oid typeOid,
+								int32 typmod, int16 ndims, Oid collOid);
 
 extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype, List *args,
 							  Oid funccollid, Oid inputcollid, CoercionForm fformat);
