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

Commit09878cd

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 parent8d9f963 commit09878cd

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

‎src/bin/pg_upgrade/check.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static void check_proper_datallowconn(ClusterInfo *cluster);
2424
staticvoidcheck_for_prepared_transactions(ClusterInfo*cluster);
2525
staticvoidcheck_for_isn_and_int8_passing_mismatch(ClusterInfo*cluster);
2626
staticvoidcheck_for_user_defined_postfix_ops(ClusterInfo*cluster);
27+
staticvoidcheck_for_incompatible_polymorphics(ClusterInfo*cluster);
2728
staticvoidcheck_for_tables_with_oids(ClusterInfo*cluster);
2829
staticvoidcheck_for_composite_data_type_usage(ClusterInfo*cluster);
2930
staticvoidcheck_for_reg_data_type_usage(ClusterInfo*cluster);
@@ -122,6 +123,13 @@ check_and_dump_old_cluster(bool live_check)
122123
if (GET_MAJOR_VERSION(old_cluster.major_version) <=1300)
123124
check_for_user_defined_postfix_ops(&old_cluster);
124125

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+
125133
/*
126134
* Pre-PG 12 allowed tables to be declared WITH OIDS, which is not
127135
* supported anymore. Verify there are none, iff applicable.
@@ -999,6 +1007,133 @@ check_for_user_defined_postfix_ops(ClusterInfo *cluster)
9991007
check_ok();
10001008
}
10011009

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+
staticvoid
1017+
check_for_incompatible_polymorphics(ClusterInfo*cluster)
1018+
{
1019+
PGresult*res;
1020+
FILE*script=NULL;
1021+
charoutput_path[MAXPGPATH];
1022+
PQExpBufferDataold_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 (intdbnum=0;dbnum<cluster->dbarr.ndbs;dbnum++)
1051+
{
1052+
booldb_used= false;
1053+
DbInfo*active_db=&cluster->dbarr.dbs[dbnum];
1054+
PGconn*conn=connectToServer(cluster,active_db->db_name);
1055+
intntups;
1056+
inti_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 (introwno=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+
10021137
/*
10031138
* Verify that no tables are declared WITH OIDS.
10041139
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp