@@ -1413,6 +1413,40 @@ check_for_user_defined_postfix_ops(ClusterInfo *cluster)
1413
1413
check_ok ();
1414
1414
}
1415
1415
1416
+ /*
1417
+ * Callback function for processing results of query for
1418
+ * check_for_incompatible_polymorphics()'s UpgradeTask. If the query returned
1419
+ * any rows (i.e., the check failed), write the details to the report file.
1420
+ */
1421
+ static void
1422
+ process_incompat_polymorphics (DbInfo * dbinfo , PGresult * res , void * arg )
1423
+ {
1424
+ UpgradeTaskReport * report = (UpgradeTaskReport * ) arg ;
1425
+ bool db_used = false;
1426
+ int ntups = PQntuples (res );
1427
+ int i_objkind = PQfnumber (res , "objkind" );
1428
+ int i_objname = PQfnumber (res , "objname" );
1429
+
1430
+ AssertVariableIsOfType (& process_incompat_polymorphics ,
1431
+ UpgradeTaskProcessCB );
1432
+
1433
+ for (int rowno = 0 ; rowno < ntups ; rowno ++ )
1434
+ {
1435
+ if (report -> file == NULL &&
1436
+ (report -> file = fopen_priv (report -> path , "w" )) == NULL )
1437
+ pg_fatal ("could not open file \"%s\": %m" , report -> path );
1438
+ if (!db_used )
1439
+ {
1440
+ fprintf (report -> file , "In database: %s\n" , dbinfo -> db_name );
1441
+ db_used = true;
1442
+ }
1443
+
1444
+ fprintf (report -> file , " %s: %s\n" ,
1445
+ PQgetvalue (res , rowno , i_objkind ),
1446
+ PQgetvalue (res , rowno , i_objname ));
1447
+ }
1448
+ }
1449
+
1416
1450
/*
1417
1451
* check_for_incompatible_polymorphics()
1418
1452
*
@@ -1422,14 +1456,15 @@ check_for_user_defined_postfix_ops(ClusterInfo *cluster)
1422
1456
static void
1423
1457
check_for_incompatible_polymorphics (ClusterInfo * cluster )
1424
1458
{
1425
- PGresult * res ;
1426
- FILE * script = NULL ;
1427
- char output_path [MAXPGPATH ];
1428
1459
PQExpBufferData old_polymorphics ;
1460
+ UpgradeTask * task = upgrade_task_create ();
1461
+ UpgradeTaskReport report ;
1462
+ char * query ;
1429
1463
1430
1464
prep_status ("Checking for incompatible polymorphic functions" );
1431
1465
1432
- snprintf (output_path , sizeof (output_path ), "%s/%s" ,
1466
+ report .file = NULL ;
1467
+ snprintf (report .path , sizeof (report .path ), "%s/%s" ,
1433
1468
log_opts .basedir ,
1434
1469
"incompatible_polymorphics.txt" );
1435
1470
@@ -1453,93 +1488,65 @@ check_for_incompatible_polymorphics(ClusterInfo *cluster)
1453
1488
", 'array_positions(anyarray,anyelement)'"
1454
1489
", 'width_bucket(anyelement,anyarray)'" );
1455
1490
1456
- for (int dbnum = 0 ; dbnum < cluster -> dbarr .ndbs ; dbnum ++ )
1457
- {
1458
- bool db_used = false;
1459
- DbInfo * active_db = & cluster -> dbarr .dbs [dbnum ];
1460
- PGconn * conn = connectToServer (cluster , active_db -> db_name );
1461
- int ntups ;
1462
- int i_objkind ,
1463
- i_objname ;
1464
-
1465
- /*
1466
- * The query below hardcodes FirstNormalObjectId as 16384 rather than
1467
- * interpolating that C #define into the query because, if that
1468
- * #define is ever changed, the cutoff we want to use is the value
1469
- * used by pre-version 14 servers, not that of some future version.
1470
- */
1471
- res = executeQueryOrDie (conn ,
1472
- /* Aggregate transition functions */
1473
- "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1474
- "FROM pg_proc AS p "
1475
- "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1476
- "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1477
- "WHERE p.oid >= 16384 "
1478
- "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1479
- "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1480
-
1481
- /* Aggregate final functions */
1482
- "UNION ALL "
1483
- "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1484
- "FROM pg_proc AS p "
1485
- "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1486
- "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1487
- "WHERE p.oid >= 16384 "
1488
- "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1489
- "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1490
-
1491
- /* Operators */
1492
- "UNION ALL "
1493
- "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1494
- "FROM pg_operator AS op "
1495
- "WHERE op.oid >= 16384 "
1496
- "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
1497
- "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[]);" ,
1498
- old_polymorphics .data ,
1499
- old_polymorphics .data ,
1500
- old_polymorphics .data );
1501
-
1502
- ntups = PQntuples (res );
1503
-
1504
- i_objkind = PQfnumber (res , "objkind" );
1505
- i_objname = PQfnumber (res , "objname" );
1506
-
1507
- for (int rowno = 0 ; rowno < ntups ; rowno ++ )
1508
- {
1509
- if (script == NULL &&
1510
- (script = fopen_priv (output_path , "w" )) == NULL )
1511
- pg_fatal ("could not open file \"%s\": %m" , output_path );
1512
- if (!db_used )
1513
- {
1514
- fprintf (script , "In database: %s\n" , active_db -> db_name );
1515
- db_used = true;
1516
- }
1517
-
1518
- fprintf (script , " %s: %s\n" ,
1519
- PQgetvalue (res , rowno , i_objkind ),
1520
- PQgetvalue (res , rowno , i_objname ));
1521
- }
1491
+ /*
1492
+ * The query below hardcodes FirstNormalObjectId as 16384 rather than
1493
+ * interpolating that C #define into the query because, if that #define is
1494
+ * ever changed, the cutoff we want to use is the value used by
1495
+ * pre-version 14 servers, not that of some future version.
1496
+ */
1522
1497
1523
- PQclear (res );
1524
- PQfinish (conn );
1525
- }
1498
+ /* Aggregate transition functions */
1499
+ query = psprintf ("SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1500
+ "FROM pg_proc AS p "
1501
+ "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1502
+ "JOIN pg_proc AS transfn ON transfn.oid=a.aggtransfn "
1503
+ "WHERE p.oid >= 16384 "
1504
+ "AND a.aggtransfn = ANY(ARRAY[%s]::regprocedure[]) "
1505
+ "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1506
+
1507
+ /* Aggregate final functions */
1508
+ "UNION ALL "
1509
+ "SELECT 'aggregate' AS objkind, p.oid::regprocedure::text AS objname "
1510
+ "FROM pg_proc AS p "
1511
+ "JOIN pg_aggregate AS a ON a.aggfnoid=p.oid "
1512
+ "JOIN pg_proc AS finalfn ON finalfn.oid=a.aggfinalfn "
1513
+ "WHERE p.oid >= 16384 "
1514
+ "AND a.aggfinalfn = ANY(ARRAY[%s]::regprocedure[]) "
1515
+ "AND a.aggtranstype = ANY(ARRAY['anyarray', 'anyelement']::regtype[]) "
1516
+
1517
+ /* Operators */
1518
+ "UNION ALL "
1519
+ "SELECT 'operator' AS objkind, op.oid::regoperator::text AS objname "
1520
+ "FROM pg_operator AS op "
1521
+ "WHERE op.oid >= 16384 "
1522
+ "AND oprcode = ANY(ARRAY[%s]::regprocedure[]) "
1523
+ "AND oprleft = ANY(ARRAY['anyarray', 'anyelement']::regtype[])" ,
1524
+ old_polymorphics .data ,
1525
+ old_polymorphics .data ,
1526
+ old_polymorphics .data );
1527
+
1528
+ upgrade_task_add_step (task , query , process_incompat_polymorphics ,
1529
+ true, & report );
1530
+ upgrade_task_run (task , cluster );
1531
+ upgrade_task_free (task );
1526
1532
1527
- if (script )
1533
+ if (report . file )
1528
1534
{
1529
- fclose (script );
1535
+ fclose (report . file );
1530
1536
pg_log (PG_REPORT , "fatal" );
1531
1537
pg_fatal ("Your installation contains user-defined objects that refer to internal\n"
1532
1538
"polymorphic functions with arguments of type \"anyarray\" or \"anyelement\".\n"
1533
1539
"These user-defined objects must be dropped before upgrading and restored\n"
1534
1540
"afterwards, changing them to refer to the new corresponding functions with\n"
1535
1541
"arguments of type \"anycompatiblearray\" and \"anycompatible\".\n"
1536
1542
"A list of the problematic objects is in the file:\n"
1537
- " %s" , output_path );
1543
+ " %s" , report . path );
1538
1544
}
1539
1545
else
1540
1546
check_ok ();
1541
1547
1542
1548
termPQExpBuffer (& old_polymorphics );
1549
+ pg_free (query );
1543
1550
}
1544
1551
1545
1552
/*
0 commit comments