13 #include "catalog/pg_class_d.h"
47 const char *old_pgdata,
const char *new_pgdata)
53 bool all_matched =
true;
64 old_relnum = new_relnum = 0;
65 while (old_relnum < old_db->rel_arr.nrels ||
66 new_relnum < new_db->rel_arr.nrels)
70 RelInfo *new_rel = (new_relnum < new_db->rel_arr.nrels) ?
93 if (strcmp(new_rel->nspname,
"pg_toast") != 0)
103 if (old_rel->
reloid < new_rel->reloid)
111 else if (old_rel->
reloid > new_rel->reloid)
114 if (strcmp(new_rel->nspname,
"pg_toast") != 0)
128 if (strcmp(old_rel->
nspname, new_rel->nspname) != 0 ||
129 strcmp(old_rel->
relname, new_rel->relname) != 0)
131 pg_log(
PG_WARNING,
"Relation names for OID %u in database \"%s\" do not match: "
132 "old name \"%s.%s\", new name \"%s.%s\"",
135 new_rel->nspname, new_rel->relname);
144 old_rel, new_rel,
maps + num_maps);
151 pg_fatal(
"Failed to match up old and new tables in database \"%s\"",
220 snprintf(reldesc,
sizeof(reldesc),
"\"%s.%s\"",
231 sizeof(reldesc) - strlen(reldesc),
232 _(
" which is an index on \"%s.%s\""),
241 sizeof(reldesc) - strlen(reldesc),
242 _(
" which is an index on OID %u"), rel->
indtable);
253 sizeof(reldesc) - strlen(reldesc),
254 _(
" which is the TOAST table for \"%s.%s\""),
261 sizeof(reldesc) - strlen(reldesc),
262 _(
" which is the TOAST table for OID %u"), rel->
toastheap);
266 pg_log(
PG_WARNING,
"No match found in old cluster for new relation with OID %u in database \"%s\": %s",
269 pg_log(
PG_WARNING,
"No match found in new cluster for old relation with OID %u in database \"%s\": %s",
283 char *rel_infos_query = NULL;
284 char *logical_slot_infos_query = NULL;
286 if (
cluster->dbarr.dbs != NULL)
312 logical_slot_infos_query,
321 if (logical_slot_infos_query)
322 pg_free(logical_slot_infos_query);
345 int i_datlocprovider;
352 "SELECT encoding, datlocprovider, "
353 " datcollate, datctype, datlocale "
354 "FROM pg_catalog.pg_database "
355 "WHERE datname='template0'");
358 "SELECT encoding, datlocprovider, "
359 " datcollate, datctype, daticulocale AS datlocale "
360 "FROM pg_catalog.pg_database "
361 "WHERE datname='template0'");
364 "SELECT encoding, 'c' AS datlocprovider, "
365 " datcollate, datctype, NULL AS datlocale "
366 "FROM pg_catalog.pg_database "
367 "WHERE datname='template0'");
375 i_datencoding =
PQfnumber(dbres,
"encoding");
376 i_datlocprovider =
PQfnumber(dbres,
"datlocprovider");
377 i_datcollate =
PQfnumber(dbres,
"datcollate");
378 i_datctype =
PQfnumber(dbres,
"datctype");
379 i_datlocale =
PQfnumber(dbres,
"datlocale");
417 "SELECT d.oid, d.datname, d.encoding, d.datcollate, d.datctype, ");
419 snprintf(query + strlen(query),
sizeof(query) - strlen(query),
420 "datlocprovider, datlocale, ");
422 snprintf(query + strlen(query),
sizeof(query) - strlen(query),
423 "datlocprovider, daticulocale AS datlocale, ");
425 snprintf(query + strlen(query),
sizeof(query) - strlen(query),
426 "'c' AS datlocprovider, NULL AS datlocale, ");
427 snprintf(query + strlen(query),
sizeof(query) - strlen(query),
428 "pg_catalog.pg_tablespace_location(t.oid) AS spclocation "
429 "FROM pg_catalog.pg_database d "
430 " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
431 " ON d.dattablespace = t.oid "
432 "WHERE d.datallowconn = true "
444 for (tupnum = 0; tupnum < ntups; tupnum++)
448 snprintf(dbinfos[tupnum].db_tablespace,
sizeof(dbinfos[tupnum].db_tablespace),
"%s",
488 "WITH regular_heap (reloid, indtable, toastheap) AS ( "
489 " SELECT c.oid, 0::oid, 0::oid "
490 " FROM pg_catalog.pg_class c JOIN pg_catalog.pg_namespace n "
491 " ON c.relnamespace = n.oid "
492 " WHERE relkind IN (" CppAsString2(RELKIND_RELATION)
", "
495 " ((n.nspname !~ '^pg_temp_' AND "
496 " n.nspname !~ '^pg_toast_temp_' AND "
497 " n.nspname NOT IN ('pg_catalog', 'information_schema', "
498 " 'binary_upgrade', 'pg_toast') AND "
499 " c.oid >= %u::pg_catalog.oid) OR "
500 " (n.nspname = 'pg_catalog' AND "
501 " relname IN ('pg_largeobject') ))), ",
510 " toast_heap (reloid, indtable, toastheap) AS ( "
511 " SELECT c.reltoastrelid, 0::oid, c.oid "
512 " FROM regular_heap JOIN pg_catalog.pg_class c "
513 " ON regular_heap.reloid = c.oid "
514 " WHERE c.reltoastrelid != 0), ");
523 " all_index (reloid, indtable, toastheap) AS ( "
524 " SELECT indexrelid, indrelid, 0::oid "
525 " FROM pg_catalog.pg_index "
526 " WHERE indisvalid AND indisready "
528 " (SELECT reloid FROM regular_heap "
530 " SELECT reloid FROM toast_heap)) ");
537 "SELECT all_rels.*, n.nspname, c.relname, "
538 " c.relfilenode, c.reltablespace, "
539 " pg_catalog.pg_tablespace_location(t.oid) AS spclocation "
540 "FROM (SELECT * FROM regular_heap "
542 " SELECT * FROM toast_heap "
544 " SELECT * FROM all_index) all_rels "
545 " JOIN pg_catalog.pg_class c "
546 " ON all_rels.reloid = c.oid "
547 " JOIN pg_catalog.pg_namespace n "
548 " ON c.relnamespace = n.oid "
549 " LEFT OUTER JOIN pg_catalog.pg_tablespace t "
550 " ON c.reltablespace = t.oid "
575 char *nspname = NULL;
578 char *last_namespace = NULL;
579 char *last_tablespace = NULL;
583 for (
int relnum = 0; relnum < ntups; relnum++)
585 RelInfo *curr = &relinfos[num_rels++];
600 if (last_namespace && strcmp(nspname, last_namespace) == 0)
601 curr->
nspname = last_namespace;
624 if (last_tablespace && strcmp(
tablespace, last_tablespace) == 0)
637 dbinfo->rel_arr.rels = relinfos;
638 dbinfo->rel_arr.nrels = num_rels;
669 return psprintf(
"SELECT slot_name, plugin, two_phase, failover, "
670 "%s as caught_up, invalidation_reason IS NOT NULL as invalid "
671 "FROM pg_catalog.pg_replication_slots "
672 "WHERE slot_type = 'logical' AND "
673 "database = current_database() AND "
674 "temporary IS FALSE;",
676 "(CASE WHEN invalidation_reason IS NOT NULL THEN FALSE "
677 "ELSE (SELECT pg_catalog.binary_upgrade_logical_slot_has_caught_up(slot_name)) "
714 for (
int slotnum = 0; slotnum < num_slots; slotnum++)
727 dbinfo->slot_arr.slots = slotinfos;
728 dbinfo->slot_arr.nslots = num_slots;
765 "FROM pg_catalog.pg_subscription");
777 for (dbnum = 0; dbnum < db_arr->
ndbs; dbnum++)
793 for (relnum = 0; relnum < rel_arr->
nrels; relnum++)
811 for (dbnum = 0; dbnum < db_arr->
ndbs; dbnum++)
827 for (relnum = 0; relnum < rel_arr->
nrels; relnum++)
839 if (slot_arr->
nslots == 0)
844 for (
int slotnum = 0; slotnum < slot_arr->
nslots; slotnum++)
848 pg_log(
PG_VERBOSE,
"slot name: \"%s\", output plugin: \"%s\", two_phase: %s",
851 slot_info->
two_phase ?
"true" :
"false");
#define AssertVariableIsOfType(varname, typename)
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
static void PGresult * res
void PQfinish(PGconn *conn)
int PQntuples(const PGresult *res)
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
int PQfnumber(const PGresult *res, const char *field_name)
int PQgetisnull(const PGresult *res, int tup_num, int field_num)
void * pg_malloc0(size_t size)
char * pg_strdup(const char *in)
void * pg_malloc(size_t size)
static void print_slot_infos(LogicalSlotInfoArr *slot_arr)
void get_subscription_count(ClusterInfo *cluster)
static void process_rel_infos(DbInfo *dbinfo, PGresult *res, void *arg)
static void get_template0_info(ClusterInfo *cluster)
static void report_unmatched_relation(const RelInfo *rel, const DbInfo *db, bool is_new_db)
static void get_db_infos(ClusterInfo *cluster)
static void free_rel_infos(RelInfoArr *rel_arr)
static void print_rel_infos(RelInfoArr *rel_arr)
static void create_rel_filename_map(const char *old_data, const char *new_data, const DbInfo *old_db, const DbInfo *new_db, const RelInfo *old_rel, const RelInfo *new_rel, FileNameMap *map)
FileNameMap * gen_db_file_maps(DbInfo *old_db, DbInfo *new_db, int *nmaps, const char *old_pgdata, const char *new_pgdata)
static void free_db_and_rel_infos(DbInfoArr *db_arr)
static char * get_rel_infos_query(void)
static void process_old_cluster_logical_slot_infos(DbInfo *dbinfo, PGresult *res, void *arg)
static void print_db_infos(DbInfoArr *db_arr)
static char * get_old_cluster_logical_slot_infos_query(void)
int count_old_cluster_logical_slots(void)
void get_db_rel_and_slot_infos(ClusterInfo *cluster)
static struct LogicalRepInfo * dbinfo
UpgradeTask * upgrade_task_create(void)
void upgrade_task_run(const UpgradeTask *task, const ClusterInfo *cluster)
void void pg_log(eLogType type, const char *fmt,...) pg_attribute_printf(2
void upgrade_task_free(UpgradeTask *task)
void(* UpgradeTaskProcessCB)(DbInfo *dbinfo, PGresult *res, void *arg)
PGconn * connectToServer(ClusterInfo *cluster, const char *db_name)
#define GET_MAJOR_VERSION(v)
void upgrade_task_add_step(UpgradeTask *task, const char *query, UpgradeTaskProcessCB process_cb, bool free_result, void *arg)
PGresult * executeQueryOrDie(PGconn *conn, const char *fmt,...) pg_attribute_printf(2
void initPQExpBuffer(PQExpBuffer str)
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
char * psprintf(const char *fmt,...)
const char * tablespace_suffix
LogicalSlotInfoArr slot_arr
const char * new_tablespace
const char * old_tablespace_suffix
const char * old_tablespace
RelFileNumber relfilenumber
const char * new_tablespace_suffix
RelFileNumber relfilenumber
#define FirstNormalObjectId
static const pg_conv_map maps[]