Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * quote.c 4 : * Functions for quoting identifiers and literals 5 : * 6 : * Portions Copyright (c) 2000-2026, 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 8744 : quote_ident(PG_FUNCTION_ARGS) 26 : { 27 8744 : text *t = PG_GETARG_TEXT_PP(0); 28 : const char *qstr; 29 : char *str; 30 : 31 8744 : str = text_to_cstring(t); 32 8744 : qstr = quote_identifier(str); 33 8744 : PG_RETURN_TEXT_P(cstring_to_text(qstr)); 34 : } 35 : 36 : /* 37 : * quote_literal_internal - 38 : * helper function for quote_literal and quote_literal_cstr 39 : * 40 : * NOTE: This must produce output that will work in old servers with 41 : * standard_conforming_strings = off. It's used for example by 42 : * dblink, which may send the result to another server. 43 : */ 44 : static size_t 45 9588 : quote_literal_internal(char *dst, const char *src, size_t len) 46 : { 47 : const char *s; 48 9588 : char *savedst = dst; 49 : 50 700882 : for (s = src; s < src + len; s++) 51 : { 52 691304 : if (*s == '\\') 53 : { 54 10 : *dst++ = ESCAPE_STRING_SYNTAX; 55 10 : break; 56 : } 57 : } 58 : 59 9588 : *dst++ = '\''; 60 700896 : while (len-- > 0) 61 : { 62 691308 : if (SQL_STR_DOUBLE(*src, true)) 63 48 : *dst++ = *src; 64 691308 : *dst++ = *src++; 65 : } 66 9588 : *dst++ = '\''; 67 : 68 9588 : return dst - savedst; 69 : } 70 : 71 : /* 72 : * quote_literal - 73 : * returns a properly quoted literal 74 : */ 75 : Datum 76 3538 : quote_literal(PG_FUNCTION_ARGS) 77 : { 78 3538 : text *t = PG_GETARG_TEXT_PP(0); 79 : text *result; 80 : char *cp1; 81 : char *cp2; 82 : int len; 83 : 84 3538 : len = VARSIZE_ANY_EXHDR(t); 85 : /* We make a worst-case result area; wasting a little space is OK */ 86 3538 : result = (text *) palloc(len * 2 + 3 + VARHDRSZ); 87 : 88 3538 : cp1 = VARDATA_ANY(t); 89 3538 : cp2 = VARDATA(result); 90 : 91 3538 : SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len)); 92 : 93 3538 : PG_RETURN_TEXT_P(result); 94 : } 95 : 96 : /* 97 : * quote_literal_cstr - 98 : * returns a properly quoted literal 99 : */ 100 : char * 101 6050 : quote_literal_cstr(const char *rawstr) 102 : { 103 : char *result; 104 : int len; 105 : int newlen; 106 : 107 6050 : len = strlen(rawstr); 108 : /* We make a worst-case result area; wasting a little space is OK */ 109 6050 : result = palloc( 110 : (len * 2) /* doubling for every character if each one is 111 : * a quote */ 112 : + 3 /* two outer quotes + possibly 'E' if needed */ 113 6050 : + 1 /* null terminator */ 114 : ); 115 : 116 6050 : newlen = quote_literal_internal(result, rawstr, len); 117 6050 : result[newlen] = '\0'; 118 : 119 6050 : return result; 120 : } 121 : 122 : /* 123 : * quote_nullable - 124 : * Returns a properly quoted literal, with null values returned 125 : * as the text string 'NULL'. 126 : */ 127 : Datum 128 1580 : quote_nullable(PG_FUNCTION_ARGS) 129 : { 130 1580 : if (PG_ARGISNULL(0)) 131 84 : PG_RETURN_TEXT_P(cstring_to_text("NULL")); 132 : else 133 1496 : PG_RETURN_DATUM(DirectFunctionCall1(quote_literal, 134 : PG_GETARG_DATUM(0))); 135 : }