* Quotes input string if it's not a legitimate SQL identifier as-is. * * Note that the returned string must be used before calling fmtIdEnc again, * since we re-use the same return buffer each time. */
| 98 | * since we re-use the same return buffer each time. |
| 99 | */ |
| 100 | const char * |
| 101 | fmtIdEnc(const char *rawid, int encoding) |
| 102 | { |
| 103 | PQExpBuffer id_return = getLocalPQExpBuffer(); |
| 104 | |
| 105 | const char *cp; |
| 106 | bool need_quotes = false; |
| 107 | size_t remaining = strlen(rawid); |
| 108 | |
| 109 | /* |
| 110 | * These checks need to match the identifier production in scan.l. Don't |
| 111 | * use islower() etc. |
| 112 | */ |
| 113 | if (quote_all_identifiers) |
| 114 | need_quotes = true; |
| 115 | /* slightly different rules for first character */ |
| 116 | else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_')) |
| 117 | need_quotes = true; |
| 118 | else |
| 119 | { |
| 120 | /* otherwise check the entire string */ |
| 121 | cp = rawid; |
| 122 | for (size_t i = 0; i < remaining; i++, cp++) |
| 123 | { |
| 124 | if (!((*cp >= 'a' && *cp <= 'z') |
| 125 | || (*cp >= '0' && *cp <= '9') |
| 126 | || (*cp == '_'))) |
| 127 | { |
| 128 | need_quotes = true; |
| 129 | break; |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | if (!need_quotes) |
| 135 | { |
| 136 | /* |
| 137 | * Check for keyword. We quote keywords except for unreserved ones. |
| 138 | * (In some cases we could avoid quoting a col_name or type_func_name |
| 139 | * keyword, but it seems much harder than it's worth to tell that.) |
| 140 | * |
| 141 | * Note: ScanKeywordLookup() does case-insensitive comparison, but |
| 142 | * that's fine, since we already know we have all-lower-case. |
| 143 | */ |
| 144 | int kwnum = ScanKeywordLookup(rawid, &ScanKeywords); |
| 145 | |
| 146 | if (kwnum >= 0 && ScanKeywordCategories[kwnum] != UNRESERVED_KEYWORD) |
| 147 | need_quotes = true; |
| 148 | } |
| 149 | |
| 150 | if (!need_quotes) |
| 151 | { |
| 152 | /* no quoting needed */ |
| 153 | appendPQExpBufferStr(id_return, rawid); |
| 154 | } |
| 155 | else |
| 156 | { |
| 157 | appendPQExpBufferChar(id_return, '"'); |
no test coverage detected