5656#include "common/connect.h"
5757#include "common/int.h"
5858#include "common/relpath.h"
59+ #include "common/shortest_dec.h"
5960#include "compress_io.h"
6061#include "dumputils.h"
6162#include "fe_utils/option_utils.h"
@@ -524,6 +525,9 @@ main(int argc, char **argv)
524525pg_logging_set_level(PG_LOG_WARNING);
525526set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_dump"));
526527
528+ /* ensure that locale does not affect floating point interpretation */
529+ setlocale(LC_NUMERIC, "C");
530+
527531/*
528532 * Initialize what we need for parallel execution, especially for thread
529533 * support on Windows.
@@ -6814,7 +6818,8 @@ getFuncs(Archive *fout)
68146818 *
68156819 */
68166820static RelStatsInfo *
6817- getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
6821+ getRelationStatistics(Archive *fout, DumpableObject *rel, int32 relpages,
6822+ float reltuples, int32 relallvisible, char relkind)
68186823{
68196824if (!fout->dopt->dumpStatistics)
68206825return NULL;
@@ -6839,6 +6844,9 @@ getRelationStatistics(Archive *fout, DumpableObject *rel, char relkind)
68396844dobj->components |= DUMP_COMPONENT_STATISTICS;
68406845dobj->name = pg_strdup(rel->name);
68416846dobj->namespace = rel->namespace;
6847+ info->relpages = relpages;
6848+ info->reltuples = reltuples;
6849+ info->relallvisible = relallvisible;
68426850info->relkind = relkind;
68436851info->postponed_def = false;
68446852
@@ -6874,6 +6882,8 @@ getTables(Archive *fout, int *numTables)
68746882inti_relhasindex;
68756883inti_relhasrules;
68766884inti_relpages;
6885+ inti_reltuples;
6886+ inti_relallvisible;
68776887inti_toastpages;
68786888inti_owning_tab;
68796889inti_owning_col;
@@ -6924,7 +6934,7 @@ getTables(Archive *fout, int *numTables)
69246934 "c.relowner, "
69256935 "c.relchecks, "
69266936 "c.relhasindex, c.relhasrules, c.relpages, "
6927- "c.relhastriggers, "
6937+ "c.reltuples, c.relallvisible, c. relhastriggers, "
69286938 "c.relpersistence, "
69296939 "c.reloftype, "
69306940 "c.relacl, "
@@ -7088,6 +7098,8 @@ getTables(Archive *fout, int *numTables)
70887098i_relhasindex = PQfnumber(res, "relhasindex");
70897099i_relhasrules = PQfnumber(res, "relhasrules");
70907100i_relpages = PQfnumber(res, "relpages");
7101+ i_reltuples = PQfnumber(res, "reltuples");
7102+ i_relallvisible = PQfnumber(res, "relallvisible");
70917103i_toastpages = PQfnumber(res, "toastpages");
70927104i_owning_tab = PQfnumber(res, "owning_tab");
70937105i_owning_col = PQfnumber(res, "owning_col");
@@ -7134,6 +7146,9 @@ getTables(Archive *fout, int *numTables)
71347146
71357147for (i = 0; i < ntups; i++)
71367148{
7149+ floatreltuples = strtof(PQgetvalue(res, i, i_reltuples), NULL);
7150+ int32relallvisible = atoi(PQgetvalue(res, i, i_relallvisible));
7151+
71377152tblinfo[i].dobj.objType = DO_TABLE;
71387153tblinfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_reltableoid));
71397154tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
@@ -7233,7 +7248,8 @@ getTables(Archive *fout, int *numTables)
72337248
72347249/* Add statistics */
72357250if (tblinfo[i].interesting)
7236- getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relkind);
7251+ getRelationStatistics(fout, &tblinfo[i].dobj, tblinfo[i].relpages,
7252+ reltuples, relallvisible, tblinfo[i].relkind);
72377253
72387254/*
72397255 * Read-lock target tables to make sure they aren't DROPPED or altered
@@ -7499,6 +7515,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
74997515i_oid,
75007516i_indrelid,
75017517i_indexname,
7518+ i_relpages,
7519+ i_reltuples,
7520+ i_relallvisible,
75027521i_parentidx,
75037522i_indexdef,
75047523i_indnkeyatts,
@@ -7552,6 +7571,7 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
75527571appendPQExpBufferStr(query,
75537572 "SELECT t.tableoid, t.oid, i.indrelid, "
75547573 "t.relname AS indexname, "
7574+ "t.relpages, t.reltuples, t.relallvisible, "
75557575 "pg_catalog.pg_get_indexdef(i.indexrelid) AS indexdef, "
75567576 "i.indkey, i.indisclustered, "
75577577 "c.contype, c.conname, "
@@ -7659,6 +7679,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
76597679i_oid = PQfnumber(res, "oid");
76607680i_indrelid = PQfnumber(res, "indrelid");
76617681i_indexname = PQfnumber(res, "indexname");
7682+ i_relpages = PQfnumber(res, "relpages");
7683+ i_reltuples = PQfnumber(res, "reltuples");
7684+ i_relallvisible = PQfnumber(res, "relallvisible");
76627685i_parentidx = PQfnumber(res, "parentidx");
76637686i_indexdef = PQfnumber(res, "indexdef");
76647687i_indnkeyatts = PQfnumber(res, "indnkeyatts");
@@ -7725,6 +7748,9 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
77257748charcontype;
77267749charindexkind;
77277750RelStatsInfo *relstats;
7751+ int32relpages = atoi(PQgetvalue(res, j, i_relpages));
7752+ floatreltuples = strtof(PQgetvalue(res, j, i_reltuples), NULL);
7753+ int32relallvisible = atoi(PQgetvalue(res, j, i_relallvisible));
77287754
77297755indxinfo[j].dobj.objType = DO_INDEX;
77307756indxinfo[j].dobj.catId.tableoid = atooid(PQgetvalue(res, j, i_tableoid));
@@ -7759,7 +7785,8 @@ getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
77597785indexkind = RELKIND_PARTITIONED_INDEX;
77607786
77617787contype = *(PQgetvalue(res, j, i_contype));
7762- relstats = getRelationStatistics(fout, &indxinfo[j].dobj, indexkind);
7788+ relstats = getRelationStatistics(fout, &indxinfo[j].dobj, relpages,
7789+ reltuples, relallvisible, indexkind);
77637790
77647791if (contype == 'p' || contype == 'u' || contype == 'x')
77657792{
@@ -10383,18 +10410,6 @@ dumpComment(Archive *fout, const char *type,
1038310410catalogId, subid, dumpId, NULL);
1038410411}
1038510412
10386- /*
10387- * Tabular description of the parameters to pg_restore_relation_stats()
10388- * param_name, param_type
10389- */
10390- static const char *rel_stats_arginfo[][2] = {
10391- {"relation", "regclass"},
10392- {"version", "integer"},
10393- {"relpages", "integer"},
10394- {"reltuples", "real"},
10395- {"relallvisible", "integer"},
10396- };
10397-
1039810413/*
1039910414 * Tabular description of the parameters to pg_restore_attribute_stats()
1040010415 * param_name, param_type
@@ -10419,30 +10434,6 @@ static const char *att_stats_arginfo[][2] = {
1041910434{"range_bounds_histogram", "text"},
1042010435};
1042110436
10422- /*
10423- * getRelStatsExportQuery --
10424- *
10425- * Generate a query that will fetch all relation (e.g. pg_class)
10426- * stats for a given relation.
10427- */
10428- static void
10429- getRelStatsExportQuery(PQExpBuffer query, Archive *fout,
10430- const char *schemaname, const char *relname)
10431- {
10432- resetPQExpBuffer(query);
10433- appendPQExpBufferStr(query,
10434- "SELECT c.oid::regclass AS relation, "
10435- "current_setting('server_version_num') AS version, "
10436- "c.relpages, c.reltuples, c.relallvisible "
10437- "FROM pg_class c "
10438- "JOIN pg_namespace n "
10439- "ON n.oid = c.relnamespace "
10440- "WHERE n.nspname = ");
10441- appendStringLiteralAH(query, schemaname, fout);
10442- appendPQExpBufferStr(query, " AND c.relname = ");
10443- appendStringLiteralAH(query, relname, fout);
10444- }
10445-
1044610437/*
1044710438 * getAttStatsExportQuery --
1044810439 *
@@ -10454,21 +10445,22 @@ getAttStatsExportQuery(PQExpBuffer query, Archive *fout,
1045410445 const char *schemaname, const char *relname)
1045510446{
1045610447resetPQExpBuffer(query);
10457- appendPQExpBufferStr(query,
10458- "SELECT c.oid::regclass AS relation, "
10459- "s.attname,"
10460- "s.inherited,"
10461- "current_setting('server_version_num') AS version, "
10462- "s.null_frac,"
10463- "s.avg_width,"
10464- "s.n_distinct,"
10465- "s.most_common_vals,"
10466- "s.most_common_freqs,"
10467- "s.histogram_bounds,"
10468- "s.correlation,"
10469- "s.most_common_elems,"
10470- "s.most_common_elem_freqs,"
10471- "s.elem_count_histogram,");
10448+ appendPQExpBuffer(query,
10449+ "SELECT c.oid::regclass AS relation, "
10450+ "s.attname,"
10451+ "s.inherited,"
10452+ "'%u'::integer AS version, "
10453+ "s.null_frac,"
10454+ "s.avg_width,"
10455+ "s.n_distinct,"
10456+ "s.most_common_vals,"
10457+ "s.most_common_freqs,"
10458+ "s.histogram_bounds,"
10459+ "s.correlation,"
10460+ "s.most_common_elems,"
10461+ "s.most_common_elem_freqs,"
10462+ "s.elem_count_histogram,",
10463+ fout->remoteVersion);
1047210464
1047310465if (fout->remoteVersion >= 170000)
1047410466appendPQExpBufferStr(query,
@@ -10521,34 +10513,21 @@ appendNamedArgument(PQExpBuffer out, Archive *fout, const char *argname,
1052110513 * Append a formatted pg_restore_relation_stats statement.
1052210514 */
1052310515static void
10524- appendRelStatsImport(PQExpBuffer out, Archive *fout,PGresult *res )
10516+ appendRelStatsImport(PQExpBuffer out, Archive *fout,const RelStatsInfo *rsinfo )
1052510517{
10526- const char *sep = "";
10518+ const char *qualname = fmtQualifiedId(rsinfo->dobj.namespace->dobj.name, rsinfo->dobj.name);
10519+ charreltuples_str[FLOAT_SHORTEST_DECIMAL_LEN];
1052710520
10528- if (PQntuples(res) == 0)
10529- return;
10521+ float_to_shortest_decimal_buf(rsinfo->reltuples, reltuples_str);
1053010522
1053110523appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
10532-
10533- for (int argno = 0; argno < lengthof(rel_stats_arginfo); argno++)
10534- {
10535- const char *argname = rel_stats_arginfo[argno][0];
10536- const char *argtype = rel_stats_arginfo[argno][1];
10537- intfieldno = PQfnumber(res, argname);
10538-
10539- if (fieldno < 0)
10540- pg_fatal("relation stats export query missing field '%s'",
10541- argname);
10542-
10543- if (PQgetisnull(res, 0, fieldno))
10544- continue;
10545-
10546- appendPQExpBufferStr(out, sep);
10547- appendNamedArgument(out, fout, argname, PQgetvalue(res, 0, fieldno), argtype);
10548-
10549- sep = ",\n";
10550- }
10551- appendPQExpBufferStr(out, "\n);\n");
10524+ appendPQExpBuffer(out, "\t'relation', '%s'::regclass,\n", qualname);
10525+ appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
10526+ fout->remoteVersion);
10527+ appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages);
10528+ appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", reltuples_str);
10529+ appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
10530+ rsinfo->relallvisible);
1055210531}
1055310532
1055410533/*
@@ -10643,15 +10622,11 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
1064310622tag = createPQExpBuffer();
1064410623appendPQExpBufferStr(tag, fmtId(dobj->name));
1064510624
10646- query = createPQExpBuffer();
1064710625out = createPQExpBuffer();
1064810626
10649- getRelStatsExportQuery(query, fout, dobj->namespace->dobj.name,
10650- dobj->name);
10651- res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
10652- appendRelStatsImport(out, fout, res);
10653- PQclear(res);
10627+ appendRelStatsImport(out, fout, rsinfo);
1065410628
10629+ query = createPQExpBuffer();
1065510630getAttStatsExportQuery(query, fout, dobj->namespace->dobj.name,
1065610631 dobj->name);
1065710632res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);