LCOV - code coverage report
Current view: top level - src/bin/scripts - pg_isready.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 86 130 66.2 %
Date: 2024-04-20 00:11:33 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pg_isready --- checks the status of the PostgreSQL server
       4             :  *
       5             :  * Copyright (c) 2013-2024, PostgreSQL Global Development Group
       6             :  *
       7             :  * src/bin/scripts/pg_isready.c
       8             :  *
       9             :  *-------------------------------------------------------------------------
      10             :  */
      11             : 
      12             : #include "postgres_fe.h"
      13             : #include "common.h"
      14             : #include "common/logging.h"
      15             : #include "fe_utils/option_utils.h"
      16             : 
      17             : #define DEFAULT_CONNECT_TIMEOUT "3"
      18             : 
      19             : static void
      20             :             help(const char *progname);
      21             : 
      22             : int
      23          10 : main(int argc, char **argv)
      24             : {
      25             :     int         c;
      26             : 
      27             :     const char *progname;
      28             : 
      29          10 :     const char *pghost = NULL;
      30          10 :     const char *pgport = NULL;
      31          10 :     const char *pguser = NULL;
      32          10 :     const char *pgdbname = NULL;
      33          10 :     const char *connect_timeout = DEFAULT_CONNECT_TIMEOUT;
      34             : 
      35          10 :     const char *pghost_str = NULL;
      36          10 :     const char *pghostaddr_str = NULL;
      37          10 :     const char *pgport_str = NULL;
      38             : 
      39             : #define PARAMS_ARRAY_SIZE   7
      40             : 
      41             :     const char *keywords[PARAMS_ARRAY_SIZE];
      42             :     const char *values[PARAMS_ARRAY_SIZE];
      43             : 
      44          10 :     bool        quiet = false;
      45             : 
      46             :     PGPing      rv;
      47          10 :     PQconninfoOption *opts = NULL;
      48          10 :     PQconninfoOption *defs = NULL;
      49             :     PQconninfoOption *opt;
      50             :     PQconninfoOption *def;
      51          10 :     char       *errmsg = NULL;
      52             : 
      53             :     /*
      54             :      * We accept user and database as options to avoid useless errors from
      55             :      * connecting with invalid params
      56             :      */
      57             : 
      58             :     static struct option long_options[] = {
      59             :         {"dbname", required_argument, NULL, 'd'},
      60             :         {"host", required_argument, NULL, 'h'},
      61             :         {"port", required_argument, NULL, 'p'},
      62             :         {"quiet", no_argument, NULL, 'q'},
      63             :         {"timeout", required_argument, NULL, 't'},
      64             :         {"username", required_argument, NULL, 'U'},
      65             :         {NULL, 0, NULL, 0}
      66             :     };
      67             : 
      68          10 :     pg_logging_init(argv[0]);
      69          10 :     progname = get_progname(argv[0]);
      70          10 :     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pgscripts"));
      71          10 :     handle_help_version_opts(argc, argv, progname, help);
      72             : 
      73           8 :     while ((c = getopt_long(argc, argv, "d:h:p:qt:U:", long_options, NULL)) != -1)
      74             :     {
      75           4 :         switch (c)
      76             :         {
      77           0 :             case 'd':
      78           0 :                 pgdbname = pg_strdup(optarg);
      79           0 :                 break;
      80           0 :             case 'h':
      81           0 :                 pghost = pg_strdup(optarg);
      82           0 :                 break;
      83           0 :             case 'p':
      84           0 :                 pgport = pg_strdup(optarg);
      85           0 :                 break;
      86           0 :             case 'q':
      87           0 :                 quiet = true;
      88           0 :                 break;
      89           2 :             case 't':
      90           2 :                 connect_timeout = pg_strdup(optarg);
      91           2 :                 break;
      92           0 :             case 'U':
      93           0 :                 pguser = pg_strdup(optarg);
      94           0 :                 break;
      95           2 :             default:
      96             :                 /* getopt_long already emitted a complaint */
      97           2 :                 pg_log_error_hint("Try \"%s --help\" for more information.", progname);
      98             : 
      99             :                 /*
     100             :                  * We need to make sure we don't return 1 here because someone
     101             :                  * checking the return code might infer unintended meaning
     102             :                  */
     103           2 :                 exit(PQPING_NO_ATTEMPT);
     104             :         }
     105             :     }
     106             : 
     107           4 :     if (optind < argc)
     108             :     {
     109           0 :         pg_log_error("too many command-line arguments (first is \"%s\")",
     110             :                      argv[optind]);
     111           0 :         pg_log_error_hint("Try \"%s --help\" for more information.", progname);
     112             : 
     113             :         /*
     114             :          * We need to make sure we don't return 1 here because someone
     115             :          * checking the return code might infer unintended meaning
     116             :          */
     117           0 :         exit(PQPING_NO_ATTEMPT);
     118             :     }
     119             : 
     120           4 :     keywords[0] = "host";
     121           4 :     values[0] = pghost;
     122           4 :     keywords[1] = "port";
     123           4 :     values[1] = pgport;
     124           4 :     keywords[2] = "user";
     125           4 :     values[2] = pguser;
     126           4 :     keywords[3] = "dbname";
     127           4 :     values[3] = pgdbname;
     128           4 :     keywords[4] = "connect_timeout";
     129           4 :     values[4] = connect_timeout;
     130           4 :     keywords[5] = "fallback_application_name";
     131           4 :     values[5] = progname;
     132           4 :     keywords[6] = NULL;
     133           4 :     values[6] = NULL;
     134             : 
     135             :     /*
     136             :      * Get the host and port so we can display them in our output
     137             :      */
     138           4 :     if (pgdbname &&
     139           0 :         (strncmp(pgdbname, "postgresql://", 13) == 0 ||
     140           0 :          strncmp(pgdbname, "postgres://", 11) == 0 ||
     141           0 :          strchr(pgdbname, '=') != NULL))
     142             :     {
     143           0 :         opts = PQconninfoParse(pgdbname, &errmsg);
     144           0 :         if (opts == NULL)
     145             :         {
     146           0 :             pg_log_error("%s", errmsg);
     147           0 :             exit(PQPING_NO_ATTEMPT);
     148             :         }
     149             :     }
     150             : 
     151           4 :     defs = PQconndefaults();
     152           4 :     if (defs == NULL)
     153             :     {
     154           0 :         pg_log_error("could not fetch default options");
     155           0 :         exit(PQPING_NO_ATTEMPT);
     156             :     }
     157             : 
     158         168 :     for (opt = opts, def = defs; def->keyword; def++)
     159             :     {
     160         164 :         if (strcmp(def->keyword, "host") == 0)
     161             :         {
     162           4 :             if (opt && opt->val)
     163           0 :                 pghost_str = opt->val;
     164           4 :             else if (pghost)
     165           0 :                 pghost_str = pghost;
     166           4 :             else if (def->val)
     167           4 :                 pghost_str = def->val;
     168             :             else
     169           0 :                 pghost_str = DEFAULT_PGSOCKET_DIR;
     170             :         }
     171         160 :         else if (strcmp(def->keyword, "hostaddr") == 0)
     172             :         {
     173           4 :             if (opt && opt->val)
     174           0 :                 pghostaddr_str = opt->val;
     175           4 :             else if (def->val)
     176           0 :                 pghostaddr_str = def->val;
     177             :         }
     178         156 :         else if (strcmp(def->keyword, "port") == 0)
     179             :         {
     180           4 :             if (opt && opt->val)
     181           0 :                 pgport_str = opt->val;
     182           4 :             else if (pgport)
     183           0 :                 pgport_str = pgport;
     184           4 :             else if (def->val)
     185           4 :                 pgport_str = def->val;
     186             :         }
     187             : 
     188         164 :         if (opt)
     189           0 :             opt++;
     190             :     }
     191             : 
     192           4 :     rv = PQpingParams(keywords, values, 1);
     193             : 
     194           4 :     if (!quiet)
     195             :     {
     196           4 :         printf("%s:%s - ",
     197             :                pghostaddr_str != NULL ? pghostaddr_str : pghost_str,
     198             :                pgport_str);
     199             : 
     200           4 :         switch (rv)
     201             :         {
     202           2 :             case PQPING_OK:
     203           2 :                 printf(_("accepting connections\n"));
     204           2 :                 break;
     205           0 :             case PQPING_REJECT:
     206           0 :                 printf(_("rejecting connections\n"));
     207           0 :                 break;
     208           2 :             case PQPING_NO_RESPONSE:
     209           2 :                 printf(_("no response\n"));
     210           2 :                 break;
     211           0 :             case PQPING_NO_ATTEMPT:
     212           0 :                 printf(_("no attempt\n"));
     213           0 :                 break;
     214           0 :             default:
     215           0 :                 printf(_("unknown\n"));
     216             :         }
     217           0 :     }
     218             : 
     219           4 :     exit(rv);
     220             : }
     221             : 
     222             : static void
     223           2 : help(const char *progname)
     224             : {
     225           2 :     printf(_("%s issues a connection check to a PostgreSQL database.\n\n"), progname);
     226           2 :     printf(_("Usage:\n"));
     227           2 :     printf(_("  %s [OPTION]...\n"), progname);
     228             : 
     229           2 :     printf(_("\nOptions:\n"));
     230           2 :     printf(_("  -d, --dbname=DBNAME      database name\n"));
     231           2 :     printf(_("  -q, --quiet              run quietly\n"));
     232           2 :     printf(_("  -V, --version            output version information, then exit\n"));
     233           2 :     printf(_("  -?, --help               show this help, then exit\n"));
     234             : 
     235           2 :     printf(_("\nConnection options:\n"));
     236           2 :     printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
     237           2 :     printf(_("  -p, --port=PORT          database server port\n"));
     238           2 :     printf(_("  -t, --timeout=SECS       seconds to wait when attempting connection, 0 disables (default: %s)\n"), DEFAULT_CONNECT_TIMEOUT);
     239           2 :     printf(_("  -U, --username=USERNAME  user name to connect as\n"));
     240           2 :     printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
     241           2 :     printf(_("%s home page: <%s>\n"), PACKAGE_NAME, PACKAGE_URL);
     242           2 : }

Generated by: LCOV version 1.14