LCOV - differential code coverage report
Current view: top level - src/bin/scripts - reindexdb.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 79.5 % 370 294 17 5 16 38 20 90 14 170 10 90 8 29
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 6 6 4 2 4
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 51.9 % 27 14 12 1 4 8 2 1
Legend: Lines: hit not hit (240..) days: 81.6 % 343 280 5 5 16 37 16 90 6 168 9 90
Function coverage date bins:
(240..) days: 60.0 % 10 6 4 2 4

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * reindexdb
                                  4                 :  *
                                  5                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  6                 :  *
                                  7                 :  * src/bin/scripts/reindexdb.c
                                  8                 :  *
                                  9                 :  *-------------------------------------------------------------------------
                                 10                 :  */
                                 11                 : 
                                 12                 : #include "postgres_fe.h"
                                 13                 : 
                                 14                 : #include <limits.h>
                                 15                 : 
                                 16                 : #include "catalog/pg_class_d.h"
                                 17                 : #include "common.h"
                                 18                 : #include "common/connect.h"
                                 19                 : #include "common/logging.h"
                                 20                 : #include "fe_utils/cancel.h"
                                 21                 : #include "fe_utils/option_utils.h"
                                 22                 : #include "fe_utils/parallel_slot.h"
                                 23                 : #include "fe_utils/query_utils.h"
                                 24                 : #include "fe_utils/simple_list.h"
                                 25                 : #include "fe_utils/string_utils.h"
                                 26                 : 
                                 27                 : typedef enum ReindexType
                                 28                 : {
                                 29                 :     REINDEX_DATABASE,
                                 30                 :     REINDEX_INDEX,
                                 31                 :     REINDEX_SCHEMA,
                                 32                 :     REINDEX_SYSTEM,
                                 33                 :     REINDEX_TABLE
                                 34                 : } ReindexType;
                                 35                 : 
                                 36                 : 
                                 37                 : static SimpleStringList *get_parallel_object_list(PGconn *conn,
                                 38                 :                                                   ReindexType type,
                                 39                 :                                                   SimpleStringList *user_list,
                                 40                 :                                                   bool echo);
                                 41                 : static void reindex_one_database(ConnParams *cparams, ReindexType type,
                                 42                 :                                  SimpleStringList *user_list,
                                 43                 :                                  const char *progname,
                                 44                 :                                  bool echo, bool verbose, bool concurrently,
                                 45                 :                                  int concurrentCons, const char *tablespace);
                                 46                 : static void reindex_all_databases(ConnParams *cparams,
                                 47                 :                                   const char *progname, bool echo,
                                 48                 :                                   bool quiet, bool verbose, bool concurrently,
                                 49                 :                                   int concurrentCons, const char *tablespace);
                                 50                 : static void run_reindex_command(PGconn *conn, ReindexType type,
                                 51                 :                                 const char *name, bool echo, bool verbose,
                                 52                 :                                 bool concurrently, bool async,
                                 53                 :                                 const char *tablespace);
                                 54                 : 
                                 55                 : static void help(const char *progname);
                                 56                 : 
                                 57                 : int
 6463 bruce                      58 CBC          32 : main(int argc, char *argv[])
                                 59                 : {
                                 60                 :     static struct option long_options[] = {
                                 61                 :         {"host", required_argument, NULL, 'h'},
                                 62                 :         {"port", required_argument, NULL, 'p'},
                                 63                 :         {"username", required_argument, NULL, 'U'},
                                 64                 :         {"no-password", no_argument, NULL, 'w'},
                                 65                 :         {"password", no_argument, NULL, 'W'},
                                 66                 :         {"echo", no_argument, NULL, 'e'},
                                 67                 :         {"quiet", no_argument, NULL, 'q'},
                                 68                 :         {"schema", required_argument, NULL, 'S'},
                                 69                 :         {"dbname", required_argument, NULL, 'd'},
                                 70                 :         {"all", no_argument, NULL, 'a'},
                                 71                 :         {"system", no_argument, NULL, 's'},
                                 72                 :         {"table", required_argument, NULL, 't'},
                                 73                 :         {"index", required_argument, NULL, 'i'},
                                 74                 :         {"jobs", required_argument, NULL, 'j'},
                                 75                 :         {"verbose", no_argument, NULL, 'v'},
                                 76                 :         {"concurrently", no_argument, NULL, 1},
                                 77                 :         {"maintenance-db", required_argument, NULL, 2},
                                 78                 :         {"tablespace", required_argument, NULL, 3},
                                 79                 :         {NULL, 0, NULL, 0}
                                 80                 :     };
                                 81                 : 
                                 82                 :     const char *progname;
                                 83                 :     int         optindex;
                                 84                 :     int         c;
                                 85                 : 
 6385                            86              32 :     const char *dbname = NULL;
 4142 rhaas                      87              32 :     const char *maintenance_db = NULL;
 6385 bruce                      88              32 :     const char *host = NULL;
                                 89              32 :     const char *port = NULL;
                                 90              32 :     const char *username = NULL;
  767 michael                    91              32 :     const char *tablespace = NULL;
 5155 peter_e                    92              32 :     enum trivalue prompt_password = TRI_DEFAULT;
                                 93                 :     ConnParams  cparams;
 6463 bruce                      94              32 :     bool        syscatalog = false;
                                 95              32 :     bool        alldb = false;
                                 96              32 :     bool        echo = false;
                                 97              32 :     bool        quiet = false;
 2886 fujii                      98              32 :     bool        verbose = false;
 1472 peter                      99              32 :     bool        concurrently = false;
 3734 magnus                    100              32 :     SimpleStringList indexes = {NULL, NULL};
                                101              32 :     SimpleStringList tables = {NULL, NULL};
 3043 simon                     102              32 :     SimpleStringList schemas = {NULL, NULL};
 1352 michael                   103              32 :     int         concurrentCons = 1;
                                104                 : 
 1469 peter                     105              32 :     pg_logging_init(argv[0]);
 6463 bruce                     106              32 :     progname = get_progname(argv[0]);
 5232 peter_e                   107              32 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
                                108                 : 
 6463 bruce                     109              32 :     handle_help_version_opts(argc, argv, "reindexdb", help);
                                110                 : 
                                111                 :     /* process command-line options */
  118 peter                     112 GNC          87 :     while ((c = getopt_long(argc, argv, "ad:eh:i:j:qp:sS:t:U:vwW", long_options, &optindex)) != -1)
                                113                 :     {
 6463 bruce                     114 CBC          58 :         switch (c)
                                115                 :         {
  118 peter                     116 GNC           2 :             case 'a':
                                117               2 :                 alldb = true;
 6463 bruce                     118 GBC           2 :                 break;
  118 peter                     119               1 :             case 'd':
                                120               1 :                 dbname = pg_strdup(optarg);
 6463 bruce                     121 CBC           1 :                 break;
  118 peter                     122 GNC           4 :             case 'e':
                                123               4 :                 echo = true;
 6463 bruce                     124 CBC           4 :                 break;
  118 peter                     125 UNC           0 :             case 'h':
                                126               0 :                 host = pg_strdup(optarg);
 5155 peter_e                   127 UBC           0 :                 break;
  118 peter                     128 GBC           5 :             case 'i':
                                129               5 :                 simple_string_list_append(&indexes, optarg);
 6463 bruce                     130 CBC           5 :                 break;
  118 peter                     131               5 :             case 'j':
                                132               5 :                 if (!option_parse_int(optarg, "-j/--jobs", 1, INT_MAX,
  118 peter                     133 EUB             :                                       &concurrentCons))
  118 peter                     134 UBC           0 :                     exit(1);
 6463 bruce                     135 GBC           5 :                 break;
 6463 bruce                     136 UNC           0 :             case 'q':
                                137               0 :                 quiet = true;
                                138               0 :                 break;
  118 peter                     139               0 :             case 'p':
                                140               0 :                 port = pg_strdup(optarg);
 6463 bruce                     141               0 :                 break;
 6463 bruce                     142 GNC           4 :             case 's':
                                143               4 :                 syscatalog = true;
                                144               4 :                 break;
  118 peter                     145               5 :             case 'S':
                                146               5 :                 simple_string_list_append(&schemas, optarg);
                                147               5 :                 break;
 6463 bruce                     148              10 :             case 't':
 3734 magnus                    149              10 :                 simple_string_list_append(&tables, optarg);
 6463 bruce                     150              10 :                 break;
  118 peter                     151 UNC           0 :             case 'U':
                                152               0 :                 username = pg_strdup(optarg);
 1352 michael                   153               0 :                 break;
 2886 fujii                     154 GBC           4 :             case 'v':
                                155               4 :                 verbose = true;
                                156               4 :                 break;
  118 peter                     157 UNC           0 :             case 'w':
                                158               0 :                 prompt_password = TRI_NO;
                                159               0 :                 break;
                                160               0 :             case 'W':
                                161               0 :                 prompt_password = TRI_YES;
                                162               0 :                 break;
 1472 peter                     163 CBC          10 :             case 1:
                                164              10 :                 concurrently = true;
                                165              10 :                 break;
 4142 rhaas                     166 UBC           0 :             case 2:
 3831 bruce                     167               0 :                 maintenance_db = pg_strdup(optarg);
 4142 rhaas                     168               0 :                 break;
  767 michael                   169 CBC           7 :             case 3:
                                170               7 :                 tablespace = pg_strdup(optarg);
                                171               7 :                 break;
 6463 bruce                     172               1 :             default:
                                173                 :                 /* getopt_long already emitted a complaint */
  366 tgl                       174               1 :                 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 6463 bruce                     175               1 :                 exit(1);
                                176                 :         }
                                177                 :     }
                                178                 : 
                                179                 :     /*
                                180                 :      * Non-option argument specifies database name as long as it wasn't
                                181                 :      * already specified with -d / --dbname
                                182                 :      */
 4009 andrew                    183              29 :     if (optind < argc && dbname == NULL)
                                184                 :     {
                                185              25 :         dbname = argv[optind];
                                186              25 :         optind++;
                                187                 :     }
                                188                 : 
                                189              29 :     if (optind < argc)
                                190                 :     {
 1469 peter                     191 UBC           0 :         pg_log_error("too many command-line arguments (first is \"%s\")",
                                192                 :                      argv[optind]);
  366 tgl                       193               0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
 4009 andrew                    194               0 :         exit(1);
                                195                 :     }
                                196                 : 
                                197                 :     /* fill cparams except for dbname, which is set below */
  902 tgl                       198 CBC          29 :     cparams.pghost = host;
                                199              29 :     cparams.pgport = port;
                                200              29 :     cparams.pguser = username;
                                201              29 :     cparams.prompt_password = prompt_password;
                                202              29 :     cparams.override_dbname = NULL;
                                203                 : 
 1224 michael                   204              29 :     setup_cancel_handler(NULL);
                                205                 : 
 6463 bruce                     206              29 :     if (alldb)
                                207                 :     {
                                208               2 :         if (dbname)
  366 tgl                       209 UBC           0 :             pg_fatal("cannot reindex all databases and a specific one at the same time");
 6463 bruce                     210 CBC           2 :         if (syscatalog)
  366 tgl                       211 UBC           0 :             pg_fatal("cannot reindex all databases and system catalogs at the same time");
 3043 simon                     212 CBC           2 :         if (schemas.head != NULL)
  366 tgl                       213 UBC           0 :             pg_fatal("cannot reindex specific schema(s) in all databases");
 3734 magnus                    214 CBC           2 :         if (tables.head != NULL)
  366 tgl                       215 UBC           0 :             pg_fatal("cannot reindex specific table(s) in all databases");
 3734 magnus                    216 CBC           2 :         if (indexes.head != NULL)
  366 tgl                       217 UBC           0 :             pg_fatal("cannot reindex specific index(es) in all databases");
                                218                 : 
  902 tgl                       219 CBC           2 :         cparams.dbname = maintenance_db;
                                220                 : 
                                221               2 :         reindex_all_databases(&cparams, progname, echo, quiet, verbose,
                                222                 :                               concurrently, concurrentCons, tablespace);
                                223                 :     }
 6463 bruce                     224              27 :     else if (syscatalog)
                                225                 :     {
 3043 simon                     226               4 :         if (schemas.head != NULL)
  366 tgl                       227 UBC           0 :             pg_fatal("cannot reindex specific schema(s) and system catalogs at the same time");
 3734 magnus                    228 CBC           4 :         if (tables.head != NULL)
  366 tgl                       229 UBC           0 :             pg_fatal("cannot reindex specific table(s) and system catalogs at the same time");
 3734 magnus                    230 CBC           4 :         if (indexes.head != NULL)
  366 tgl                       231 UBC           0 :             pg_fatal("cannot reindex specific index(es) and system catalogs at the same time");
                                232                 : 
 1352 michael                   233 CBC           4 :         if (concurrentCons > 1)
  366 tgl                       234               1 :             pg_fatal("cannot use multiple jobs to reindex system catalogs");
                                235                 : 
 6463 bruce                     236               3 :         if (dbname == NULL)
                                237                 :         {
 6463 bruce                     238 UBC           0 :             if (getenv("PGDATABASE"))
                                239               0 :                 dbname = getenv("PGDATABASE");
                                240               0 :             else if (getenv("PGUSER"))
                                241               0 :                 dbname = getenv("PGUSER");
                                242                 :             else
 3399                           243               0 :                 dbname = get_user_name_or_exit(progname);
                                244                 :         }
                                245                 : 
  902 tgl                       246 CBC           3 :         cparams.dbname = dbname;
                                247                 : 
                                248               3 :         reindex_one_database(&cparams, REINDEX_SYSTEM, NULL,
                                249                 :                              progname, echo, verbose,
                                250                 :                              concurrently, 1, tablespace);
                                251                 :     }
                                252                 :     else
                                253                 :     {
                                254                 :         /*
                                255                 :          * Index-level REINDEX is not supported with multiple jobs as we
                                256                 :          * cannot control the concurrent processing of multiple indexes
                                257                 :          * depending on the same relation.
                                258                 :          */
 1352 michael                   259              23 :         if (concurrentCons > 1 && indexes.head != NULL)
  366 tgl                       260               1 :             pg_fatal("cannot use multiple jobs to reindex indexes");
                                261                 : 
 6463 bruce                     262              22 :         if (dbname == NULL)
                                263                 :         {
                                264               1 :             if (getenv("PGDATABASE"))
                                265               1 :                 dbname = getenv("PGDATABASE");
 6463 bruce                     266 UBC           0 :             else if (getenv("PGUSER"))
                                267               0 :                 dbname = getenv("PGUSER");
                                268                 :             else
 3399                           269               0 :                 dbname = get_user_name_or_exit(progname);
                                270                 :         }
                                271                 : 
  902 tgl                       272 CBC          22 :         cparams.dbname = dbname;
                                273                 : 
 3043 simon                     274              22 :         if (schemas.head != NULL)
  902 tgl                       275               4 :             reindex_one_database(&cparams, REINDEX_SCHEMA, &schemas,
                                276                 :                                  progname, echo, verbose,
                                277                 :                                  concurrently, concurrentCons, tablespace);
                                278                 : 
 3734 magnus                    279              22 :         if (indexes.head != NULL)
  902 tgl                       280               4 :             reindex_one_database(&cparams, REINDEX_INDEX, &indexes,
                                281                 :                                  progname, echo, verbose,
                                282                 :                                  concurrently, 1, tablespace);
                                283                 : 
 3734 magnus                    284              20 :         if (tables.head != NULL)
  902 tgl                       285              10 :             reindex_one_database(&cparams, REINDEX_TABLE, &tables,
                                286                 :                                  progname, echo, verbose,
                                287                 :                                  concurrently, concurrentCons, tablespace);
                                288                 : 
                                289                 :         /*
                                290                 :          * reindex database only if neither index nor table nor schema is
                                291                 :          * specified
                                292                 :          */
 3043 simon                     293              18 :         if (indexes.head == NULL && tables.head == NULL && schemas.head == NULL)
  902 tgl                       294               4 :             reindex_one_database(&cparams, REINDEX_DATABASE, NULL,
                                295                 :                                  progname, echo, verbose,
                                296                 :                                  concurrently, concurrentCons, tablespace);
                                297                 :     }
                                298                 : 
 6463 bruce                     299              22 :     exit(0);
                                300                 : }
                                301                 : 
                                302                 : static void
  759 rhaas                     303              34 : reindex_one_database(ConnParams *cparams, ReindexType type,
                                304                 :                      SimpleStringList *user_list,
                                305                 :                      const char *progname, bool echo,
                                306                 :                      bool verbose, bool concurrently, int concurrentCons,
                                307                 :                      const char *tablespace)
                                308                 : {
                                309                 :     PGconn     *conn;
                                310                 :     SimpleStringListCell *cell;
 1352 michael                   311              34 :     bool        parallel = concurrentCons > 1;
                                312              34 :     SimpleStringList *process_list = user_list;
                                313              34 :     ReindexType process_type = type;
                                314                 :     ParallelSlotArray *sa;
                                315              34 :     bool        failed = false;
                                316              34 :     int         items_count = 0;
                                317                 : 
  902 tgl                       318              34 :     conn = connectDatabase(cparams, progname, echo, false, false);
                                319                 : 
 1472 peter                     320              34 :     if (concurrently && PQserverVersion(conn) < 120000)
                                321                 :     {
 1472 peter                     322 UBC           0 :         PQfinish(conn);
  366 tgl                       323               0 :         pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
                                324                 :                  "concurrently", "12");
                                325                 :     }
                                326                 : 
  767 michael                   327 CBC          34 :     if (tablespace && PQserverVersion(conn) < 140000)
                                328                 :     {
  767 michael                   329 UBC           0 :         PQfinish(conn);
  366 tgl                       330               0 :         pg_fatal("cannot use the \"%s\" option on server versions older than PostgreSQL %s",
                                331                 :                  "tablespace", "14");
                                332                 :     }
                                333                 : 
 1352 michael                   334 CBC          34 :     if (!parallel)
                                335                 :     {
                                336              31 :         switch (process_type)
                                337                 :         {
                                338              15 :             case REINDEX_DATABASE:
                                339                 :             case REINDEX_SYSTEM:
                                340                 : 
                                341                 :                 /*
                                342                 :                  * Database and system reindexes only need to work on the
                                343                 :                  * database itself, so build a list with a single entry.
                                344                 :                  */
                                345              15 :                 Assert(user_list == NULL);
                                346              15 :                 process_list = pg_malloc0(sizeof(SimpleStringList));
                                347              15 :                 simple_string_list_append(process_list, PQdb(conn));
                                348              15 :                 break;
                                349                 : 
                                350              16 :             case REINDEX_INDEX:
                                351                 :             case REINDEX_SCHEMA:
                                352                 :             case REINDEX_TABLE:
                                353              16 :                 Assert(user_list != NULL);
                                354              16 :                 break;
                                355                 :         }
                                356                 :     }
                                357                 :     else
                                358                 :     {
                                359               3 :         switch (process_type)
                                360                 :         {
                                361               1 :             case REINDEX_DATABASE:
                                362                 : 
                                363                 :                 /* Build a list of relations from the database */
 1352 michael                   364 GIC           1 :                 process_list = get_parallel_object_list(conn, process_type,
 1352 michael                   365 ECB             :                                                         user_list, echo);
 1352 michael                   366 GIC           1 :                 process_type = REINDEX_TABLE;
 1352 michael                   367 ECB             : 
                                368                 :                 /* Bail out if nothing to process */
 1352 michael                   369 GIC           1 :                 if (process_list == NULL)
 1352 michael                   370 LBC           0 :                     return;
 1352 michael                   371 CBC           1 :                 break;
 1352 michael                   372 ECB             : 
 1352 michael                   373 GIC           2 :             case REINDEX_SCHEMA:
 1352 michael                   374 GBC           2 :                 Assert(user_list != NULL);
                                375                 : 
                                376                 :                 /* Build a list of relations from all the schemas */
                                377               2 :                 process_list = get_parallel_object_list(conn, process_type,
                                378                 :                                                         user_list, echo);
 1352 michael                   379 GIC           2 :                 process_type = REINDEX_TABLE;
 1352 michael                   380 EUB             : 
                                381                 :                 /* Bail out if nothing to process */
 1352 michael                   382 GIC           2 :                 if (process_list == NULL)
                                383               1 :                     return;
                                384               1 :                 break;
                                385                 : 
 1352 michael                   386 UBC           0 :             case REINDEX_SYSTEM:
                                387                 :             case REINDEX_INDEX:
                                388                 :                 /* not supported */
 1352 michael                   389 UIC           0 :                 Assert(false);
                                390                 :                 break;
                                391                 : 
                                392               0 :             case REINDEX_TABLE:
                                393                 : 
                                394                 :                 /*
 1352 michael                   395 ECB             :                  * Fall through.  The list of items for tables is already
                                396                 :                  * created.
                                397                 :                  */
 1352 michael                   398 UIC           0 :                 break;
                                399                 :         }
 1352 michael                   400 ECB             :     }
                                401                 : 
                                402                 :     /*
                                403                 :      * Adjust the number of concurrent connections depending on the items in
                                404                 :      * the list.  We choose the minimum between the number of concurrent
                                405                 :      * connections and the number of items in the list.
                                406                 :      */
 1352 michael                   407 GIC          35 :     for (cell = process_list->head; cell; cell = cell->next)
 1352 michael                   408 ECB             :     {
 1352 michael                   409 CBC          35 :         items_count++;
                                410                 : 
 1352 michael                   411 ECB             :         /* no need to continue if there are more elements than jobs */
 1352 michael                   412 GIC          35 :         if (items_count >= concurrentCons)
                                413              33 :             break;
 1352 michael                   414 ECB             :     }
 1352 michael                   415 CBC          33 :     concurrentCons = Min(concurrentCons, items_count);
 1352 michael                   416 GIC          33 :     Assert(concurrentCons > 0);
 1352 michael                   417 ECB             : 
 1352 michael                   418 GIC          33 :     Assert(process_list != NULL);
 1352 michael                   419 EUB             : 
  759 rhaas                     420 GBC          33 :     sa = ParallelSlotsSetup(concurrentCons, cparams, progname, echo, NULL);
  759 rhaas                     421 GIC          33 :     ParallelSlotsAdoptConn(sa, conn);
                                422                 : 
 1352 michael                   423 CBC          33 :     cell = process_list->head;
 1352 michael                   424 ECB             :     do
                                425                 :     {
 1352 michael                   426 GBC          41 :         const char *objname = cell->val;
                                427              41 :         ParallelSlot *free_slot = NULL;
                                428                 : 
 1352 michael                   429 GIC          41 :         if (CancelRequested)
 1352 michael                   430 ECB             :         {
 1352 michael                   431 LBC           0 :             failed = true;
 1352 michael                   432 UIC           0 :             goto finish;
                                433                 :         }
 1352 michael                   434 ECB             : 
  759 rhaas                     435 CBC          41 :         free_slot = ParallelSlotsGetIdle(sa, NULL);
 1352 michael                   436 GIC          41 :         if (!free_slot)
 1352 michael                   437 ECB             :         {
 1352 michael                   438 LBC           0 :             failed = true;
 1352 michael                   439 UIC           0 :             goto finish;
 1352 michael                   440 ECB             :         }
                                441                 : 
  793 rhaas                     442 GIC          41 :         ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
 1352 michael                   443 CBC          41 :         run_reindex_command(free_slot->connection, process_type, objname,
  767 michael                   444 ECB             :                             echo, verbose, concurrently, true, tablespace);
                                445                 : 
 1352 michael                   446 GIC          41 :         cell = cell->next;
 1352 michael                   447 CBC          41 :     } while (cell != NULL);
 1352 michael                   448 ECB             : 
  759 rhaas                     449 GIC          33 :     if (!ParallelSlotsWaitCompletion(sa))
 1352 michael                   450 CBC           5 :         failed = true;
 1352 michael                   451 ECB             : 
 1352 michael                   452 GIC          28 : finish:
 1349                           453              33 :     if (process_list != user_list)
                                454                 :     {
 1349 michael                   455 CBC          17 :         simple_string_list_destroy(process_list);
 1349 michael                   456 GIC          17 :         pg_free(process_list);
                                457                 :     }
                                458                 : 
  759 rhaas                     459 CBC          33 :     ParallelSlotsTerminate(sa);
                                460              33 :     pfree(sa);
 1352 michael                   461 ECB             : 
 1352 michael                   462 GIC          33 :     if (failed)
                                463               5 :         exit(1);
                                464                 : }
 1352 michael                   465 ECB             : 
                                466                 : static void
 1352 michael                   467 GIC          41 : run_reindex_command(PGconn *conn, ReindexType type, const char *name,
  767 michael                   468 ECB             :                     bool echo, bool verbose, bool concurrently, bool async,
                                469                 :                     const char *tablespace)
 1352                           470                 : {
  767 michael                   471 GIC          41 :     const char *paren = "(";
  767 michael                   472 CBC          41 :     const char *comma = ", ";
  767 michael                   473 GIC          41 :     const char *sep = paren;
 1352 michael                   474 ECB             :     PQExpBufferData sql;
                                475                 :     bool        status;
                                476                 : 
 1352 michael                   477 GIC          41 :     Assert(name);
 1352 michael                   478 ECB             : 
                                479                 :     /* build the REINDEX query */
 6463 bruce                     480 CBC          41 :     initPQExpBuffer(&sql);
 6463 bruce                     481 ECB             : 
 1868 noah                      482 GIC          41 :     appendPQExpBufferStr(&sql, "REINDEX ");
                                483                 : 
 2886 fujii                     484 CBC          41 :     if (verbose)
  767 michael                   485 ECB             :     {
  767 michael                   486 GIC           4 :         appendPQExpBuffer(&sql, "%sVERBOSE", sep);
                                487               4 :         sep = comma;
  767 michael                   488 ECB             :     }
                                489                 : 
  767 michael                   490 CBC          41 :     if (tablespace)
  767 michael                   491 ECB             :     {
  767 michael                   492 CBC           7 :         appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep, fmtId(tablespace));
                                493               7 :         sep = comma;
  767 michael                   494 ECB             :     }
                                495                 : 
  767 michael                   496 CBC          41 :     if (sep != paren)
                                497               9 :         appendPQExpBufferStr(&sql, ") ");
 2886 fujii                     498 ECB             : 
 1377 michael                   499                 :     /* object type */
 1377 michael                   500 CBC          41 :     switch (type)
 1377 michael                   501 ECB             :     {
 1377 michael                   502 CBC          12 :         case REINDEX_DATABASE:
                                503              12 :             appendPQExpBufferStr(&sql, "DATABASE ");
                                504              12 :             break;
 1377 michael                   505 GIC           4 :         case REINDEX_INDEX:
                                506               4 :             appendPQExpBufferStr(&sql, "INDEX ");
                                507               4 :             break;
                                508               2 :         case REINDEX_SCHEMA:
                                509               2 :             appendPQExpBufferStr(&sql, "SCHEMA ");
                                510               2 :             break;
                                511               3 :         case REINDEX_SYSTEM:
 1377 michael                   512 CBC           3 :             appendPQExpBufferStr(&sql, "SYSTEM ");
                                513               3 :             break;
 1377 michael                   514 GIC          20 :         case REINDEX_TABLE:
                                515              20 :             appendPQExpBufferStr(&sql, "TABLE ");
 1377 michael                   516 CBC          20 :             break;
                                517                 :     }
 1377 michael                   518 ECB             : 
                                519                 :     /*
  767                           520                 :      * Parenthesized grammar is only supported for CONCURRENTLY since
                                521                 :      * PostgreSQL 14.  Since 12, CONCURRENTLY can be specified after the
                                522                 :      * object type.
                                523                 :      */
 1472 peter                     524 CBC          41 :     if (concurrently)
                                525              17 :         appendPQExpBufferStr(&sql, "CONCURRENTLY ");
 1377 michael                   526 ECB             : 
                                527                 :     /* object name */
 1377 michael                   528 CBC          41 :     switch (type)
                                529                 :     {
 1377 michael                   530 GIC          15 :         case REINDEX_DATABASE:
                                531                 :         case REINDEX_SYSTEM:
 1352 michael                   532 CBC          15 :             appendPQExpBufferStr(&sql, fmtId(name));
 1377 michael                   533 GIC          15 :             break;
 1377 michael                   534 CBC          24 :         case REINDEX_INDEX:
                                535                 :         case REINDEX_TABLE:
 1360                           536              24 :             appendQualifiedRelation(&sql, name, conn, echo);
 1377                           537              24 :             break;
 1377 michael                   538 GIC           2 :         case REINDEX_SCHEMA:
 1377 michael                   539 CBC           2 :             appendPQExpBufferStr(&sql, name);
 1377 michael                   540 GIC           2 :             break;
                                541                 :     }
 1377 michael                   542 EUB             : 
                                543                 :     /* finish the query */
 2838 heikki.linnakangas        544 CBC          41 :     appendPQExpBufferChar(&sql, ';');
                                545                 : 
 1352 michael                   546 GBC          41 :     if (async)
                                547                 :     {
                                548              41 :         if (echo)
                                549              10 :             printf("%s\n", sql.data);
                                550                 : 
                                551              41 :         status = PQsendQuery(conn, sql.data) == 1;
 1352 michael                   552 EUB             :     }
                                553                 :     else
 1352 michael                   554 UIC           0 :         status = executeMaintenanceCommand(conn, sql.data, echo);
 1352 michael                   555 EUB             : 
 1352 michael                   556 GBC          41 :     if (!status)
 6463 bruce                     557 EUB             :     {
 1377 michael                   558 UIC           0 :         switch (type)
 1377 michael                   559 EUB             :         {
 1377 michael                   560 UBC           0 :             case REINDEX_DATABASE:
                                561               0 :                 pg_log_error("reindexing of database \"%s\" failed: %s",
                                562                 :                              PQdb(conn), PQerrorMessage(conn));
                                563               0 :                 break;
                                564               0 :             case REINDEX_INDEX:
                                565               0 :                 pg_log_error("reindexing of index \"%s\" in database \"%s\" failed: %s",
                                566                 :                              name, PQdb(conn), PQerrorMessage(conn));
                                567               0 :                 break;
 1377 michael                   568 UIC           0 :             case REINDEX_SCHEMA:
 1377 michael                   569 UBC           0 :                 pg_log_error("reindexing of schema \"%s\" in database \"%s\" failed: %s",
                                570                 :                              name, PQdb(conn), PQerrorMessage(conn));
                                571               0 :                 break;
                                572               0 :             case REINDEX_SYSTEM:
 1066 peter                     573 UIC           0 :                 pg_log_error("reindexing of system catalogs in database \"%s\" failed: %s",
                                574                 :                              PQdb(conn), PQerrorMessage(conn));
 1377 michael                   575               0 :                 break;
 1377 michael                   576 LBC           0 :             case REINDEX_TABLE:
                                577               0 :                 pg_log_error("reindexing of table \"%s\" in database \"%s\" failed: %s",
                                578                 :                              name, PQdb(conn), PQerrorMessage(conn));
 1377 michael                   579 UIC           0 :                 break;
                                580                 :         }
 1352                           581               0 :         if (!async)
                                582                 :         {
                                583               0 :             PQfinish(conn);
                                584               0 :             exit(1);
                                585                 :         }
                                586                 :     }
                                587                 : 
 6463 bruce                     588 CBC          41 :     termPQExpBuffer(&sql);
 6463 bruce                     589 GIC          41 : }
                                590                 : 
                                591                 : /*
                                592                 :  * Prepare the list of objects to process by querying the catalogs.
                                593                 :  *
                                594                 :  * This function will return a SimpleStringList object containing the entire
                                595                 :  * list of tables in the given database that should be processed by a parallel
                                596                 :  * database-wide reindex (excluding system tables), or NULL if there's no such
                                597                 :  * table.
 1352 michael                   598 ECB             :  */
                                599                 : static SimpleStringList *
 1352 michael                   600 GIC           3 : get_parallel_object_list(PGconn *conn, ReindexType type,
                                601                 :                          SimpleStringList *user_list, bool echo)
                                602                 : {
                                603                 :     PQExpBufferData catalog_query;
 1352 michael                   604 ECB             :     PQExpBufferData buf;
                                605                 :     PGresult   *res;
                                606                 :     SimpleStringList *tables;
                                607                 :     int         ntups,
                                608                 :                 i;
                                609                 : 
 1352 michael                   610 GIC           3 :     initPQExpBuffer(&catalog_query);
                                611                 : 
                                612                 :     /*
                                613                 :      * The queries here are using a safe search_path, so there's no need to
                                614                 :      * fully qualify everything.
                                615                 :      */
                                616               3 :     switch (type)
                                617                 :     {
 1352 michael                   618 CBC           1 :         case REINDEX_DATABASE:
 1352 michael                   619 GIC           1 :             Assert(user_list == NULL);
  906 drowley                   620 CBC           1 :             appendPQExpBufferStr(&catalog_query,
                                621                 :                                  "SELECT c.relname, ns.nspname\n"
                                622                 :                                  " FROM pg_catalog.pg_class c\n"
  906 drowley                   623 ECB             :                                  " JOIN pg_catalog.pg_namespace ns"
                                624                 :                                  " ON c.relnamespace = ns.oid\n"
                                625                 :                                  " WHERE ns.nspname != 'pg_catalog'\n"
                                626                 :                                  "   AND c.relkind IN ("
                                627                 :                                  CppAsString2(RELKIND_RELATION) ", "
                                628                 :                                  CppAsString2(RELKIND_MATVIEW) ")\n"
                                629                 :                                  " ORDER BY c.relpages DESC;");
 1352 michael                   630 GIC           1 :             break;
 1352 michael                   631 ECB             : 
 1352 michael                   632 GIC           2 :         case REINDEX_SCHEMA:
                                633                 :             {
                                634                 :                 SimpleStringListCell *cell;
                                635               2 :                 bool        nsp_listed = false;
                                636                 : 
                                637               2 :                 Assert(user_list != NULL);
                                638                 : 
                                639                 :                 /*
                                640                 :                  * All the tables from all the listed schemas are grabbed at
 1352 michael                   641 ECB             :                  * once.
                                642                 :                  */
  906 drowley                   643 CBC           2 :                 appendPQExpBufferStr(&catalog_query,
                                644                 :                                      "SELECT c.relname, ns.nspname\n"
  906 drowley                   645 ECB             :                                      " FROM pg_catalog.pg_class c\n"
                                646                 :                                      " JOIN pg_catalog.pg_namespace ns"
                                647                 :                                      " ON c.relnamespace = ns.oid\n"
                                648                 :                                      " WHERE c.relkind IN ("
                                649                 :                                      CppAsString2(RELKIND_RELATION) ", "
                                650                 :                                      CppAsString2(RELKIND_MATVIEW) ")\n"
                                651                 :                                      " AND ns.nspname IN (");
                                652                 : 
 1352 michael                   653 CBC           5 :                 for (cell = user_list->head; cell; cell = cell->next)
                                654                 :                 {
 1352 michael                   655 GIC           3 :                     const char *nspname = cell->val;
 1352 michael                   656 ECB             : 
 1352 michael                   657 GIC           3 :                     if (nsp_listed)
  906 drowley                   658 GBC           1 :                         appendPQExpBufferStr(&catalog_query, ", ");
                                659                 :                     else
 1352 michael                   660 GIC           2 :                         nsp_listed = true;
 1352 michael                   661 EUB             : 
 1352 michael                   662 GIC           3 :                     appendStringLiteralConn(&catalog_query, nspname, conn);
                                663                 :                 }
                                664                 : 
  906 drowley                   665 CBC           2 :                 appendPQExpBufferStr(&catalog_query, ")\n"
  906 drowley                   666 ECB             :                                      " ORDER BY c.relpages DESC;");
                                667                 :             }
 1352 michael                   668 GIC           2 :             break;
                                669                 : 
 1352 michael                   670 UIC           0 :         case REINDEX_SYSTEM:
 1352 michael                   671 ECB             :         case REINDEX_INDEX:
                                672                 :         case REINDEX_TABLE:
 1352 michael                   673 UIC           0 :             Assert(false);
 1352 michael                   674 ECB             :             break;
                                675                 :     }
                                676                 : 
 1352 michael                   677 GIC           3 :     res = executeQuery(conn, catalog_query.data, echo);
                                678               3 :     termPQExpBuffer(&catalog_query);
 1352 michael                   679 ECB             : 
                                680                 :     /*
                                681                 :      * If no rows are returned, there are no matching tables, so we are done.
                                682                 :      */
 1352 michael                   683 CBC           3 :     ntups = PQntuples(res);
 1352 michael                   684 GIC           3 :     if (ntups == 0)
 1352 michael                   685 ECB             :     {
 1352 michael                   686 CBC           1 :         PQclear(res);
                                687               1 :         PQfinish(conn);
 1352 michael                   688 GIC           1 :         return NULL;
 1352 michael                   689 ECB             :     }
                                690                 : 
 1352 michael                   691 GIC           2 :     tables = pg_malloc0(sizeof(SimpleStringList));
 1352 michael                   692 ECB             : 
                                693                 :     /* Build qualified identifiers for each table */
 1352 michael                   694 GIC           2 :     initPQExpBuffer(&buf);
 1352 michael                   695 CBC          12 :     for (i = 0; i < ntups; i++)
                                696                 :     {
 1352 michael                   697 GIC          10 :         appendPQExpBufferStr(&buf,
                                698              10 :                              fmtQualifiedId(PQgetvalue(res, i, 1),
 1352 michael                   699 CBC          10 :                                             PQgetvalue(res, i, 0)));
                                700                 : 
 1352 michael                   701 GIC          10 :         simple_string_list_append(tables, buf.data);
                                702              10 :         resetPQExpBuffer(&buf);
                                703                 :     }
                                704               2 :     termPQExpBuffer(&buf);
                                705               2 :     PQclear(res);
                                706                 : 
                                707               2 :     return tables;
 1352 michael                   708 ECB             : }
                                709                 : 
 6463 bruce                     710                 : static void
  902 tgl                       711 GIC           2 : reindex_all_databases(ConnParams *cparams,
 1472 peter                     712 ECB             :                       const char *progname, bool echo, bool quiet, bool verbose,
                                713                 :                       bool concurrently, int concurrentCons,
  767 michael                   714                 :                       const char *tablespace)
                                715                 : {
 6385 bruce                     716                 :     PGconn     *conn;
                                717                 :     PGresult   *result;
                                718                 :     int         i;
 6463                           719                 : 
  902 tgl                       720 GIC           2 :     conn = connectMaintenanceDatabase(cparams, progname, echo);
 1360 michael                   721               2 :     result = executeQuery(conn, "SELECT datname FROM pg_database WHERE datallowconn ORDER BY 1;", echo);
 6463 bruce                     722 CBC           2 :     PQfinish(conn);
                                723                 : 
                                724              11 :     for (i = 0; i < PQntuples(result); i++)
                                725                 :     {
 6385 bruce                     726 GIC           9 :         char       *dbname = PQgetvalue(result, i, 0);
                                727                 : 
 6463                           728               9 :         if (!quiet)
 5788 peter_e                   729 ECB             :         {
 5788 peter_e                   730 CBC           9 :             printf(_("%s: reindexing database \"%s\"\n"), progname, dbname);
 5788 peter_e                   731 GIC           9 :             fflush(stdout);
                                732                 :         }
 6463 bruce                     733 ECB             : 
  902 tgl                       734 GIC           9 :         cparams->override_dbname = dbname;
 2435 noah                      735 ECB             : 
  902 tgl                       736 CBC           9 :         reindex_one_database(cparams, REINDEX_DATABASE, NULL,
 1352 michael                   737 ECB             :                              progname, echo, verbose, concurrently,
  767                           738                 :                              concurrentCons, tablespace);
 6463 bruce                     739                 :     }
                                740                 : 
 6463 bruce                     741 CBC           2 :     PQclear(result);
                                742               2 : }
 6463 bruce                     743 ECB             : 
                                744                 : static void
 6463 bruce                     745 CBC           1 : help(const char *progname)
 6463 bruce                     746 ECB             : {
 6463 bruce                     747 CBC           1 :     printf(_("%s reindexes a PostgreSQL database.\n\n"), progname);
                                748               1 :     printf(_("Usage:\n"));
                                749               1 :     printf(_("  %s [OPTION]... [DBNAME]\n"), progname);
                                750               1 :     printf(_("\nOptions:\n"));
  767 michael                   751               1 :     printf(_("  -a, --all                    reindex all databases\n"));
                                752               1 :     printf(_("      --concurrently           reindex concurrently\n"));
                                753               1 :     printf(_("  -d, --dbname=DBNAME          database to reindex\n"));
                                754               1 :     printf(_("  -e, --echo                   show the commands being sent to the server\n"));
                                755               1 :     printf(_("  -i, --index=INDEX            recreate specific index(es) only\n"));
                                756               1 :     printf(_("  -j, --jobs=NUM               use this many concurrent connections to reindex\n"));
                                757               1 :     printf(_("  -q, --quiet                  don't write any messages\n"));
  529 magnus                    758               1 :     printf(_("  -s, --system                 reindex system catalogs only\n"));
  767 michael                   759               1 :     printf(_("  -S, --schema=SCHEMA          reindex specific schema(s) only\n"));
                                760               1 :     printf(_("  -t, --table=TABLE            reindex specific table(s) only\n"));
                                761               1 :     printf(_("      --tablespace=TABLESPACE  tablespace where indexes are rebuilt\n"));
                                762               1 :     printf(_("  -v, --verbose                write a lot of output\n"));
                                763               1 :     printf(_("  -V, --version                output version information, then exit\n"));
  767 michael                   764 GIC           1 :     printf(_("  -?, --help                   show this help, then exit\n"));
 6463 bruce                     765               1 :     printf(_("\nConnection options:\n"));
  767 michael                   766               1 :     printf(_("  -h, --host=HOSTNAME          database server host or socket directory\n"));
                                767               1 :     printf(_("  -p, --port=PORT              database server port\n"));
                                768               1 :     printf(_("  -U, --username=USERNAME      user name to connect as\n"));
                                769               1 :     printf(_("  -w, --no-password            never prompt for password\n"));
                                770               1 :     printf(_("  -W, --password               force password prompt\n"));
                                771               1 :     printf(_("  --maintenance-db=DBNAME      alternate maintenance database\n"));
 6463 bruce                     772               1 :     printf(_("\nRead the description of the SQL command REINDEX for details.\n"));
 1136 peter                     773               1 :     printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
                                774               1 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
 6463 bruce                     775               1 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a