-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Bug when Null Filtering on embedded resources #2951
Conversation
I'm not sure whether the |
Or even better... maybe just translate |
That might be difficult as joins much change the shape of the query. Edit: additionally ANTI JOINs and OR queries wouldn't work no more. |
What would be the advantage of that one? |
It could be possible for anti joins but the OR queries wouldn't work this way. Although I get that it's not 1-1 with PostgreSQL ( |
Yes. I didn't say
Performance. I don't think the distinct from approach will be optimized very well, while comparing only the join columns is very likely optimized nicely. |
I did some benchmarks using curl "http://localhost:3000/projects?select=name,clients(name)&clients=not.is.null" Queries:-- IS NOT NULL (Before the change)
WITH pgrst_source AS
(SELECT "test"."projects"."name",
row_to_json("projects_clients_1".*) AS "clients"
FROM "test"."projects"
LEFT JOIN LATERAL
(SELECT "clients_1"."name"
FROM "test"."clients" AS "clients_1"
WHERE "clients_1"."id" = "test"."projects"."client_id") AS "projects_clients_1" ON TRUE
WHERE "projects_clients_1" IS NOT NULL)
SELECT NULL::bigint AS total_result_set,
pg_catalog.count(_postgrest_t) AS page_total,
coalesce(json_agg(_postgrest_t), '[]') AS body,
nullif(current_setting('response.headers', TRUE), '') AS response_headers,
nullif(current_setting('response.status', TRUE), '') AS response_status
FROM
(SELECT *
FROM pgrst_source) _postgrest_t;
-- IS DISTINCT FROM NULL
WITH pgrst_source AS
(SELECT "test"."projects"."name",
row_to_json("projects_clients_1".*) AS "clients"
FROM "test"."projects"
LEFT JOIN LATERAL
(SELECT "clients_1"."name"
FROM "test"."clients" AS "clients_1"
WHERE "clients_1"."id" = "test"."projects"."client_id") AS "projects_clients_1" ON TRUE
WHERE "projects_clients_1" IS DISTINCT FROM NULL)
SELECT NULL::bigint AS total_result_set,
pg_catalog.count(_postgrest_t) AS page_total,
coalesce(json_agg(_postgrest_t), '[]') AS body,
nullif(current_setting('response.headers', TRUE), '') AS response_headers,
nullif(current_setting('response.status', TRUE), '') AS response_status
FROM
(SELECT *
FROM pgrst_source) _postgrest_t;
-- INNER JOIN
WITH pgrst_source AS
(SELECT "test"."projects"."name",
row_to_json("projects_clients_1".*) AS "clients"
FROM "test"."projects"
INNER JOIN LATERAL
(SELECT "clients_1"."name"
FROM "test"."clients" AS "clients_1"
WHERE "clients_1"."id" = "test"."projects"."client_id") AS "projects_clients_1" ON TRUE)
SELECT NULL::bigint AS total_result_set,
pg_catalog.count(_postgrest_t) AS page_total,
coalesce(json_agg(_postgrest_t), '[]') AS body,
nullif(current_setting('response.headers', TRUE), '') AS response_headers,
nullif(current_setting('response.status', TRUE), '') AS response_status
FROM
(SELECT *
FROM pgrst_source) _postgrest_t; The `pgbench` for each of the queries:
The
I didn't know how to implement this for the test (and allow the OR across joins), just used the |
So we getter perf now! 🎉
Yeah, INNER JOIN cannot be done and this goes back to the introduction of top-level filtering: #1949 (comment). Iced-Sun's query helped us there. |
Right, the OR approach can't be written with JOIN easily. But in my latest comment I didn't say "write as JOIN", but "check only join columns". This is possible to do with OR as well. The test you did is very artificial, because the tables are really small (few columns!). Once you add a lot more columns, those tests will show that both before the change and after the change with IS DISTINCT are both very slow compared to just testing the join columns.
As I said before this is misleading. The performance is not really better, it's less bad. But not good, yet.
If you test the join columns, PG might be able to rewrite this to an inner join automatically. |
Yes, at the end of the tests I added that I couldn't find a way on how to do this, that's why it's not included there.
Cool, then the problem right now is to rewrite the queries to allow filtering on the JOIN columns. It does not seem to be trivial: as it is now, we select from the LEFT JOIN LATERAL subquery, if the join column is not selected by the user Edit: opened an issue to keep track of this #2961 |
Closes #2800