Skip to content

refactor(workspace): quote the expanded columns with the catalog's quote_identifier - #998

Open
psteinroe wants to merge 1 commit into
fix/completions-quote-namesfrom
refactor/expand-star-quote-identifier
Open

psteinroe wants to merge 1 commit into
fix/completions-quote-namesfrom
refactor/expand-star-quote-identifier

Conversation

@psteinroe

@psteinroe psteinroe commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #981.

Follow-up to the review of #932: the local quote_identifier in workspace/server/expand_star.rs "should be a helper in catalog". #981 adds that helper, pgls_catalog::quote_identifier(name, NamePosition), so expand star now uses it and its own copy is gone.

The catalog's version knows where a name is written, so the expanded list changes a little. The old helper quoted every keyword that isn't unreserved, like Postgres' quote_identifier. Now the first name of each column is quoted as a ColId and the names after a dot as labels:

-- table t (id int, "select" text, between int, "left" int)
select * from t
-- before: id, "select", "between", "left"
-- now:    id, "select", between, "left"
select t.* from t
-- before: t.id, t."select", t."between", t."left"
-- now:    t.id, t.select, t.between, t.left

More precisely:

  • A column name keyword (between, int, time, values, ...) is no longer quoted, also without a qualifier.
  • Any keyword after a dot is no longer quoted: t.select, public."Posts".user.
  • Reserved keywords (select, user) and type or function name keywords (left, join) are still quoted as the first name.

I checked this against the Postgres 15 test database for all 151 keywords that aren't unreserved there: every column name keyword parses unquoted as the only, the first and the last item of a select list, and returns the column's value, and so does every keyword after a dot. Reserved and type or function name keywords fail to parse without quotes as the first name, which is why they stay quoted there. Keywords added in Postgres 16 and 17 (json_table, merge_action, ...) aren't covered by that check; they follow the same gram.y categories.

column_list also no longer runs the scanner once per name; keyword_category is a table lookup.

This PR changes workspace/server/expand_star.rs where it is on main. #990 moves that file to features/code_actions/expand_star.rs without changing it otherwise, and a trial merge of #990 into this branch applies this change to the moved file without conflicts.

Tests

  • quotes_names_where_postgres_needs_it replaces the unit test of the removed helper and goes through column_list: a column name keyword, a reserved and a type or function name keyword with and without a qualifier, upper case, a space, ", and names that aren't ASCII.
  • qualifies_columns and test_code_actions_expand_star now expect public."Posts".user and t.select.
  • cargo test -p pgls_workspace --lib -- expand_star, cargo test -p pgls_lsp -- expand_star and cargo clippy --workspace --all-targets -- -D warnings pass.

…ote_identifier

Expand star had its own quote_identifier, which quoted every keyword
that isn't unreserved. It now uses pgls_catalog::quote_identifier: the
first name of a column as a ColId, the names after a dot as labels. A
column name keyword like `between` and any keyword after a dot, as in
`t.select`, are no longer quoted, as Postgres reads them as the column.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant