Repository navigation
fix(deparser): support ALTER STATISTICS RENAME and quote/validate operator names - #370
pyramation wants to merge 1 commit into
Conversation
|
I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".
|
|
Review complete. 🟡 1 medium 💬 Inline comments (1)
The change teaches the deparser to emit qualified operator references (
Reviewed commit: e2c6d77 |
There was a problem hiding this comment.
This PR adds operator-name validation and qualified OPERATOR(schema.op) deparsing plus ALTER STATISTICS support to the deparser, backed by new kitchen-sink fixtures and tests.
Key findings
- 🟡
%wrongly accepted in operators ending in+/-— deparser.ts:991
| // The lexer rewrites `!=` to `<>` and treats `=>` as its own token. | ||
| if (op === '!=' || op === '=>') return false; | ||
| // A multi-char operator may only end in + or - if it contains one of these. | ||
| return op.length === 1 || !/[+-]$/.test(op) || /[~!@#^&|`?%]/.test(op); |
There was a problem hiding this comment.
🟡 bug · medium
% wrongly accepted in operators ending in +/-
isValidOperatorSymbol includes % in the exception class /[~!@#^&|?%]/that legalizes multi-character operators ending in+or-(packages/deparser/src/deparser.ts:991). PostgreSQL's lexer only allows such operators when they contain at least one of~ ! @ # ^ & | ` ?—%does not qualify. A name like%+` therefore passes validation and is deparsed, but the emitted SQL is rejected by the real PostgreSQL parser, breaking the round-trip guarantee this check was added to enforce.
📋 Prompt for AI Agents
In packages/deparser/src/deparser.ts at line 991, change the trailing +/- exception regex in isValidOperatorSymbol from /[~!@#^&|?%]/to/[~!@#^&|?]/. PostgreSQL's lexer only allows a multi-character operator ending in + or - when it contains one of ~ ! @ # ^ & | ? — % does not qualify, so the current code accepts invalid operators like%+` that PostgreSQL will reject on reparse.
|
Folded into #371 |
Summary
ALTER STATISTICS
RenameStmtwithOBJECT_STATISTIC_EXTthrewUnsupported RenameStmt renameType. It now emitsALTER STATISTICS [schema.]name RENAME TO new, with the qualified name quoted.AlterStatsStmtdroppedIF EXISTS(missing_ok), emitted invalidSET STATISTICSwith no value forSET STATISTICS DEFAULT(the PG18 AST has nostxstattarget), and did not quote names.Operator names. The schema part of a qualified operator was never quoted, and the operator symbol was emitted unchecked. Before → after:
a OPERATOR("My Schema".+) bOPERATOR(My Schema.+)(syntax error)a OPERATOR("S".=) ANY (...)OPERATOR(S.=)(a different schema)CREATE OPERATOR ... COMMUTATOR = OPERATOR("My Schema".===)Commutator = "My Schema", "==="Commutator = OPERATOR("My Schema".===)ALTER OPERATOR ... SET (COMMUTATOR = OPERATOR("My Schema".===))commutator = 'My Schema, ==='commutator = OPERATOR("My Schema".===)COMMENT ON OPERATOR "My Schema".=== (int, int)COMMENT ON OPERATOR My Schema(int, int)OPERATOR 1 "S".< (int, int)S.<(int, int)"S".<(int, int)EXCLUDE (c WITH OPERATOR("S".&&))c WITH S(syntax error)c WITH OPERATOR("S".&&)All of these now go through one helper,
qualifiedOperatorName(names): it quotes each schema part withQuoteUtils.quoteIdentifierand checks the symbol.deparseOperatorNamewraps qualified names inOPERATOR(...).ObjectWithArgstakes anisOperatorflag, which defaults tocontext.objtype === 'OBJECT_OPERATOR'and is passed byAlterOperatorStmtand opclass operator items.The symbol check throws
Invalid operator namefor any name that would not lex back as the same single operator token:~!@#^&|?+-*/%<>=`--or/*!=, which the lexer rewrites to<>=>+/-that don't contain one of~!@#^&|?%, e.g.+-, which lexes as+ -`Before this change those names were emitted as-is, so the SQL silently reparsed as a different expression.
Tests
misc/alter-statistics.sqlandmisc/operator-names.sql, regenerated withnpm run kitchen-sink.__tests__/misc/operator-names.test.tsuses hand-built ASTs, because the parser can never produce an invalid operator name. It covers the rejected names and some valid edge cases (~-,@-@, a quoted schema).src/deparser.tschecked out): both fixture tests and 10/13 of the hand-built cases failed, withUnsupported RenameStmt renameType: OBJECT_STATISTIC_EXT,syntax error at or near "Schema", orReceived function did not throw. After the fix all 15 pass.tscis clean and lint reports 0 errors.This is independent of #368 and #369.
Link to Devin session: https://app.devin.ai/sessions/cb07c6509db64478af655f52611468f4
Open in Devin Desktop: https://app.devin.ai/desktop/session/cb07c6509db64478af655f52611468f4?variant=devin
Requested by: @pyramation