@@ -24,6 +24,7 @@ static void check_proper_datallowconn(ClusterInfo *cluster);
24
24
static void check_for_prepared_transactions (ClusterInfo * cluster );
25
25
static void check_for_isn_and_int8_passing_mismatch (ClusterInfo * cluster );
26
26
static void check_for_user_defined_postfix_ops (ClusterInfo * cluster );
27
+ static void check_for_incompatible_polymorphics (ClusterInfo * cluster );
27
28
static void check_for_tables_with_oids (ClusterInfo * cluster );
28
29
static void check_for_composite_data_type_usage (ClusterInfo * cluster );
29
30
static void check_for_reg_data_type_usage (ClusterInfo * cluster );
@@ -122,6 +123,13 @@ check_and_dump_old_cluster(bool live_check)
122
123
if (GET_MAJOR_VERSION (old_cluster .major_version ) <= 1300 )
123
124
check_for_user_defined_postfix_ops (& old_cluster );
124
125
126
+ /*
127
+ * PG 14 changed polymorphic functions from anyarray to
128
+ * anycompatiblearray.
129
+ */
130
+ if (GET_MAJOR_VERSION (old_cluster .major_version ) <= 1300 )
131
+ check_for_incompatible_polymorphics (& old_cluster );
132
+
125
133
/*
126
134
* Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
127
135
* supported anymore. Verify there are none, iff applicable.
@@ -999,6 +1007,133 @@ check_for_user_defined_postfix_ops(ClusterInfo *cluster)
999
1007
check_ok ();
1000
1008
}
1001
1009
1010
+ /*
1011
+ * check_for_incompatible_polymorphics()
1012
+ *
1013
+ * Make sure nothing is using old polymorphic functions with
1014
+ * anyarray/anyelement rather than the new anycompatible variants.
1015
+ */
1016
+ static void
1017
+ check_for_incompatible_polymorphics (ClusterInfo * cluster )
1018
+ {
1019
+ PGresult * res ;
1020
+ FILE * script = NULL ;
1021
+ char output_path [MAXPGPATH ];
1022
+ PQExpBufferData old_polymorphics ;
1023
+
1024
+ prep_status ("Checking for incompatible polymorphic functions" );
1025
+
1026
+ snprintf (output_path , sizeof (output_path ), "%s/%s" ,
1027
+ log_opts .basedir ,
1028
+ "incompatible_polymorphics.txt" );
1029
+
1030
+ /* The set of problematic functions varies a bit in different versions */
1031
+ initPQExpBuffer (& old_polymorphics );
1032
+
1033
+ appendPQExpBufferStr (& old_polymorphics ,
1034
+ "'array_append(anyarray,anyelement)'"
1035
+ ", 'array_cat(anyarray,anyarray)'"
1036
+ ", 'array_prepend(anyelement,anyarray)'" );
1037
+
1038
+ if (GET_MAJOR_VERSION (cluster -> major_version ) >= 903 )
1039
+ appendPQExpBufferStr (& old_polymorphics ,
1040
+ ", 'array_remove(anyarray,anyelement)'"
1041
+ ", 'array_replace(anyarray,anyelement,anyelement)'" );
1042
+
1043
+ if (GET_MAJOR_VERSION (cluster -> major_version ) >= 905 )
1044
+ appendPQExpBufferStr (& old_polymorphics ,
1045
+ ", 'array_position(anyarray,anyelement)'"
1046
+ ", 'array_position(anyarray,anyelement,integer)'"
1047
+ ", 'array_positions(anyarray,anyelement)'"
1048
+ ", 'width_bucket(anyelement,anyarray)'" );
1049
+
1050
+ for (int dbnum = 0 ; dbnum < cluster -> dbarr .ndbs ; dbnum ++ )
1051
+ {
1052
+ bool db_used = false;
1053
+ DbInfo * active_db = & cluster -> dbarr .dbs [dbnum ];
1054
+ PGconn * conn = connectToServer (cluster , active_db -> db_name );
1055
+ int ntups ;
1056
+ int i_objkind ,
1057
+ i_objname ;
1058
+
1059
+ /*
1060
+ * The query below hardcodes FirstNormalObjectId as 16384 rather than
1061
+ * interpolating that C #define into the query because, if that
1062
+ * #define is ever changed, the cutoff we want to use is the value
1063
+ * used by pre-version 14 servers, not that of some future version.
1064
+ */
1065
+ res = executeQueryOrDie (conn ,
1066
+ /* Aggregate transition functions */
1067
+ "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1068
+ "FROM pg_proc AS p "
1069
+ "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1070
+ "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1071
+ "WHERE p.oid >= 16384 "
1072
+ "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1073
+
1074
+ /* Aggregate final functions */
1075
+ "UNION ALL "
1076
+ "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1077
+ "FROM pg_proc AS p "
1078
+ "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1079
+ "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1080
+ "WHERE p.oid >= 16384 "
1081
+ "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1082
+
1083
+ /* Operators */
1084
+ "UNION ALL "
1085
+ "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1086
+ "FROM pg_operator AS op "
1087
+ "WHERE op.oid >= 16384 "
1088
+ "AND oprcode = ANY(ARRAY[%s]::regprocedure[]);" ,
1089
+ old_polymorphics .data ,
1090
+ old_polymorphics .data ,
1091
+ old_polymorphics .data );
1092
+
1093
+ ntups = PQntuples (res );
1094
+
1095
+ i_objkind = PQfnumber (res , "objkind" );
1096
+ i_objname = PQfnumber (res , "objname" );
1097
+
1098
+ for (int rowno = 0 ; rowno < ntups ; rowno ++ )
1099
+ {
1100
+ if (script == NULL &&
1101
+ (script = fopen_priv (output_path , "w" )) == NULL )
1102
+ pg_fatal ("could not open file \"%s\": %s\n" ,
1103
+ output_path , strerror (errno ));
1104
+ if (!db_used )
1105
+ {
1106
+ fprintf (script , "In database: %s\n" , active_db -> db_name );
1107
+ db_used = true;
1108
+ }
1109
+
1110
+ fprintf (script , " %s: %s\n" ,
1111
+ PQgetvalue (res , rowno , i_objkind ),
1112
+ PQgetvalue (res , rowno , i_objname ));
1113
+ }
1114
+
1115
+ PQclear (res );
1116
+ PQfinish (conn );
1117
+ }
1118
+
1119
+ if (script )
1120
+ {
1121
+ fclose (script );
1122
+ pg_log (PG_REPORT , "fatal\n" );
1123
+ pg_fatal ("Your installation contains user-defined objects that refer to internal\n"
1124
+ "polymorphic functions with arguments of type 'anyarray' or 'anyelement'.\n"
1125
+ "These user-defined objects must be dropped before upgrading and restored\n"
1126
+ "afterwards, changing them to refer to the new corresponding functions with\n"
1127
+ "arguments of type 'anycompatiblearray' and 'anycompatible'.\n"
1128
+ "A list of the problematic objects is in the file:\n"
1129
+ " %s\n\n" , output_path );
1130
+ }
1131
+ else
1132
+ check_ok ();
1133
+
1134
+ termPQExpBuffer (& old_polymorphics );
1135
+ }
1136
+
1002
1137
/*
1003
1138
* Verify that no tables are declared WITH OIDS.
1004
1139
*/
0 commit comments