Header And Logo

PostgreSQL
| The world's most advanced open source database.

reindexdb.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * reindexdb
00004  *
00005  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00006  *
00007  * src/bin/scripts/reindexdb.c
00008  *
00009  *-------------------------------------------------------------------------
00010  */
00011 
00012 #include "postgres_fe.h"
00013 #include "common.h"
00014 #include "dumputils.h"
00015 
00016 
00017 static void reindex_one_database(const char *name, const char *dbname,
00018                      const char *type, const char *host,
00019                      const char *port, const char *username,
00020                      enum trivalue prompt_password, const char *progname,
00021                      bool echo);
00022 static void reindex_all_databases(const char *maintenance_db,
00023                       const char *host, const char *port,
00024                       const char *username, enum trivalue prompt_password,
00025                       const char *progname, bool echo,
00026                       bool quiet);
00027 static void reindex_system_catalogs(const char *dbname,
00028                         const char *host, const char *port,
00029                         const char *username, enum trivalue prompt_password,
00030                         const char *progname, bool echo);
00031 static void help(const char *progname);
00032 
00033 int
00034 main(int argc, char *argv[])
00035 {
00036     static struct option long_options[] = {
00037         {"host", required_argument, NULL, 'h'},
00038         {"port", required_argument, NULL, 'p'},
00039         {"username", required_argument, NULL, 'U'},
00040         {"no-password", no_argument, NULL, 'w'},
00041         {"password", no_argument, NULL, 'W'},
00042         {"echo", no_argument, NULL, 'e'},
00043         {"quiet", no_argument, NULL, 'q'},
00044         {"dbname", required_argument, NULL, 'd'},
00045         {"all", no_argument, NULL, 'a'},
00046         {"system", no_argument, NULL, 's'},
00047         {"table", required_argument, NULL, 't'},
00048         {"index", required_argument, NULL, 'i'},
00049         {"maintenance-db", required_argument, NULL, 2},
00050         {NULL, 0, NULL, 0}
00051     };
00052 
00053     const char *progname;
00054     int         optindex;
00055     int         c;
00056 
00057     const char *dbname = NULL;
00058     const char *maintenance_db = NULL;
00059     const char *host = NULL;
00060     const char *port = NULL;
00061     const char *username = NULL;
00062     enum trivalue prompt_password = TRI_DEFAULT;
00063     bool        syscatalog = false;
00064     bool        alldb = false;
00065     bool        echo = false;
00066     bool        quiet = false;
00067     SimpleStringList indexes = {NULL, NULL};
00068     SimpleStringList tables = {NULL, NULL};
00069 
00070     progname = get_progname(argv[0]);
00071     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
00072 
00073     handle_help_version_opts(argc, argv, "reindexdb", help);
00074 
00075     /* process command-line options */
00076     while ((c = getopt_long(argc, argv, "h:p:U:wWeqd:ast:i:", long_options, &optindex)) != -1)
00077     {
00078         switch (c)
00079         {
00080             case 'h':
00081                 host = pg_strdup(optarg);
00082                 break;
00083             case 'p':
00084                 port = pg_strdup(optarg);
00085                 break;
00086             case 'U':
00087                 username = pg_strdup(optarg);
00088                 break;
00089             case 'w':
00090                 prompt_password = TRI_NO;
00091                 break;
00092             case 'W':
00093                 prompt_password = TRI_YES;
00094                 break;
00095             case 'e':
00096                 echo = true;
00097                 break;
00098             case 'q':
00099                 quiet = true;
00100                 break;
00101             case 'd':
00102                 dbname = pg_strdup(optarg);
00103                 break;
00104             case 'a':
00105                 alldb = true;
00106                 break;
00107             case 's':
00108                 syscatalog = true;
00109                 break;
00110             case 't':
00111                 simple_string_list_append(&tables, optarg);
00112                 break;
00113             case 'i':
00114                 simple_string_list_append(&indexes, optarg);
00115                 break;
00116             case 2:
00117                 maintenance_db = pg_strdup(optarg);
00118                 break;
00119             default:
00120                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00121                 exit(1);
00122         }
00123     }
00124 
00125     /*
00126      * Non-option argument specifies database name as long as it wasn't
00127      * already specified with -d / --dbname
00128      */
00129     if (optind < argc && dbname == NULL)
00130     {
00131         dbname = argv[optind];
00132         optind++;
00133     }
00134 
00135     if (optind < argc)
00136     {
00137         fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
00138                 progname, argv[optind]);
00139         fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
00140         exit(1);
00141     }
00142 
00143     setup_cancel_handler();
00144 
00145     if (alldb)
00146     {
00147         if (dbname)
00148         {
00149             fprintf(stderr, _("%s: cannot reindex all databases and a specific one at the same time\n"), progname);
00150             exit(1);
00151         }
00152         if (syscatalog)
00153         {
00154             fprintf(stderr, _("%s: cannot reindex all databases and system catalogs at the same time\n"), progname);
00155             exit(1);
00156         }
00157         if (tables.head != NULL)
00158         {
00159             fprintf(stderr, _("%s: cannot reindex specific table(s) in all databases\n"), progname);
00160             exit(1);
00161         }
00162         if (indexes.head != NULL)
00163         {
00164             fprintf(stderr, _("%s: cannot reindex specific index(es) in all databases\n"), progname);
00165             exit(1);
00166         }
00167 
00168         reindex_all_databases(maintenance_db, host, port, username,
00169                               prompt_password, progname, echo, quiet);
00170     }
00171     else if (syscatalog)
00172     {
00173         if (tables.head != NULL)
00174         {
00175             fprintf(stderr, _("%s: cannot reindex specific table(s) and system catalogs at the same time\n"), progname);
00176             exit(1);
00177         }
00178         if (indexes.head != NULL)
00179         {
00180             fprintf(stderr, _("%s: cannot reindex specific index(es) and system catalogs at the same time\n"), progname);
00181             exit(1);
00182         }
00183 
00184         if (dbname == NULL)
00185         {
00186             if (getenv("PGDATABASE"))
00187                 dbname = getenv("PGDATABASE");
00188             else if (getenv("PGUSER"))
00189                 dbname = getenv("PGUSER");
00190             else
00191                 dbname = get_user_name(progname);
00192         }
00193 
00194         reindex_system_catalogs(dbname, host, port, username, prompt_password,
00195                                 progname, echo);
00196     }
00197     else
00198     {
00199         if (dbname == NULL)
00200         {
00201             if (getenv("PGDATABASE"))
00202                 dbname = getenv("PGDATABASE");
00203             else if (getenv("PGUSER"))
00204                 dbname = getenv("PGUSER");
00205             else
00206                 dbname = get_user_name(progname);
00207         }
00208 
00209         if (indexes.head != NULL)
00210         {
00211             SimpleStringListCell *cell;
00212 
00213             for (cell = indexes.head; cell; cell = cell->next)
00214             {
00215                 reindex_one_database(cell->val, dbname, "INDEX", host, port,
00216                                   username, prompt_password, progname, echo);
00217             }
00218         }
00219         if (tables.head != NULL)
00220         {
00221             SimpleStringListCell *cell;
00222 
00223             for (cell = tables.head; cell; cell = cell->next)
00224             {
00225                 reindex_one_database(cell->val, dbname, "TABLE", host, port,
00226                                   username, prompt_password, progname, echo);
00227             }
00228         }
00229         /* reindex database only if neither index nor table is specified */
00230         if (indexes.head == NULL && tables.head == NULL)
00231             reindex_one_database(dbname, dbname, "DATABASE", host, port,
00232                                  username, prompt_password, progname, echo);
00233     }
00234 
00235     exit(0);
00236 }
00237 
00238 static void
00239 reindex_one_database(const char *name, const char *dbname, const char *type,
00240                      const char *host, const char *port, const char *username,
00241               enum trivalue prompt_password, const char *progname, bool echo)
00242 {
00243     PQExpBufferData sql;
00244 
00245     PGconn     *conn;
00246 
00247     initPQExpBuffer(&sql);
00248 
00249     appendPQExpBuffer(&sql, "REINDEX");
00250     if (strcmp(type, "TABLE") == 0)
00251         appendPQExpBuffer(&sql, " TABLE %s", name);
00252     else if (strcmp(type, "INDEX") == 0)
00253         appendPQExpBuffer(&sql, " INDEX %s", name);
00254     else if (strcmp(type, "DATABASE") == 0)
00255         appendPQExpBuffer(&sql, " DATABASE %s", fmtId(name));
00256     appendPQExpBuffer(&sql, ";\n");
00257 
00258     conn = connectDatabase(dbname, host, port, username, prompt_password,
00259                            progname, false);
00260 
00261     if (!executeMaintenanceCommand(conn, sql.data, echo))
00262     {
00263         if (strcmp(type, "TABLE") == 0)
00264             fprintf(stderr, _("%s: reindexing of table \"%s\" in database \"%s\" failed: %s"),
00265                     progname, name, dbname, PQerrorMessage(conn));
00266         if (strcmp(type, "INDEX") == 0)
00267             fprintf(stderr, _("%s: reindexing of index \"%s\" in database \"%s\" failed: %s"),
00268                     progname, name, dbname, PQerrorMessage(conn));
00269         else
00270             fprintf(stderr, _("%s: reindexing of database \"%s\" failed: %s"),
00271                     progname, dbname, PQerrorMessage(conn));
00272         PQfinish(conn);
00273         exit(1);
00274     }
00275 
00276     PQfinish(conn);
00277     termPQExpBuffer(&sql);
00278 }
00279 
00280 static void
00281 reindex_all_databases(const char *maintenance_db,
00282                       const char *host, const char *port,
00283                       const char *username, enum trivalue prompt_password,
00284                       const char *progname, bool echo, bool quiet)
00285 {
00286     PGconn     *conn;
00287     PGresult   *result;
00288     int         i;
00289 
00290     conn = connectMaintenanceDatabase(maintenance_db, host, port, username,
00291                                       prompt_password, progname);
00292     result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", progname, echo);
00293     PQfinish(conn);
00294 
00295     for (i = 0; i < PQntuples(result); i++)
00296     {
00297         char       *dbname = PQgetvalue(result, i, 0);
00298 
00299         if (!quiet)
00300         {
00301             printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
00302             fflush(stdout);
00303         }
00304 
00305         reindex_one_database(dbname, dbname, "DATABASE", host, port, username,
00306                              prompt_password, progname, echo);
00307     }
00308 
00309     PQclear(result);
00310 }
00311 
00312 static void
00313 reindex_system_catalogs(const char *dbname, const char *host, const char *port,
00314                         const char *username, enum trivalue prompt_password,
00315                         const char *progname, bool echo)
00316 {
00317     PQExpBufferData sql;
00318 
00319     PGconn     *conn;
00320 
00321     initPQExpBuffer(&sql);
00322 
00323     appendPQExpBuffer(&sql, "REINDEX SYSTEM %s;\n", dbname);
00324 
00325     conn = connectDatabase(dbname, host, port, username, prompt_password,
00326                            progname, false);
00327     if (!executeMaintenanceCommand(conn, sql.data, echo))
00328     {
00329         fprintf(stderr, _("%s: reindexing of system catalogs failed: %s"),
00330                 progname, PQerrorMessage(conn));
00331         PQfinish(conn);
00332         exit(1);
00333     }
00334     PQfinish(conn);
00335     termPQExpBuffer(&sql);
00336 }
00337 
00338 static void
00339 help(const char *progname)
00340 {
00341     printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
00342     printf(_("Usage:\n"));
00343     printf(_("  %s [OPTION]... [DBNAME]\n"), progname);
00344     printf(_("\nOptions:\n"));
00345     printf(_("  -a, --all                 reindex all databases\n"));
00346     printf(_("  -d, --dbname=DBNAME       database to reindex\n"));
00347     printf(_("  -e, --echo                show the commands being sent to the server\n"));
00348     printf(_("  -i, --index=INDEX         recreate specific index(es) only\n"));
00349     printf(_("  -q, --quiet               don't write any messages\n"));
00350     printf(_("  -s, --system              reindex system catalogs\n"));
00351     printf(_("  -t, --table=TABLE         reindex specific table(s) only\n"));
00352     printf(_("  -V, --version             output version information, then exit\n"));
00353     printf(_("  -?, --help                show this help, then exit\n"));
00354     printf(_("\nConnection options:\n"));
00355     printf(_("  -h, --host=HOSTNAME       database server host or socket directory\n"));
00356     printf(_("  -p, --port=PORT           database server port\n"));
00357     printf(_("  -U, --username=USERNAME   user name to connect as\n"));
00358     printf(_("  -w, --no-password         never prompt for password\n"));
00359     printf(_("  -W, --password            force password prompt\n"));
00360     printf(_("  --maintenance-db=DBNAME   alternate maintenance database\n"));
00361     printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
00362     printf(_("\nReport bugs to <[email protected]>.\n"));
00363 }