supabase / wrappers

Postgres Foreign Data Wrapper development framework in Rust.

Home Page:http://fdw.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Stripe joins failing to return results.

kav opened this issue · comments

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Describe the bug

Joining stripe fdw tables seems to fail or return incomplete results. I'm not sure if this is expected and just not yet implemented or a bug or what so opening an issue before I dig deeper.

e.g.

SELECT stripe_customers.email, stripe_subscriptions.currency 
FROM stripe_customers 
INNER JOIN stripe_subscriptions ON stripe_customers.id = stripe_subscriptions.customer

Using the mock data returns nothing and using our stripe account data returns a single row even though there are additional valid results.

To Reproduce

Add the following test and run the test suite.

  let results = c
                .select(
                    "SELECT stripe_customers.email, stripe_subscriptions.currency FROM stripe_customers INNER JOIN stripe_subscriptions ON stripe_customers.id = stripe_subscriptions.customer",
                    None,
                    None,
                ).unwrap()
                .filter_map(|r| {
                    r.get_by_name::<&str, _>("email")
                        .unwrap()
                        .zip(r.get_by_name::<&str, _>("currency").unwrap())
                })
                .collect::<Vec<_>>();
            assert_ne!(results, vec![]);

Run the query above against a stripe account with customers and subscriptions.

Expected behavior

Joined rows are returned.

commented

In the mock data, there is only one test customer cus_MJiBgSUgeWFN0z which doesn't have subscription, so the join returns empty data set.

data returns a single row even though there are additional valid results.

This is still an issue probably because nested loop execution plan isn't handled properly, I will have a deeper look at it.

Just ran into a similar situation as well. For my use case it's not preventing me from moving forward but it was a bit confusing when my results were all over the place. Glad it has already been reported 😄

I'm adding this limitation to the docs until its fixed as I've seen it in support tickets a couple of times.
#176

Please remove that note once this issue has been addressed

@olirice @burmecia This seems to not be working in the supabase sql editor. (I commented on the PR as well, I'm not sure which is the right place)

This returns 1 result:
select * from stripe.customers c where c.email = 'xxx'

This returns 5 results:
select * from stripe.payment_intents where customer = 'xxx'

However, this query returns only 1 result instead of 5 and payment intents is always null
select * from stripe.customers c left join stripe.payment_intents p on (p.customer = c.id) where c.email = 'xxxx'

can you try use customer.id as the filter instead of email?

select * from stripe.customers c left join stripe.payment_intents p on (p.customer = c.id) where c.id = 'cus_xxxx'

The reason is the execution plan may be different if using different column in the filter.

can you try use customer.id as the filter instead of email?

select * from stripe.customers c left join stripe.payment_intents p on (p.customer = c.id) where c.id = 'cus_xxxx'

The reason is the execution plan may be different if using different column in the filter.

I don't understand - shouldn't it be able to join on one column and filter on another?

The Postgres query planner will work out different execution plan based on table column characteristic. When using c.id = 'cus_xxxx' the execution plan is to filter on stripe.customers first, that will make the filter pushed down to Stripe first, thus the query is fast. But when using c.email = 'xxxx' the execution plan is to get ALL Stripe customers to local first, and then apply the filter, that is a slow operation.