From 53e18987a274b262ee0ef764469d70be3074a081 Mon Sep 17 00:00:00 2001 From: jian he Date: Mon, 5 Oct 2026 13:34:06 +0800 Subject: [PATCH v2 1/2] refactor check_for_invalid_global_names and pgindent --- src/bin/pg_dump/pg_dumpall.c | 110 ++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c index d1714cb7447..f1152f46a42 100644 --- a/src/bin/pg_dump/pg_dumpall.c +++ b/src/bin/pg_dump/pg_dumpall.c @@ -776,12 +776,12 @@ main(int argc, char *argv[]) if (!data_only && !statistics_only && !no_schema) { /* - * For plain-text output with --clean, print the Drop - * databases/Drop tablespaces/Drop roles sections first, ahead of - * any creates (see dropDBsText() for why the order matters). For - * non-plain formats, dumpRoles()/dumpTablespaces()/dumpDatabases() - * instead attach a drop statement to each archive entry, and the - * archiver decides at restore time whether to use it. + * For plain-text output with --clean, print the Drop databases/Drop + * tablespaces/Drop roles sections first, ahead of any creates (see + * dropDBsText() for why the order matters). For non-plain formats, + * dumpRoles()/dumpTablespaces()/dumpDatabases() instead attach a drop + * statement to each archive entry, and the archiver decides at + * restore time whether to use it. * * For non-text formats, pg_dumpall unconditionally process --clean * option. In contrast, pg_restore only applies it if the user @@ -1762,7 +1762,7 @@ dumpTablespaces(PGconn *conn) ArchiveEntry(fout, nilCatalogId, /* catalog ID */ - spcDumpId, /* dump ID */ + spcDumpId, /* dump ID */ ARCHIVE_OPTS(.tag = tag, .description = "TABLESPACE", .section = SECTION_PRE_DATA, @@ -2231,58 +2231,62 @@ static void check_for_invalid_global_names(PGconn *conn, SimpleStringList *excluded_names) { + PQExpBuffer query = createPQExpBuffer(); + PQExpBuffer escaped; PGresult *res; - int i; - PQExpBuffer names; - int count = 0; - - res = executeQuery(conn, - "SELECT datname AS objname, 'database' AS objtype " - "FROM pg_catalog.pg_database " - "WHERE datallowconn AND datconnlimit != -2 " - "UNION ALL " - "SELECT rolname AS objname, 'role' AS objtype " - "FROM pg_catalog.pg_roles " - "UNION ALL " - "SELECT spcname AS objname, 'tablespace' AS objtype " - "FROM pg_catalog.pg_tablespace"); - - names = createPQExpBuffer(); - - for (i = 0; i < PQntuples(res); i++) + char *objname; + char *objtype; + + appendPQExpBufferStr(query, + "(SELECT datname AS objname, 'database' AS objtype " + "FROM pg_catalog.pg_database " + "WHERE datallowconn AND datconnlimit != -2 " + "AND datname ~ E'[\\n\\r]'"); + + for (SimpleStringListCell *cell = excluded_names->head; cell; cell = cell->next) { - char *objname = PQgetvalue(res, i, 0); - char *objtype = PQgetvalue(res, i, 1); - - /* Skip excluded databases since they won't be in map.dat */ - if (strcmp(objtype, "database") == 0 && - simple_string_list_member(excluded_names, objname)) - continue; - - if (strpbrk(objname, "\n\r")) - { - appendPQExpBuffer(names, " %s: \"", objtype); - for (char *p = objname; *p; p++) - { - if (*p == '\n') - appendPQExpBufferStr(names, "\\n"); - else if (*p == '\r') - appendPQExpBufferStr(names, "\\r"); - else - appendPQExpBufferChar(names, *p); - } - appendPQExpBufferStr(names, "\"\n"); - count++; - } + appendPQExpBufferStr(query, " AND datname <> "); + appendStringLiteralConn(query, cell->val, conn); } - PQclear(res); + appendPQExpBufferStr(query, + " LIMIT 1) " + "UNION ALL " + "(SELECT rolname, 'role' " + "FROM pg_catalog.pg_roles " + "WHERE rolname ~ E'[\\n\\r]' LIMIT 1) " + "UNION ALL " + "(SELECT spcname, 'tablespace' " + "FROM pg_catalog.pg_tablespace " + "WHERE spcname ~ E'[\\n\\r]' LIMIT 1) " + "LIMIT 1"); + + res = executeQuery(conn, query->data); + destroyPQExpBuffer(query); + + if (PQntuples(res) == 0) + { + PQclear(res); + return; + } - if (count > 0) - pg_fatal("database, role, or tablespace names contain a newline or carriage return character, which is not supported in non-plain-text dumps:\n%s", - names->data); + objname = PQgetvalue(res, 0, 0); + objtype = PQgetvalue(res, 0, 1); + + /* Show newline and carriage return as \n and \r */ + escaped = createPQExpBuffer(); + for (char *p = objname; *p; p++) + { + if (*p == '\n') + appendPQExpBufferStr(escaped, "\\n"); + else if (*p == '\r') + appendPQExpBufferStr(escaped, "\\r"); + else + appendPQExpBufferChar(escaped, *p); + } - destroyPQExpBuffer(names); + pg_fatal("%s name \"%s\" contains a newline or carriage return character, which is not supported in non-plain-text dumps", + objtype, escaped->data); } -- 2.34.1