@@ -445,11 +445,14 @@ heap_create(const char *relname,
445
445
* this is used to make certain the tuple descriptor contains a
446
446
* valid set of attribute names and datatypes. a problem simply
447
447
* generates ereport(ERROR) which aborts the current transaction.
448
+ *
449
+ * relkind is the relkind of the relation to be created.
450
+ * flags controls which datatypes are allowed, cf CheckAttributeType.
448
451
* --------------------------------
449
452
*/
450
453
void
451
454
CheckAttributeNamesTypes (TupleDesc tupdesc , char relkind ,
452
- bool allow_system_table_mods )
455
+ int flags )
453
456
{
454
457
int i ;
455
458
int j ;
@@ -507,7 +510,7 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
507
510
TupleDescAttr (tupdesc , i )-> atttypid ,
508
511
TupleDescAttr (tupdesc , i )-> attcollation ,
509
512
NIL , /* assume we're creating a new rowtype */
510
- allow_system_table_mods );
513
+ flags );
511
514
}
512
515
}
513
516
@@ -524,26 +527,41 @@ CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind,
524
527
* containing_rowtypes. When checking a to-be-created rowtype, it's
525
528
* sufficient to pass NIL, because there could not be any recursive reference
526
529
* to a not-yet-existing rowtype.
530
+ *
531
+ * flags is a bitmask controlling which datatypes we allow. For the most
532
+ * part, pseudo-types are disallowed as attribute types, but there are some
533
+ * exceptions: ANYARRAYOID, RECORDOID, and RECORDARRAYOID can be allowed
534
+ * in some cases. (This works because values of those type classes are
535
+ * self-identifying to some extent. However, RECORDOID and RECORDARRAYOID
536
+ * are reliably identifiable only within a session, since the identity info
537
+ * may use a typmod that is only locally assigned. The caller is expected
538
+ * to know whether these cases are safe.)
527
539
* --------------------------------
528
540
*/
529
541
void
530
542
CheckAttributeType (const char * attname ,
531
543
Oid atttypid , Oid attcollation ,
532
544
List * containing_rowtypes ,
533
- bool allow_system_table_mods )
545
+ int flags )
534
546
{
535
547
char att_typtype = get_typtype (atttypid );
536
548
Oid att_typelem ;
537
549
538
550
if (att_typtype == TYPTYPE_PSEUDO )
539
551
{
540
552
/*
541
- * Refuse any attempt to create a pseudo-type column, except for a
542
- * special hack for pg_statistic: allow ANYARRAY when modifying system
543
- * catalogs (this allows creating pg_statistic and cloning it during
544
- * VACUUM FULL)
553
+ * We disallow pseudo-type columns, with the exception of ANYARRAY,
554
+ * RECORD, and RECORD[] when the caller says that those are OK.
555
+ *
556
+ * We don't need to worry about recursive containment for RECORD and
557
+ * RECORD[] because (a) no named composite type should be allowed to
558
+ * contain those, and (b) two "anonymous" record types couldn't be
559
+ * considered to be the same type, so infinite recursion isn't
560
+ * possible.
545
561
*/
546
- if (atttypid != ANYARRAYOID || !allow_system_table_mods )
562
+ if (!((atttypid == ANYARRAYOID && (flags & CHKATYPE_ANYARRAY )) ||
563
+ (atttypid == RECORDOID && (flags & CHKATYPE_ANYRECORD )) ||
564
+ (atttypid == RECORDARRAYOID && (flags & CHKATYPE_ANYRECORD ))))
547
565
ereport (ERROR ,
548
566
(errcode (ERRCODE_INVALID_TABLE_DEFINITION ),
549
567
errmsg ("column \"%s\" has pseudo-type %s" ,
@@ -556,7 +574,7 @@ CheckAttributeType(const char *attname,
556
574
*/
557
575
CheckAttributeType (attname , getBaseType (atttypid ), attcollation ,
558
576
containing_rowtypes ,
559
- allow_system_table_mods );
577
+ flags );
560
578
}
561
579
else if (att_typtype == TYPTYPE_COMPOSITE )
562
580
{
@@ -594,7 +612,7 @@ CheckAttributeType(const char *attname,
594
612
CheckAttributeType (NameStr (attr -> attname ),
595
613
attr -> atttypid , attr -> attcollation ,
596
614
containing_rowtypes ,
597
- allow_system_table_mods );
615
+ flags );
598
616
}
599
617
600
618
relation_close (relation , AccessShareLock );
@@ -608,7 +626,7 @@ CheckAttributeType(const char *attname,
608
626
*/
609
627
CheckAttributeType (attname , att_typelem , attcollation ,
610
628
containing_rowtypes ,
611
- allow_system_table_mods );
629
+ flags );
612
630
}
613
631
614
632
/*
@@ -1074,7 +1092,13 @@ heap_create_with_catalog(const char *relname,
1074
1092
*/
1075
1093
Assert (IsNormalProcessingMode () || IsBootstrapProcessingMode ());
1076
1094
1077
- CheckAttributeNamesTypes (tupdesc , relkind , allow_system_table_mods );
1095
+ /*
1096
+ * Validate proposed tupdesc for the desired relkind. If
1097
+ * allow_system_table_mods is on, allow ANYARRAY to be used; this is a
1098
+ * hack to allow creating pg_statistic and cloning it during VACUUM FULL.
1099
+ */
1100
+ CheckAttributeNamesTypes (tupdesc , relkind ,
1101
+ allow_system_table_mods ? CHKATYPE_ANYARRAY : 0 );
1078
1102
1079
1103
/*
1080
1104
* This would fail later on anyway, if the relation already exists. But
0 commit comments