Supabaseの入れ子selectが期待どおりの順で返ってきたが、それは保証ではなかった
ダミーデータを3件入れて、入れ子の select で取ってきたら新しい順で返ってきました。画面もそのとおりに並びます。
順序を指定していないのに、です。
順序を指定していない select
feed_sources ( max_entries, last_fetched_at,
feed_entries ( title, url, published_at, thumbnail_url ) )
feed_entries に order を書いていません。それでも期待どおりに見えたのは、ダミー3件を新しい順に insert したからでした。insert 順のまま物理的に並んでいただけです。
order by が無ければ、PostgreSQL はどの順で返してもよい。これは SQL の基礎なので知っていました。知っていたのに、動いている画面を見て「正しい」と読んでいた。
テストを書いても気づけない
3件しかないので、テストを書いても通ります。返ってくる結果が「正しく見える」ので。
本物のフィードに差し替えると、件数も更新順も変わります。そのとき順番が崩れても、原因が「順序未指定」だと結びつかない。数週間前に書いたコードの、書いていない1行が原因なので。
ここで1つ、自分が最初に間違えた読み方があります。「テストデータを3件から増やせば解決する」と考えかけました。
違います。件数を増やしても、order を書いていない限り正しい順で返る保証は増えません。効いているのは件数ではなくて、何をもって「合格」とするかを決めていなかったこと。「画面に3件並んだ」を合格条件にしていたので、並び順は最初から検査の対象外でした。
対処の選択
| 案 | 採否 | 理由 |
|---|---|---|
| 表示側で並べ替える | ✅ 採用 | 3件しかない。「新しい順に出す」という意図がコードに残る |
DB 側(supabase-js の .order(..., { referencedTable })) |
❌ | 1段目なら書ける。2段ネスト(feed_sources の中の feed_entries)で効く書き方を確かめる項目が増える |
DB 側で並べるほうが筋としては正しいと思います。supabase-js には埋め込み先を並べる referencedTable オプションがあるので、書けないわけではない。ただ今回は2段ネストで効くかを確かめる時間を取らず、確かめる項目を増やさない側を取りました。件数が増えたら見直します。
入れ子だと order を書く場所が視界に入らない
order by を書き忘れる、という話ではないと思っています。普通の select なら .order() を書く習慣がありました。
入れ子の select は文字列の中に構造を書くので、feed_entries の順序を指定する場所が、コードを書いている視界に入らない。外側の .order() は付けていて、内側は文字列の中に埋もれていた。
手順書には「表示側は素直に全件出せばよい」と書いてありました。これは件数の話で、順序には触れていません。「全件出せばよい」を「そのまま出せば正しい」と読んだのは自分でした。
動いていることは、保証されていることではない。 当たり前なのですが、動いている画面を前にすると、その当たり前が消えます。
環境: Supabase(PostgREST)/ @supabase/supabase-js 2.112.1 / Next.js 16.3.0。
Discussion