Line data Source code
1 : /*------------------------------------------------------------------------- 2 : * 3 : * quote.c 4 : * Functions for quoting identifiers and literals 5 : * 6 : * Portions Copyright (c) 2000-2024, 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 8644 : quote_ident(PG_FUNCTION_ARGS) 26 : { 27 8644 : text *t = PG_GETARG_TEXT_PP(0); 28 : const char *qstr; 29 : char *str; 30 : 31 8644 : str = text_to_cstring(t); 32 8644 : qstr = quote_identifier(str); 33 8644 : 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 9130 : quote_literal_internal(char *dst, const char *src, size_t len) 48 : { 49 : const char *s; 50 9130 : char *savedst = dst; 51 : 52 695930 : for (s = src; s < src + len; s++) 53 : { 54 686810 : if (*s == '\\') 55 : { 56 10 : *dst++ = ESCAPE_STRING_SYNTAX; 57 10 : break; 58 : } 59 : } 60 : 61 9130 : *dst++ = '\''; 62 695944 : while (len-- > 0) 63 : { 64 686814 : if (SQL_STR_DOUBLE(*src, true)) 65 44 : *dst++ = *src; 66 686814 : *dst++ = *src++; 67 : } 68 9130 : *dst++ = '\''; 69 : 70 9130 : return dst - savedst; 71 : } 72 : 73 : /* 74 : * quote_literal - 75 : * returns a properly quoted literal 76 : */ 77 : Datum 78 3528 : quote_literal(PG_FUNCTION_ARGS) 79 : { 80 3528 : text *t = PG_GETARG_TEXT_PP(0); 81 : text *result; 82 : char *cp1; 83 : char *cp2; 84 : int len; 85 : 86 3528 : len = VARSIZE_ANY_EXHDR(t); 87 : /* We make a worst-case result area; wasting a little space is OK */ 88 3528 : result = (text *) palloc(len * 2 + 3 + VARHDRSZ); 89 : 90 3528 : cp1 = VARDATA_ANY(t); 91 3528 : cp2 = VARDATA(result); 92 : 93 3528 : SET_VARSIZE(result, VARHDRSZ + quote_literal_internal(cp2, cp1, len)); 94 : 95 3528 : PG_RETURN_TEXT_P(result); 96 : } 97 : 98 : /* 99 : * quote_literal_cstr - 100 : * returns a properly quoted literal 101 : */ 102 : char * 103 5602 : quote_literal_cstr(const char *rawstr) 104 : { 105 : char *result; 106 : int len; 107 : int newlen; 108 : 109 5602 : len = strlen(rawstr); 110 : /* We make a worst-case result area; wasting a little space is OK */ 111 5602 : result = palloc(len * 2 + 3 + 1); 112 : 113 5602 : newlen = quote_literal_internal(result, rawstr, len); 114 5602 : result[newlen] = '\0'; 115 : 116 5602 : return result; 117 : } 118 : 119 : /* 120 : * quote_nullable - 121 : * Returns a properly quoted literal, with null values returned 122 : * as the text string 'NULL'. 123 : */ 124 : Datum 125 1580 : quote_nullable(PG_FUNCTION_ARGS) 126 : { 127 1580 : if (PG_ARGISNULL(0)) 128 84 : PG_RETURN_TEXT_P(cstring_to_text("NULL")); 129 : else 130 1496 : PG_RETURN_DATUM(DirectFunctionCall1(quote_literal, 131 : PG_GETARG_DATUM(0))); 132 : }