6
6
* Portions Copyright (c) 1994, Regents of the University of California
7
7
*
8
8
*
9
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.123 2009/04/08 19:02:37 heikki Exp $
9
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.124 2009/04/11 20:23:05 tgl Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
@@ -33,10 +33,13 @@ static const char *progname;
33
33
34
34
static void help (void );
35
35
36
+ static void dropRoles (PGconn * conn );
36
37
static void dumpRoles (PGconn * conn );
37
38
static void dumpRoleMembership (PGconn * conn );
38
39
static void dumpGroups (PGconn * conn );
40
+ static void dropTablespaces (PGconn * conn );
39
41
static void dumpTablespaces (PGconn * conn );
42
+ static void dropDBs (PGconn * conn );
40
43
static void dumpCreateDB (PGconn * conn );
41
44
static void dumpDatabaseConfig (PGconn * conn , const char * dbname );
42
45
static void dumpUserConfig (PGconn * conn , const char * username );
@@ -54,7 +57,6 @@ static void executeCommand(PGconn *conn, const char *query);
54
57
55
58
static char pg_dump_bin [MAXPGPATH ];
56
59
static PQExpBuffer pgdumpopts ;
57
- static bool output_clean = false;
58
60
static bool skip_acls = false;
59
61
static bool verbose = false;
60
62
@@ -82,6 +84,7 @@ main(int argc, char *argv[])
82
84
enum trivalue prompt_password = TRI_DEFAULT ;
83
85
bool data_only = false;
84
86
bool globals_only = false;
87
+ bool output_clean = false;
85
88
bool roles_only = false;
86
89
bool tablespaces_only = false;
87
90
bool schema_only = false;
@@ -90,8 +93,9 @@ main(int argc, char *argv[])
90
93
const char * std_strings ;
91
94
int c ,
92
95
ret ;
96
+ int optindex ;
93
97
94
- struct option long_options [] = {
98
+ static struct option long_options [] = {
95
99
{"data-only" , no_argument , NULL , 'a' },
96
100
{"clean" , no_argument , NULL , 'c' },
97
101
{"file" , required_argument , NULL , 'f' },
@@ -130,8 +134,6 @@ main(int argc, char *argv[])
130
134
{NULL , 0 , NULL , 0 }
131
135
};
132
136
133
- int optindex ;
134
-
135
137
set_pglocale_pgservice (argv [0 ], PG_TEXTDOMAIN ("pg_dump" ));
136
138
137
139
progname = get_progname (argv [0 ]);
@@ -442,16 +444,41 @@ main(int argc, char *argv[])
442
444
443
445
fprintf (OPF , "\\connect postgres\n\n" );
444
446
447
+ /* Replicate encoding and std_strings in output */
448
+ fprintf (OPF , "SET client_encoding = '%s';\n" ,
449
+ pg_encoding_to_char (encoding ));
450
+ fprintf (OPF , "SET standard_conforming_strings = %s;\n" , std_strings );
451
+ if (strcmp (std_strings , "off" ) == 0 )
452
+ fprintf (OPF , "SET escape_string_warning = off;\n" );
453
+ fprintf (OPF , "\n" );
454
+
445
455
if (!data_only )
446
456
{
447
- /* Replicate encoding and std_strings in output */
448
- fprintf (OPF , "SET client_encoding = '%s';\n" ,
449
- pg_encoding_to_char (encoding ));
450
- fprintf (OPF , "SET standard_conforming_strings = %s;\n" , std_strings );
451
- if (strcmp (std_strings , "off" ) == 0 )
452
- fprintf (OPF , "SET escape_string_warning = 'off';\n" );
453
- fprintf (OPF , "\n" );
457
+ /*
458
+ * If asked to --clean, do that first. We can avoid detailed
459
+ * dependency analysis because databases never depend on each other,
460
+ * and tablespaces never depend on each other. Roles could have
461
+ * grants to each other, but DROP ROLE will clean those up silently.
462
+ */
463
+ if (output_clean )
464
+ {
465
+ if (!globals_only && !roles_only && !tablespaces_only )
466
+ dropDBs (conn );
454
467
468
+ if (!roles_only && !no_tablespaces )
469
+ {
470
+ if (server_version >= 80000 )
471
+ dropTablespaces (conn );
472
+ }
473
+
474
+ if (!tablespaces_only )
475
+ dropRoles (conn );
476
+ }
477
+
478
+ /*
479
+ * Now create objects as requested. Be careful that option logic
480
+ * here is the same as for drops above.
481
+ */
455
482
if (!tablespaces_only )
456
483
{
457
484
/* Dump roles (users) */
@@ -492,7 +519,6 @@ main(int argc, char *argv[])
492
519
}
493
520
494
521
495
-
496
522
static void
497
523
help (void )
498
524
{
@@ -541,6 +567,48 @@ help(void)
541
567
}
542
568
543
569
570
+ /*
571
+ * Drop roles
572
+ */
573
+ static void
574
+ dropRoles (PGconn * conn )
575
+ {
576
+ PGresult * res ;
577
+ int i_rolname ;
578
+ int i ;
579
+
580
+ if (server_version >= 80100 )
581
+ res = executeQuery (conn ,
582
+ "SELECT rolname "
583
+ "FROM pg_authid "
584
+ "ORDER BY 1" );
585
+ else
586
+ res = executeQuery (conn ,
587
+ "SELECT usename as rolname "
588
+ "FROM pg_shadow "
589
+ "UNION "
590
+ "SELECT groname as rolname "
591
+ "FROM pg_group "
592
+ "ORDER BY 1" );
593
+
594
+ i_rolname = PQfnumber (res , "rolname" );
595
+
596
+ if (PQntuples (res ) > 0 )
597
+ fprintf (OPF , "--\n-- Drop roles\n--\n\n" );
598
+
599
+ for (i = 0 ; i < PQntuples (res ); i ++ )
600
+ {
601
+ const char * rolename ;
602
+
603
+ rolename = PQgetvalue (res , i , i_rolname );
604
+
605
+ fprintf (OPF , "DROP ROLE %s;\n" , fmtId (rolename ));
606
+ }
607
+
608
+ PQclear (res );
609
+
610
+ fprintf (OPF , "\n\n" );
611
+ }
544
612
545
613
/*
546
614
* Dump roles
@@ -637,14 +705,12 @@ dumpRoles(PGconn *conn)
637
705
638
706
resetPQExpBuffer (buf );
639
707
640
- if (output_clean )
641
- appendPQExpBuffer (buf , "DROP ROLE %s;\n" , fmtId (rolename ));
642
-
643
708
/*
644
709
* We dump CREATE ROLE followed by ALTER ROLE to ensure that the role
645
- * will acquire the right properties even if it already exists. (The
646
- * above DROP may therefore seem redundant, but it isn't really,
647
- * because this technique doesn't get rid of role memberships.)
710
+ * will acquire the right properties even if it already exists (ie,
711
+ * it won't hurt for the CREATE to fail). This is particularly
712
+ * important for the role we are connected as, since even with --clean
713
+ * we will have failed to drop it.
648
714
*/
649
715
appendPQExpBuffer (buf , "CREATE ROLE %s;\n" , fmtId (rolename ));
650
716
appendPQExpBuffer (buf , "ALTER ROLE %s WITH" , fmtId (rolename ));
@@ -834,6 +900,40 @@ dumpGroups(PGconn *conn)
834
900
fprintf (OPF , "\n\n" );
835
901
}
836
902
903
+
904
+ /*
905
+ * Drop tablespaces.
906
+ */
907
+ static void
908
+ dropTablespaces (PGconn * conn )
909
+ {
910
+ PGresult * res ;
911
+ int i ;
912
+
913
+ /*
914
+ * Get all tablespaces except built-in ones (which we assume are named
915
+ * pg_xxx)
916
+ */
917
+ res = executeQuery (conn , "SELECT spcname "
918
+ "FROM pg_catalog.pg_tablespace "
919
+ "WHERE spcname !~ '^pg_' "
920
+ "ORDER BY 1" );
921
+
922
+ if (PQntuples (res ) > 0 )
923
+ fprintf (OPF , "--\n-- Drop tablespaces\n--\n\n" );
924
+
925
+ for (i = 0 ; i < PQntuples (res ); i ++ )
926
+ {
927
+ char * spcname = PQgetvalue (res , i , 0 );
928
+
929
+ fprintf (OPF , "DROP TABLESPACE %s;\n" , fmtId (spcname ));
930
+ }
931
+
932
+ PQclear (res );
933
+
934
+ fprintf (OPF , "\n\n" );
935
+ }
936
+
837
937
/*
838
938
* Dump tablespaces.
839
939
*/
@@ -880,9 +980,6 @@ dumpTablespaces(PGconn *conn)
880
980
/* needed for buildACLCommands() */
881
981
fspcname = strdup (fmtId (spcname ));
882
982
883
- if (output_clean )
884
- appendPQExpBuffer (buf , "DROP TABLESPACE %s;\n" , fspcname );
885
-
886
983
appendPQExpBuffer (buf , "CREATE TABLESPACE %s" , fspcname );
887
984
appendPQExpBuffer (buf , " OWNER %s" , fmtId (spcowner ));
888
985
@@ -917,6 +1014,53 @@ dumpTablespaces(PGconn *conn)
917
1014
fprintf (OPF , "\n\n" );
918
1015
}
919
1016
1017
+
1018
+ /*
1019
+ * Dump commands to drop each database.
1020
+ *
1021
+ * This should match the set of databases targeted by dumpCreateDB().
1022
+ */
1023
+ static void
1024
+ dropDBs (PGconn * conn )
1025
+ {
1026
+ PGresult * res ;
1027
+ int i ;
1028
+
1029
+ if (server_version >= 70100 )
1030
+ res = executeQuery (conn ,
1031
+ "SELECT datname "
1032
+ "FROM pg_database d "
1033
+ "WHERE datallowconn ORDER BY 1" );
1034
+ else
1035
+ res = executeQuery (conn ,
1036
+ "SELECT datname "
1037
+ "FROM pg_database d "
1038
+ "ORDER BY 1" );
1039
+
1040
+ if (PQntuples (res ) > 0 )
1041
+ fprintf (OPF , "--\n-- Drop databases\n--\n\n" );
1042
+
1043
+ for (i = 0 ; i < PQntuples (res ); i ++ )
1044
+ {
1045
+ char * dbname = PQgetvalue (res , i , 0 );
1046
+
1047
+ /*
1048
+ * Skip "template1" and "postgres"; the restore script is almost
1049
+ * certainly going to be run in one or the other, and we don't know
1050
+ * which. This must agree with dumpCreateDB's choices!
1051
+ */
1052
+ if (strcmp (dbname , "template1" ) != 0 &&
1053
+ strcmp (dbname , "postgres" ) != 0 )
1054
+ {
1055
+ fprintf (OPF , "DROP DATABASE %s;\n" , fmtId (dbname ));
1056
+ }
1057
+ }
1058
+
1059
+ PQclear (res );
1060
+
1061
+ fprintf (OPF , "\n\n" );
1062
+ }
1063
+
920
1064
/*
921
1065
* Dump commands to create each database.
922
1066
*
@@ -984,7 +1128,7 @@ dumpCreateDB(PGconn *conn)
984
1128
"(select usename from pg_shadow where usesysid=datdba), "
985
1129
"(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), "
986
1130
"pg_encoding_to_char(d.encoding), "
987
- "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid"
1131
+ "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, "
988
1132
"datistemplate, '' as datacl, -1 as datconnlimit, "
989
1133
"'pg_default' AS dattablespace "
990
1134
"FROM pg_database d "
@@ -999,7 +1143,7 @@ dumpCreateDB(PGconn *conn)
999
1143
"SELECT datname, "
1000
1144
"(select usename from pg_shadow where usesysid=datdba), "
1001
1145
"pg_encoding_to_char(d.encoding), "
1002
- "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid"
1146
+ "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, "
1003
1147
"'f' as datistemplate, "
1004
1148
"'' as datacl, -1 as datconnlimit, "
1005
1149
"'pg_default' AS dattablespace "
@@ -1033,9 +1177,6 @@ dumpCreateDB(PGconn *conn)
1033
1177
if (strcmp (dbname , "template1" ) != 0 &&
1034
1178
strcmp (dbname , "postgres" ) != 0 )
1035
1179
{
1036
- if (output_clean )
1037
- appendPQExpBuffer (buf , "DROP DATABASE %s;\n" , fdbname );
1038
-
1039
1180
appendPQExpBuffer (buf , "CREATE DATABASE %s" , fdbname );
1040
1181
1041
1182
appendPQExpBuffer (buf , " WITH TEMPLATE = template0" );
@@ -1120,7 +1261,6 @@ dumpCreateDB(PGconn *conn)
1120
1261
}
1121
1262
1122
1263
1123
-
1124
1264
/*
1125
1265
* Dump database-specific configuration
1126
1266
*/
0 commit comments