* pg_set_relation_stats() needs to do an ACL check so you can't set the stats on someone else's table. I suggest honoring the new MAINTAIN privilege as well.
Added.
* If possible, reading from pg_stats (instead of pg_statistic) would be ideal because pg_stats already does the right checks at read time, so a non-superuser can export stats, too.
Done. That was sorta how it was originally, so returning to that wasn't too hard.
* If reading from pg_stats, should you change the signature of pg_set_relation_stats() to have argument names matching the columns of pg_stats (e.g. most_common_vals instead of stakind/stavalues)?
Done.
In other words, make this a slightly higher level: conceptually exporting/importing pg_stats rather than pg_statistic. This may also make the SQL export queries simpler.
Eh, about the same.
Also, I'm wondering about error handling. Is some kind of error thrown by pg_set_relation_stats() going to abort an entire restore? That might be easy to prevent with pg_restore, because it can just omit the stats, but harder if it's in a SQL file.
Aside from the oid being invalid, there's not a whole lot that can go wrong in set_relation_stats(). The error checking I did closely mirrors that in analyze.c.
Aside from the changes you suggested, as well as the error reporting change you suggested for pg_dump, I also filtered out attempts to dump stats on views.
A few TAP tests are still failing and I haven't been able to diagnose why, though the failures in parallel dump seem to be that it tries to import stats on indexes that haven't been created yet, which is odd because I sent the dependency.
All those changes are available in the patches attached.