LCOV - differential code coverage report
Current view: top level - src/common - percentrepl.c (source / functions) Coverage Total Hit UNC GNC
Current: Differential Code Coverage HEAD vs 15 Lines: 66.7 % 30 20 10 20
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 1 1 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * percentrepl.c
       4                 :  *    Common routines to replace percent placeholders in strings
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/common/percentrepl.c
      12                 :  *
      13                 :  *-------------------------------------------------------------------------
      14                 :  */
      15                 : 
      16                 : #ifndef FRONTEND
      17                 : #include "postgres.h"
      18                 : #else
      19                 : #include "postgres_fe.h"
      20                 : #include "common/logging.h"
      21                 : #endif
      22                 : 
      23                 : #include "common/percentrepl.h"
      24                 : #include "lib/stringinfo.h"
      25                 : 
      26                 : /*
      27                 :  * replace_percent_placeholders
      28                 :  *
      29                 :  * Replace percent-letter placeholders in input string with the supplied
      30                 :  * values.  For example, to replace %f with foo and %b with bar, call
      31                 :  *
      32                 :  * replace_percent_placeholders(instr, "param_name", "bf", bar, foo);
      33                 :  *
      34                 :  * The return value is palloc'd.
      35                 :  *
      36                 :  * "%%" is replaced by a single "%".
      37                 :  *
      38                 :  * This throws an error for an unsupported placeholder or a "%" at the end of
      39                 :  * the input string.
      40                 :  *
      41                 :  * A value may be NULL.  If the corresponding placeholder is found in the
      42                 :  * input string, it will be treated as if an unsupported placeholder was used.
      43                 :  * This allows callers to share a "letters" specification but vary the
      44                 :  * actually supported placeholders at run time.
      45                 :  *
      46                 :  * This functions is meant for cases where all the values are readily
      47                 :  * available or cheap to compute and most invocations will use most values
      48                 :  * (for example for archive_command).  Also, it requires that all values are
      49                 :  * strings.  It won't be a good match for things like log prefixes or prompts
      50                 :  * that use a mix of data types and any invocation will only use a few of the
      51                 :  * possible values.
      52                 :  *
      53                 :  * param_name is the name of the underlying GUC parameter, for error
      54                 :  * reporting.  At the moment, this function is only used for GUC parameters.
      55                 :  * If other kinds of uses were added, the error reporting would need to be
      56                 :  * revised.
      57                 :  */
      58                 : char *
      59 GNC         165 : replace_percent_placeholders(const char *instr, const char *param_name, const char *letters,...)
      60                 : {
      61                 :     StringInfoData result;
      62                 : 
      63             165 :     initStringInfo(&result);
      64                 : 
      65           16917 :     for (const char *sp = instr; *sp; sp++)
      66                 :     {
      67           16752 :         if (*sp == '%')
      68                 :         {
      69             316 :             if (sp[1] == '%')
      70                 :             {
      71                 :                 /* Convert %% to a single % */
      72 UNC           0 :                 sp++;
      73               0 :                 appendStringInfoChar(&result, *sp);
      74                 :             }
      75 GNC         316 :             else if (sp[1] == '\0')
      76                 :             {
      77                 :                 /* Incomplete escape sequence, expected a character afterward */
      78                 : #ifdef FRONTEND
      79 UNC           0 :                 pg_log_error("invalid value for parameter \"%s\": \"%s\"", param_name, instr);
      80               0 :                 pg_log_error_detail("String ends unexpectedly after escape character \"%%\".");
      81               0 :                 exit(1);
      82                 : #else
      83               0 :                 ereport(ERROR,
      84                 :                         errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      85                 :                         errmsg("invalid value for parameter \"%s\": \"%s\"", param_name, instr),
      86                 :                         errdetail("String ends unexpectedly after escape character \"%%\"."));
      87                 : #endif
      88                 :             }
      89                 :             else
      90                 :             {
      91                 :                 /* Look up placeholder character */
      92 GNC         316 :                 bool        found = false;
      93                 :                 va_list     ap;
      94                 : 
      95             316 :                 sp++;
      96                 : 
      97             316 :                 va_start(ap, letters);
      98             607 :                 for (const char *lp = letters; *lp; lp++)
      99                 :                 {
     100             607 :                     char       *val = va_arg(ap, char *);
     101                 : 
     102             607 :                     if (*sp == *lp)
     103                 :                     {
     104             316 :                         if (val)
     105                 :                         {
     106             316 :                             appendStringInfoString(&result, val);
     107             316 :                             found = true;
     108                 :                         }
     109                 :                         /* If val is NULL, we will report an error. */
     110             316 :                         break;
     111                 :                     }
     112                 :                 }
     113             316 :                 va_end(ap);
     114             316 :                 if (!found)
     115                 :                 {
     116                 :                     /* Unknown escape sequence */
     117                 : #ifdef FRONTEND
     118 UNC           0 :                     pg_log_error("invalid value for parameter \"%s\": \"%s\"", param_name, instr);
     119               0 :                     pg_log_error_detail("String contains unexpected escape sequence \"%c\".", *sp);
     120               0 :                     exit(1);
     121                 : #else
     122               0 :                     ereport(ERROR,
     123                 :                             errcode(ERRCODE_INVALID_PARAMETER_VALUE),
     124                 :                             errmsg("invalid value for parameter \"%s\": \"%s\"", param_name, instr),
     125                 :                             errdetail("String contains unexpected escape sequence \"%c\".", *sp));
     126                 : #endif
     127                 :                 }
     128                 :             }
     129                 :         }
     130                 :         else
     131                 :         {
     132 GNC       16436 :             appendStringInfoChar(&result, *sp);
     133                 :         }
     134                 :     }
     135                 : 
     136             165 :     return result.data;
     137                 : }
        

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