Skip to content

Commit eed051c

Browse files
committed
Full PostgreSQL operators support
Instead of listing a known list of operators, match all the allowed operators properly.
1 parent 2b36e4e commit eed051c

File tree

2 files changed

+40
-15
lines changed

2 files changed

+40
-15
lines changed

src/parser.pegjs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
} from "./utils/parserState";
4444
import { isReservedKeyword } from "./utils/keywords";
4545
import { loc } from "./utils/loc";
46+
import { isPostgresqlOtherOperator } from "./utils/pgOperators";
4647

4748
setRangeFunction(() => [peg$savedPos, peg$currPos]);
4849

@@ -7486,23 +7487,14 @@ pg_other_expr
74867487
return createBinaryExprChain(head, tail);
74877488
}
74887489

7489-
// TODO: Actually Postgres allows combinations of all these symbols:
7490+
// Postgres allows combinations of all these symbols:
74907491
//
74917492
// + - * / < > = ~ ! @ # % ^ & | ` ?
74927493
//
7494+
// But there are some restrictions (see isPostgresqlOtherOperator for details)
7495+
//
74937496
pg_other_op
7494-
= op:(
7495-
// multi-letter operators (non-exhaustive list)
7496-
"||/" / "|/" / "||" / ">>" / "<<" / "!~~*" / "~~*" / "!~~" / "~~" / "!~*" / "~*" / "!~" / "^@"
7497-
// pgvector operators
7498-
/ "<+>" / "<->" / "<#>" / "<=>" / "<~>" / "<%>"
7499-
// JSON operators
7500-
/ "->>" / "->" / "#>>" / "#>"
7501-
// JSONB operators
7502-
/ "@>" / "<@" / "?|" / "?&" / "#-" / "@?" / "@@"
7503-
// single-letter operators (exhaustive list)
7504-
/ "!" / "~" / "@" / "#" / "&" / "|" / "`" / "?"
7505-
) {
7497+
= op:(postgresql_operator) &{ return isPostgresqlOtherOperator(op); } {
75067498
return op;
75077499
}
75087500

test/expr/op_postgres.test.ts

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ describe("special PostgreSQL operators", () => {
2929
"#>",
3030
// JSONB
3131
"@>",
32-
"<@",
3332
"?",
3433
"?|",
3534
"?&",
@@ -44,13 +43,47 @@ describe("special PostgreSQL operators", () => {
4443
"<=>",
4544
"<~>",
4645
"<%>",
46+
// Others
47+
// discovered by running in Supabase:
48+
// SELECT DISTINCT oprname FROM pg_operator WHERE length(oprname) >= 2 ORDER BY oprname;
49+
"!!",
50+
"##",
51+
"&&",
52+
"&<",
53+
"&>",
54+
"*<",
55+
"*<=",
56+
"*<>",
57+
"*=",
58+
"*>",
59+
"*>=",
60+
"-|-",
61+
"<<=",
62+
"<<|",
63+
"<^",
64+
">>=",
65+
">^",
66+
"?#",
67+
"?-",
68+
"?-|",
69+
"?||",
70+
"@-@",
71+
"@@@",
72+
"^@",
73+
"|&>",
74+
"|>>",
75+
"~<=~",
76+
"~<~",
77+
"~=",
78+
"~>=~",
79+
"~>~",
4780
].forEach((op) => {
4881
it(`parses ${op} operator`, () => {
4982
testExprWc(`x ${op} y`);
5083
});
5184
});
5285

53-
// Test the currently unused isPostgresqlOtherOperator() predicate
86+
// Separately test the isPostgresqlOtherOperator() predicate
5487
describe("isPostgresqlOtherOperator()", () => {
5588
it("rejects standard operators", () => {
5689
expect(isPostgresqlOtherOperator("+")).toBe(false);

0 commit comments

Comments
 (0)