LCOV - differential code coverage report
Current view: top level - src/bin/scripts - common.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 68.1 % 47 32 15 32
Current Date: 2023-04-08 17:13:01 Functions: 66.7 % 3 2 1 2
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 68.1 % 47 32 15 32
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 66.7 % 3 2 1 2

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  *  common.c
                                  4                 :  *      Common support routines for bin/scripts/
                                  5                 :  *
                                  6                 :  *
                                  7                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  8                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  9                 :  *
                                 10                 :  * src/bin/scripts/common.c
                                 11                 :  *
                                 12                 :  *-------------------------------------------------------------------------
                                 13                 :  */
                                 14                 : 
                                 15                 : #include "postgres_fe.h"
                                 16                 : 
                                 17                 : #include <signal.h>
                                 18                 : #include <unistd.h>
                                 19                 : 
                                 20                 : #include "common.h"
                                 21                 : #include "common/connect.h"
                                 22                 : #include "common/logging.h"
                                 23                 : #include "common/string.h"
                                 24                 : #include "fe_utils/cancel.h"
                                 25                 : #include "fe_utils/query_utils.h"
                                 26                 : #include "fe_utils/string_utils.h"
                                 27                 : 
                                 28                 : /*
                                 29                 :  * Split TABLE[(COLUMNS)] into TABLE and [(COLUMNS)] portions.  When you
                                 30                 :  * finish using them, pg_free(*table).  *columns is a pointer into "spec",
                                 31                 :  * possibly to its NUL terminator.
                                 32                 :  */
                                 33                 : void
 1531 michael                    34 CBC          36 : splitTableColumnsSpec(const char *spec, int encoding,
                                 35                 :                       char **table, const char **columns)
                                 36                 : {
 1868 noah                       37              36 :     bool        inquotes = false;
                                 38              36 :     const char *cp = spec;
                                 39                 : 
                                 40                 :     /*
                                 41                 :      * Find the first '(' not identifier-quoted.  Based on
                                 42                 :      * dequote_downcase_identifier().
                                 43                 :      */
                                 44             474 :     while (*cp && (*cp != '(' || inquotes))
                                 45                 :     {
                                 46             438 :         if (*cp == '"')
                                 47                 :         {
                                 48               3 :             if (inquotes && cp[1] == '"')
                                 49               1 :                 cp++;           /* pair does not affect quoting */
                                 50                 :             else
                                 51               2 :                 inquotes = !inquotes;
                                 52               3 :             cp++;
                                 53                 :         }
                                 54                 :         else
  671 tgl                        55             435 :             cp += PQmblenBounded(cp, encoding);
                                 56                 :     }
 1222 alvherre                   57              36 :     *table = pnstrdup(spec, cp - spec);
 1868 noah                       58              36 :     *columns = cp;
                                 59              36 : }
                                 60                 : 
                                 61                 : /*
                                 62                 :  * Break apart TABLE[(COLUMNS)] of "spec".  With the reset_val of search_path
                                 63                 :  * in effect, have regclassin() interpret the TABLE portion.  Append to "buf"
                                 64                 :  * the qualified name of TABLE, followed by any (COLUMNS).  Exit on failure.
                                 65                 :  * We use this to interpret --table=foo under the search path psql would get,
                                 66                 :  * in advance of "ANALYZE public.foo" under the always-secure search path.
                                 67                 :  */
                                 68                 : void
                                 69              26 : appendQualifiedRelation(PQExpBuffer buf, const char *spec,
                                 70                 :                         PGconn *conn, bool echo)
                                 71                 : {
                                 72                 :     char       *table;
                                 73                 :     const char *columns;
                                 74                 :     PQExpBufferData sql;
                                 75                 :     PGresult   *res;
                                 76                 :     int         ntups;
                                 77                 : 
 1531 michael                    78              26 :     splitTableColumnsSpec(spec, PQclientEncoding(conn), &table, &columns);
                                 79                 : 
                                 80                 :     /*
                                 81                 :      * Query must remain ABSOLUTELY devoid of unqualified names.  This would
                                 82                 :      * be unnecessary given a regclassin() variant taking a search_path
                                 83                 :      * argument.
                                 84                 :      */
 1868 noah                       85              26 :     initPQExpBuffer(&sql);
                                 86              26 :     appendPQExpBufferStr(&sql,
                                 87                 :                          "SELECT c.relname, ns.nspname\n"
                                 88                 :                          " FROM pg_catalog.pg_class c,"
                                 89                 :                          " pg_catalog.pg_namespace ns\n"
                                 90                 :                          " WHERE c.relnamespace OPERATOR(pg_catalog.=) ns.oid\n"
                                 91                 :                          "  AND c.oid OPERATOR(pg_catalog.=) ");
                                 92              26 :     appendStringLiteralConn(&sql, table, conn);
                                 93              26 :     appendPQExpBufferStr(&sql, "::pg_catalog.regclass;");
                                 94                 : 
 1360 michael                    95              26 :     executeCommand(conn, "RESET search_path;", echo);
                                 96                 : 
                                 97                 :     /*
                                 98                 :      * One row is a typical result, as is a nonexistent relation ERROR.
                                 99                 :      * regclassin() unconditionally accepts all-digits input as an OID; if no
                                100                 :      * relation has that OID; this query returns no rows.  Catalog corruption
                                101                 :      * might elicit other row counts.
                                102                 :      */
                                103              26 :     res = executeQuery(conn, sql.data, echo);
 1868 noah                      104              25 :     ntups = PQntuples(res);
                                105              25 :     if (ntups != 1)
                                106                 :     {
 1469 peter                     107 UBC           0 :         pg_log_error(ngettext("query returned %d row instead of one: %s",
                                108                 :                               "query returned %d rows instead of one: %s",
                                109                 :                               ntups),
                                110                 :                      ntups, sql.data);
 1868 noah                      111               0 :         PQfinish(conn);
                                112               0 :         exit(1);
                                113                 :     }
 1868 noah                      114 CBC          25 :     appendPQExpBufferStr(buf,
 1696 tgl                       115              25 :                          fmtQualifiedId(PQgetvalue(res, 0, 1),
 1868 noah                      116              25 :                                         PQgetvalue(res, 0, 0)));
                                117              25 :     appendPQExpBufferStr(buf, columns);
                                118              25 :     PQclear(res);
                                119              25 :     termPQExpBuffer(&sql);
                                120              25 :     pg_free(table);
                                121                 : 
 1360 michael                   122              25 :     PQclear(executeQuery(conn, ALWAYS_SECURE_SEARCH_PATH_SQL, echo));
 1868 noah                      123              25 : }
                                124                 : 
                                125                 : 
                                126                 : /*
                                127                 :  * Check yes/no answer in a localized way.  1=yes, 0=no, -1=neither.
                                128                 :  */
                                129                 : 
                                130                 : /* translator: abbreviation for "yes" */
                                131                 : #define PG_YESLETTER gettext_noop("y")
                                132                 : /* translator: abbreviation for "no" */
                                133                 : #define PG_NOLETTER gettext_noop("n")
                                134                 : 
                                135                 : bool
 6043 peter_e                   136 UBC           0 : yesno_prompt(const char *question)
                                137                 : {
                                138                 :     char        prompt[256];
                                139                 : 
                                140                 :     /*------
                                141                 :        translator: This is a question followed by the translated options for
                                142                 :        "yes" and "no". */
 6032 bruce                     143               0 :     snprintf(prompt, sizeof(prompt), _("%s (%s/%s) "),
                                144                 :              _(question), _(PG_YESLETTER), _(PG_NOLETTER));
                                145                 : 
                                146                 :     for (;;)
 6043 peter_e                   147               0 :     {
                                148                 :         char       *resp;
                                149                 : 
  948 tgl                       150               0 :         resp = simple_prompt(prompt, true);
                                151                 : 
 6043 peter_e                   152               0 :         if (strcmp(resp, _(PG_YESLETTER)) == 0)
                                153                 :         {
  948 tgl                       154               0 :             free(resp);
 6043 peter_e                   155               0 :             return true;
                                156                 :         }
 2413 tgl                       157               0 :         if (strcmp(resp, _(PG_NOLETTER)) == 0)
                                158                 :         {
  948                           159               0 :             free(resp);
 6043 peter_e                   160               0 :             return false;
                                161                 :         }
  948 tgl                       162               0 :         free(resp);
                                163                 : 
 6043                           164               0 :         printf(_("Please answer \"%s\" or \"%s\".\n"),
                                165                 :                _(PG_YESLETTER), _(PG_NOLETTER));
                                166                 :     }
                                167                 : }
        

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