Line data Source code
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 8702 : quote_ident(PG_FUNCTION_ARGS) 26 : { 27 8702 : text *t = PG_GETARG_TEXT_PP(0); 28 : const char *qstr; 29 : char *str; 30 : 31 8702 : str = text_to_cstring(t); 32 8702 : qstr = quote_identifier(str); 33 8702 : 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: 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 9398 : quote_literal_internal(char *dst, const char *src, size_t len) 48 : { 49 : const char *s; 50 9398 : char *savedst = dst; 51 : 52 698614 : for (s = src; s < src + len; s++) 53 : { 54 689226 : if (*s == '\\') 55 : { 56 10 : *dst++ = ESCAPE_STRING_SYNTAX; 57 10 : break; 58 : } 59 : } 60 : 61 9398 : *dst++ = '\''; 62 698628 : while (len-- > 0) 63 : { 64 689230 : if (SQL_STR_DOUBLE(*src, true)) 65 44 : *dst++ = *src; 66 689230 : *dst++ = *src++; 67 : } 68 9398 : *dst++ = '\''; 69 : 70 9398 : return dst - savedst; 71 : } 72 : 73 : /* 74 : * quote_literal - 75 : * returns a properly quoted literal 76 : */ 77 : Datum 78 3552 : quote_literal(PG_FUNCTION_ARGS) 79 : { 80 3552 : text *t = PG_GETARG_TEXT_PP(0); 81 : text *result; 82 : char *cp1; 83 : char *cp2; 84 : int len; 85 : 86 3552 : len = VARSIZE_ANY_EXHDR(t); 87 : /* We make a worst-case result area; wasting a little space is OK */ 88 3552 : result = (text *) palloc(len * 2 + 3 + VARHDRSZ); 89 : 90 3552 : cp1 = VARDATA_ANY(t); 91 3552 : cp2 = VARDATA(result); 92 : 93 3552 : SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len)); 94 : 95 3552 : PG_RETURN_TEXT_P(result); 96 : } 97 : 98 : /* 99 : * quote_literal_cstr - 100 : * returns a properly quoted literal 101 : */ 102 : char * 103 5846 : quote_literal_cstr(const char *rawstr) 104 : { 105 : char *result; 106 : int len; 107 : int newlen; 108 : 109 5846 : len = strlen(rawstr); 110 : /* We make a worst-case result area; wasting a little space is OK */ 111 5846 : result = palloc( 112 : (len * 2) /* doubling for every character if each one is 113 : * a quote */ 114 : + 3 /* two outer quotes + possibly 'E' if needed */ 115 5846 : + 1 /* null terminator */ 116 : ); 117 : 118 5846 : newlen = quote_literal_internal(result, rawstr, len); 119 5846 : result[newlen] = '\0'; 120 : 121 5846 : return result; 122 : } 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 1580 : quote_nullable(PG_FUNCTION_ARGS) 131 : { 132 1580 : if (PG_ARGISNULL(0)) 133 84 : PG_RETURN_TEXT_P(cstring_to_text("NULL")); 134 : else 135 1496 : PG_RETURN_DATUM(DirectFunctionCall1(quote_literal, 136 : PG_GETARG_DATUM(0))); 137 : }