supabase / postgrest-js

Isomorphic JavaScript client for PostgREST.
https://supabase.com
MIT License
964 stars 128 forks source link

`.delete().single()` can delete multiple rows #461

Closed probablykasper closed 10 months ago

probablykasper commented 10 months ago

Bug report

Describe the bug

.single() or .maybeSingle() returns an error if multiple rows are affected. However the query still runs, which means .delete().single() can delete many rows. I'd consider this unexpected behavior.

The documentation does not state or imply this behavior.

{
    code: 'PGRST116',
    details: 'Results contain 2 rows, application/vnd.pgrst.object+json requires 1 row',
    hint: null,
    message: 'JSON object requested, multiple (or no) rows returned'
  }

To Reproduce

const result = await supabase.from('example').delete().single();
console.log(result);

Expected behavior

If the .delete().single() / .delete().maybeSingle() affects multiple rows, the query should not execute.

System information

steve-chavez commented 10 months ago

:x: Can't reproduce :

$ curl 'localhost:3000/complex_items'

[{"id":1,"name":"One","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1],"field-with_sep":1}, 
 {"id":2,"name":"Two","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2],"field-with_sep":1}, 
 {"id":3,"name":"Three","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2,3],"field-with_sep":3}]

# equivalent to supabase.from('complex_items').delete().single();
$ curl 'localhost:3000/complex_items' -X DELETE -H "Accept: application/vnd.pgrst.object"

{"code":"PGRST116","details":"The result contains 3 rows","hint":null,"message":"JSON object requested, multiple (or no) rows returned"}

$ curl 'localhost:3000/complex_items' 

[{"id":1,"name":"One","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1],"field-with_sep":1}, 
 {"id":2,"name":"Two","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2],"field-with_sep":1}, 
 {"id":3,"name":"Three","settings":{"foo":{"int":1,"bar":"baz"}},"arr_data":[1,2,3],"field-with_sep":3}]

const result = await supabase.from('example').delete().single();

On the Supabase platform you also have pg-safeupdate, which wouldn't even let the DELETE run without a filter. Is this self-hosted?

Also provide a before/after queries of the data you think is being deleted.

probablykasper commented 10 months ago

I must've messed up when testing this, I can't reproduce it either now. Sorry