An identifier can be printed in bare mode if it matches the regex `[a-z_][a-z0-9_]*` and it is not a "reserved keyword."
(&self)
| 306 | /// * it matches the regex `[a-z_][a-z0-9_]*` and |
| 307 | /// * it is not a "reserved keyword." |
| 308 | pub fn can_be_printed_bare(&self) -> bool { |
| 309 | self.has_only_bare_chars() |
| 310 | && !self |
| 311 | .as_keyword() |
| 312 | .map(|kw| { |
| 313 | kw.is_sometimes_reserved() |
| 314 | || kw.begins_query_body() |
| 315 | // `AS` at the start of a SELECT item is consumed as the |
| 316 | // `AS OF` timestamp keyword (an empty projection), so a |
| 317 | // bare `as` identifier/function name fails to reparse. |
| 318 | || kw == AS |
| 319 | // `ANY`/`ALL`/`SOME` after a comparison operator start a |
| 320 | // quantified-comparison (`x op ANY (...)`), so a bare such |
| 321 | // identifier — e.g. `0 # some` — reparses as the start of a |
| 322 | // quantifier rather than an identifier. |
| 323 | || matches!(kw, ANY | ALL | SOME) |
| 324 | // `ALL`/`DISTINCT` right after `SELECT` are consumed as the |
| 325 | // projection quantifier, so a bare `"all"` / `"distinct"` |
| 326 | // column reference reparses to a quantifier with an empty |
| 327 | // projection instead of an identifier. (`ALL` is already |
| 328 | // covered above; quoting these keeps display-only — unlike |
| 329 | // marking them always-reserved, which also rejects `WHERE |
| 330 | // distinct = 1` at parse time.) |
| 331 | || kw == DISTINCT |
| 332 | // `LIST` followed by `[` re-lexes as a `LIST[...]` literal |
| 333 | // (`list[1]` is a valid one-element list), so a bare `list` |
| 334 | // identifier that gets subscripted — `"list"[1]` — would |
| 335 | // reparse as a list literal instead of a subscript. (`ARRAY` |
| 336 | // is reserved-in-scalar-expression and so already quoted; |
| 337 | // `MAP[...]` requires `=>`, so `map[1]` is unambiguously a |
| 338 | // subscript.) |
| 339 | || kw == LIST |
| 340 | // `DEALLOCATE [PREPARE] <name>` accepts an optional |
| 341 | // `PREPARE` keyword before the name, so a bare `prepare` |
| 342 | // name is consumed as that keyword on reparse, leaving no |
| 343 | // name (`DEALLOCATE prepare` -> `DEALLOCATE` + the optional |
| 344 | // keyword + a missing name). |
| 345 | || kw == PREPARE |
| 346 | // `CASE` treats a leading `WHEN` as the start of the |
| 347 | // first arm (a searched `CASE` with no operand), so a |
| 348 | // bare `when` identifier used as the `CASE` operand — |
| 349 | // `CASE when.a WHEN ...` — reparses as `CASE WHEN .a ...` |
| 350 | // ("expected an expression, found dot"). Quoting it keeps |
| 351 | // the operand an identifier. |
| 352 | || kw == WHEN |
| 353 | // `COPY [INTO] <table> FROM …` accepts an optional `INTO` |
| 354 | // keyword before the relation name, so a bare `into` |
| 355 | // relation is consumed as that keyword on reparse |
| 356 | // (`COPY into FROM x` -> `COPY INTO <name=from> …`, which |
| 357 | // then fails expecting the FROM/TO direction). |
| 358 | || kw == INTO |
| 359 | }) |
| 360 | .unwrap_or(false) |
| 361 | } |
| 362 | |
| 363 | pub fn as_str(&self) -> &str { |
| 364 | &self.0 |
no test coverage detected