Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit175e60a

Browse files
committed
Fix pg_upgrade to detect non-upgradable anyarray usages.
When we changed some built-in functions to use anycompatiblearrayinstead of anyarray, we created a dump/restore hazard for user-definedoperators and aggregates relying on those functions: the user objectshave to be modified to change their signatures similarly. This causespg_upgrade to fail partway through if the source installation containssuch objects. We generally try to have pg_upgrade detect such hazardsand fail before it does anything exciting, so add logic to detectthis case too.Back-patch to v14 where the change was made.Justin Pryzby, reviewed by Andrey BorodinDiscussion:https://postgr.es/m/3383880.QJadu78ljV@vejsadalnx
1 parent7c1f426 commit175e60a

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

‎src/bin/pg_upgrade/check.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ static void check_proper_datallowconn(ClusterInfo *cluster);
2323
staticvoidcheck_for_prepared_transactions(ClusterInfo*cluster);
2424
staticvoidcheck_for_isn_and_int8_passing_mismatch(ClusterInfo*cluster);
2525
staticvoidcheck_for_user_defined_postfix_ops(ClusterInfo*cluster);
26+
staticvoidcheck_for_incompatible_polymorphics(ClusterInfo*cluster);
2627
staticvoidcheck_for_tables_with_oids(ClusterInfo*cluster);
2728
staticvoidcheck_for_composite_data_type_usage(ClusterInfo*cluster);
2829
staticvoidcheck_for_reg_data_type_usage(ClusterInfo*cluster);
@@ -121,6 +122,13 @@ check_and_dump_old_cluster(bool live_check)
121122
if (GET_MAJOR_VERSION(old_cluster.major_version) <=1300)
122123
check_for_user_defined_postfix_ops(&old_cluster);
123124

125+
/*
126+
* PG 14 changed polymorphic functions from anyarray to
127+
* anycompatiblearray.
128+
*/
129+
if (GET_MAJOR_VERSION(old_cluster.major_version) <=1300)
130+
check_for_incompatible_polymorphics(&old_cluster);
131+
124132
/*
125133
* Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
126134
* supported anymore. Verify there are none, iff applicable.
@@ -970,6 +978,132 @@ check_for_user_defined_postfix_ops(ClusterInfo *cluster)
970978
check_ok();
971979
}
972980

981+
/*
982+
*check_for_incompatible_polymorphics()
983+
*
984+
*Make sure nothing is using old polymorphic functions with
985+
*anyarray/anyelement rather than the new anycompatible variants.
986+
*/
987+
staticvoid
988+
check_for_incompatible_polymorphics(ClusterInfo*cluster)
989+
{
990+
PGresult*res;
991+
FILE*script=NULL;
992+
charoutput_path[MAXPGPATH];
993+
PQExpBufferDataold_polymorphics;
994+
995+
prep_status("Checking for incompatible polymorphic functions");
996+
997+
snprintf(output_path,sizeof(output_path),
998+
"incompatible_polymorphics.txt");
999+
1000+
/* The set of problematic functions varies a bit in different versions */
1001+
initPQExpBuffer(&old_polymorphics);
1002+
1003+
appendPQExpBufferStr(&old_polymorphics,
1004+
"'array_append(anyarray,anyelement)'"
1005+
", 'array_cat(anyarray,anyarray)'"
1006+
", 'array_prepend(anyelement,anyarray)'");
1007+
1008+
if (GET_MAJOR_VERSION(cluster->major_version) >=903)
1009+
appendPQExpBufferStr(&old_polymorphics,
1010+
", 'array_remove(anyarray,anyelement)'"
1011+
", 'array_replace(anyarray,anyelement,anyelement)'");
1012+
1013+
if (GET_MAJOR_VERSION(cluster->major_version) >=905)
1014+
appendPQExpBufferStr(&old_polymorphics,
1015+
", 'array_position(anyarray,anyelement)'"
1016+
", 'array_position(anyarray,anyelement,integer)'"
1017+
", 'array_positions(anyarray,anyelement)'"
1018+
", 'width_bucket(anyelement,anyarray)'");
1019+
1020+
for (intdbnum=0;dbnum<cluster->dbarr.ndbs;dbnum++)
1021+
{
1022+
booldb_used= false;
1023+
DbInfo*active_db=&cluster->dbarr.dbs[dbnum];
1024+
PGconn*conn=connectToServer(cluster,active_db->db_name);
1025+
intntups;
1026+
inti_objkind,
1027+
i_objname;
1028+
1029+
/*
1030+
* The query below hardcodes FirstNormalObjectId as 16384 rather than
1031+
* interpolating that C #define into the query because, if that
1032+
* #define is ever changed, the cutoff we want to use is the value
1033+
* used by pre-version 14 servers, not that of some future version.
1034+
*/
1035+
res=executeQueryOrDie(conn,
1036+
/* Aggregate transition functions */
1037+
"SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1038+
"FROM pg_proc AS p "
1039+
"JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1040+
"JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1041+
"WHERE p.oid >= 16384 "
1042+
"AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1043+
1044+
/* Aggregate final functions */
1045+
"UNION ALL "
1046+
"SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1047+
"FROM pg_proc AS p "
1048+
"JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1049+
"JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1050+
"WHERE p.oid >= 16384 "
1051+
"AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1052+
1053+
/* Operators */
1054+
"UNION ALL "
1055+
"SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1056+
"FROM pg_operator AS op "
1057+
"WHERE op.oid >= 16384 "
1058+
"AND oprcode = ANY(ARRAY[%s]::regprocedure[]);",
1059+
old_polymorphics.data,
1060+
old_polymorphics.data,
1061+
old_polymorphics.data);
1062+
1063+
ntups=PQntuples(res);
1064+
1065+
i_objkind=PQfnumber(res,"objkind");
1066+
i_objname=PQfnumber(res,"objname");
1067+
1068+
for (introwno=0;rowno<ntups;rowno++)
1069+
{
1070+
if (script==NULL&&
1071+
(script=fopen_priv(output_path,"w"))==NULL)
1072+
pg_fatal("could not open file \"%s\": %s\n",
1073+
output_path,strerror(errno));
1074+
if (!db_used)
1075+
{
1076+
fprintf(script,"In database: %s\n",active_db->db_name);
1077+
db_used= true;
1078+
}
1079+
1080+
fprintf(script," %s: %s\n",
1081+
PQgetvalue(res,rowno,i_objkind),
1082+
PQgetvalue(res,rowno,i_objname));
1083+
}
1084+
1085+
PQclear(res);
1086+
PQfinish(conn);
1087+
}
1088+
1089+
if (script)
1090+
{
1091+
fclose(script);
1092+
pg_log(PG_REPORT,"fatal\n");
1093+
pg_fatal("Your installation contains user-defined objects that refer to internal\n"
1094+
"polymorphic functions with arguments of type 'anyarray' or 'anyelement'.\n"
1095+
"These user-defined objects must be dropped before upgrading and restored\n"
1096+
"afterwards, changing them to refer to the new corresponding functions with\n"
1097+
"arguments of type 'anycompatiblearray' and 'anycompatible'.\n"
1098+
"A list of the problematic objects is in the file:\n"
1099+
" %s\n\n",output_path);
1100+
}
1101+
else
1102+
check_ok();
1103+
1104+
termPQExpBuffer(&old_polymorphics);
1105+
}
1106+
9731107
/*
9741108
* Verify that no tables are declared WITH OIDS.
9751109
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp