Applies a full alias map to a text blob in a single left-to-right pass.
| 237 | |
| 238 | // Applies a full alias map to a text blob in a single left-to-right pass. |
| 239 | static Status ApplyAliasMap(const unordered_map<string, string>& alias_map, |
| 240 | const string_view& text, string* output) { |
| 241 | DCHECK(output != nullptr); |
| 242 | if (alias_map.empty()) { |
| 243 | *output = string(text); |
| 244 | return Status::OK(); |
| 245 | } |
| 246 | |
| 247 | const auto entries = GetSortedReplacementEntries(alias_map); |
| 248 | |
| 249 | string result; |
| 250 | result.reserve(text.size()); |
| 251 | |
| 252 | size_t i = 0; |
| 253 | while (i < text.size()) { |
| 254 | bool matched = false; |
| 255 | for (const auto& [from, to] : entries) { |
| 256 | if (from.empty() || text.size() - i < from.size()) continue; |
| 257 | if (text.compare(i, from.size(), from) != 0) continue; |
| 258 | |
| 259 | bool start_boundary_ok = (i == 0) || !IsIdentifierChar(text[i - 1]); |
| 260 | if (!start_boundary_ok && IsEscapedJsonChar(text, i - 1)) { |
| 261 | start_boundary_ok = true; |
| 262 | } |
| 263 | const size_t after_idx = i + from.size(); |
| 264 | const bool end_boundary_ok = |
| 265 | (after_idx == text.size()) || !IsIdentifierChar(text[after_idx]); |
| 266 | if (!start_boundary_ok || !end_boundary_ok) continue; |
| 267 | |
| 268 | result.append(to.data(), to.size()); |
| 269 | i += from.size(); |
| 270 | matched = true; |
| 271 | break; |
| 272 | } |
| 273 | if (!matched) { |
| 274 | result.push_back(text[i]); |
| 275 | ++i; |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | *output = move(result); |
| 280 | return Status::OK(); |
| 281 | } |
| 282 | |
| 283 | // Extracts the analyzed query section from a plan text block. |
| 284 | static string ExtractAnalyzedQueryFromPlanText(const string_view& plan_text) { |
no test coverage detected