Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/languages/postgresql/postgresql.formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,22 +319,26 @@ export const postgresql: DialectOptions = {
'##',
'<->',
'&&',
'&&&',
'&<',
'&>',
'<<|',
'&<|',
'|>>',
'|&>',
'<^',
'^>',
'>^',
'?#',
'?-',
'?|',
'?-|',
'?||',
'@>',
'<@',
'<@>',
'~=',
// PostGIS
'|=|',
Comment on lines +322 to +341
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the PR summary the &&& operator and |=| are listed as PostGIS operators, but in the actual code only the latter is placed to PostGIS group. Some consistency would be nice.

// JSON
'?',
'@?',
Expand Down Expand Up @@ -376,6 +380,10 @@ export const postgresql: DialectOptions = {
'<->>',
'<<<->',
'<->>>',
// Cube
'~>',
// Hstore
'#=',
// Type cast
'::',
':',
Expand Down
134 changes: 133 additions & 1 deletion test/postgresql.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,26 @@ describe('PostgreSqlFormatter', () => {
'##',
'<->',
'&&',
'&&&',
'&<',
'&>',
'<<|',
'&<|',
'|>>',
'|&>',
'<^',
'^>',
'>^',
'?#',
'?-',
'?|',
'?-|',
'?||',
'@>',
'<@',
'<@>',
'~=',
// PostGIS
'|=|',
// JSON
'?',
'@?',
Expand Down Expand Up @@ -123,6 +127,10 @@ describe('PostgreSqlFormatter', () => {
'<->>',
'<<<->',
'<->>>',
// Cube
'~>',
// Hstore
'#=',
// Custom operators: from pgvector extension
'<#>',
'<=>',
Expand Down Expand Up @@ -250,4 +258,128 @@ describe('PostgreSqlFormatter', () => {
dedent`COMMENT ON TABLE foo IS 'Hello my table';`
);
});

// Tests for PostgreSQL containment and full-text search operators
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All these additional "operator tests in context" here are unnecessary. It's just noise, with no real value.

describe('containment and search operators', () => {
it('formats @> (contains) operator in WHERE clause', () => {
expect(format(`SELECT * FROM foo WHERE bar @> '{1,2}';`)).toBe(dedent`
SELECT
*
FROM
foo
WHERE
bar @> '{1,2}';
`);
});

it('formats <@ (contained by) operator in WHERE clause', () => {
expect(format(`SELECT * FROM foo WHERE bar <@ '{1,2,3}';`)).toBe(dedent`
SELECT
*
FROM
foo
WHERE
bar <@ '{1,2,3}';
`);
});

// https://www.postgresql.org/docs/current/earthdistance.html
it('formats <@> (distance) operator in ORDER BY clause', () => {
expect(format(`SELECT * FROM foo ORDER BY bar <@> point(1,2);`)).toBe(dedent`
SELECT
*
FROM
foo
ORDER BY
bar <@> point(1, 2);
`);
});

it('formats @> operator with JSONB data', () => {
expect(format(`SELECT * FROM foo WHERE data @> '{"key": "value"}';`)).toBe(dedent`
SELECT
*
FROM
foo
WHERE
data @> '{"key": "value"}';
`);
});

it('formats <@ operator with JSONB data', () => {
expect(format(`SELECT * FROM foo WHERE data <@ '{"key": "value", "other": 1}';`)).toBe(dedent`
SELECT
*
FROM
foo
WHERE
data <@ '{"key": "value", "other": 1}';
`);
});
});

// Tests for PostGIS operators
describe('PostGIS operators', () => {
// https://postgis.net/docs/geometry_overlaps_nd.html
it('formats &&& (3D bounding box overlap) operator', () => {
expect(format(`SELECT * FROM foo WHERE geom_a &&& geom_b;`)).toBe(dedent`
SELECT
*
FROM
foo
WHERE
geom_a &&& geom_b;
`);
});

// https://postgis.net/docs/geometry_distance_cpa.html
it('formats |=| (closest point of approach distance) operator', () => {
expect(format(`SELECT * FROM foo ORDER BY traj_a |=| traj_b;`)).toBe(dedent`
SELECT
*
FROM
foo
ORDER BY
traj_a |=| traj_b;
`);
});
});

// https://www.postgresql.org/docs/current/functions-geometry.html
// Note: the formatter defines ^> but PostgreSQL docs say the operator is >^
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it defined ^> in the past, but now after this PR it's corrected. So the comment doesn't really make sense any more.

describe('geometric operator correctness', () => {
it('formats >^ (is above) operator', () => {
expect(format(`SELECT * FROM foo WHERE point(1,2) >^ point(3,4);`)).toBe(dedent`
SELECT
*
FROM
foo
WHERE
point(1, 2) >^ point(3, 4);
`);
});
});

// Tests for extension operators (hstore, cube, ltree)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From where does the ltree come into play?

describe('extension operators', () => {
// https://www.postgresql.org/docs/current/cube.html
it('formats ~> (cube coordinate extraction) operator', () => {
expect(format(`SELECT c ~> 1 FROM foo;`)).toBe(dedent`
SELECT
c ~> 1
FROM
foo;
`);
});

// https://www.postgresql.org/docs/current/hstore.html
it('formats #= (hstore replace fields) operator', () => {
expect(format(`SELECT row #= hstore_data FROM foo;`)).toBe(dedent`
SELECT
row #= hstore_data
FROM
foo;
`);
});
});
});
Loading