Coverage Report

Created: 2025-10-09 06:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/adt/quote.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * quote.c
4
 *    Functions for quoting identifiers and literals
5
 *
6
 * Portions Copyright (c) 2000-2025, PostgreSQL Global Development Group
7
 *
8
 *
9
 * IDENTIFICATION
10
 *    src/backend/utils/adt/quote.c
11
 *
12
 *-------------------------------------------------------------------------
13
 */
14
#include "postgres.h"
15
16
#include "utils/builtins.h"
17
#include "varatt.h"
18
19
20
/*
21
 * quote_ident -
22
 *    returns a properly quoted identifier
23
 */
24
Datum
25
quote_ident(PG_FUNCTION_ARGS)
26
0
{
27
0
  text     *t = PG_GETARG_TEXT_PP(0);
28
0
  const char *qstr;
29
0
  char     *str;
30
31
0
  str = text_to_cstring(t);
32
0
  qstr = quote_identifier(str);
33
0
  PG_RETURN_TEXT_P(cstring_to_text(qstr));
34
0
}
35
36
/*
37
 * quote_literal_internal -
38
 *    helper function for quote_literal and quote_literal_cstr
39
 *
40
 * NOTE: think not to make this function's behavior change with
41
 * standard_conforming_strings.  We don't know where the result
42
 * literal will be used, and so we must generate a result that
43
 * will work with either setting.  Take a look at what dblink
44
 * uses this for before thinking you know better.
45
 */
46
static size_t
47
quote_literal_internal(char *dst, const char *src, size_t len)
48
0
{
49
0
  const char *s;
50
0
  char     *savedst = dst;
51
52
0
  for (s = src; s < src + len; s++)
53
0
  {
54
0
    if (*s == '\\')
55
0
    {
56
0
      *dst++ = ESCAPE_STRING_SYNTAX;
57
0
      break;
58
0
    }
59
0
  }
60
61
0
  *dst++ = '\'';
62
0
  while (len-- > 0)
63
0
  {
64
0
    if (SQL_STR_DOUBLE(*src, true))
65
0
      *dst++ = *src;
66
0
    *dst++ = *src++;
67
0
  }
68
0
  *dst++ = '\'';
69
70
0
  return dst - savedst;
71
0
}
72
73
/*
74
 * quote_literal -
75
 *    returns a properly quoted literal
76
 */
77
Datum
78
quote_literal(PG_FUNCTION_ARGS)
79
0
{
80
0
  text     *t = PG_GETARG_TEXT_PP(0);
81
0
  text     *result;
82
0
  char     *cp1;
83
0
  char     *cp2;
84
0
  int     len;
85
86
0
  len = VARSIZE_ANY_EXHDR(t);
87
  /* We make a worst-case result area; wasting a little space is OK */
88
0
  result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
89
90
0
  cp1 = VARDATA_ANY(t);
91
0
  cp2 = VARDATA(result);
92
93
0
  SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len));
94
95
0
  PG_RETURN_TEXT_P(result);
96
0
}
97
98
/*
99
 * quote_literal_cstr -
100
 *    returns a properly quoted literal
101
 */
102
char *
103
quote_literal_cstr(const char *rawstr)
104
0
{
105
0
  char     *result;
106
0
  int     len;
107
0
  int     newlen;
108
109
0
  len = strlen(rawstr);
110
  /* We make a worst-case result area; wasting a little space is OK */
111
0
  result = palloc(
112
0
          (len * 2) /* doubling for every character if each one is
113
                 * a quote */
114
0
          + 3     /* two outer quotes + possibly 'E' if needed */
115
0
          + 1     /* null terminator */
116
0
    );
117
118
0
  newlen = quote_literal_internal(result, rawstr, len);
119
0
  result[newlen] = '\0';
120
121
0
  return result;
122
0
}
123
124
/*
125
 * quote_nullable -
126
 *    Returns a properly quoted literal, with null values returned
127
 *    as the text string 'NULL'.
128
 */
129
Datum
130
quote_nullable(PG_FUNCTION_ARGS)
131
0
{
132
0
  if (PG_ARGISNULL(0))
133
0
    PG_RETURN_TEXT_P(cstring_to_text("NULL"));
134
0
  else
135
0
    PG_RETURN_DATUM(DirectFunctionCall1(quote_literal,
136
0
                      PG_GETARG_DATUM(0)));
137
0
}