はるさめ.dev

Prisma の rawQuery から pgroonnga のオペレーターが使用できない

に公開

背景

Supabase の extension に全文検索エンジンの PGRoonga を追加していて、prisma から PGRonnga の検索オペレーター&@を使用した SQL を発行しました。

const bodies = await prisma.rawQuery(`SELECT * FROM foo WHERE body &@ 'aa'`); 

すると次のようなエラーが発生しました。

ERROR: operator does not exist: character varying &@ text HINT: No operator matches the given name and argument types. You might need to add explicit type casts

他の PGRonnga のオペレーターの &@~ などでも同じでした。
しかし Supabase のダッシュボードから SQL を実行すると問題なく実行できました。

原因

PGRoonga の追加は公式のドキュメントの「PGroonga: Multilingual Full Text Search」通り以下の SQL を実行しています。

-- Enable the "pgroonga" extension
create extension pgroonga with schema extensions;

そのためオペレーターの追加先は extensions スキーマになります。
以下の SQL を実行することで追加されたカスタムオペレーターが extensions スキーマに追加されていることが確認できます。

SELECT
    oprname AS operator_name,
    oprnamespace::regnamespace AS schema_name,
    oprleft::regtype AS left_operand_type,
    oprright::regtype AS right_operand_type,
    oprresult::regtype AS result_type
FROM
    pg_operator
WHERE
    oprnamespace <> 'pg_catalog'::regnamespace
ORDER BY
    schema_name, operator_name;
カスタムオペレーターを取得する SQL を実行した結果。追加された pgroonga のカスタムオペレーターが extensions スキーマにインストールされていることがわかる。

ダッシュボード上から以下の SQL を実行すると extensions スキーマも設定されていたのですが、プログラム上から実行すると public しか設定されておらず、pgroonga のオペレーターを実行するときに extensions スキーマを検索していないことがエラー原因のようです。

SHOW search_path;

プログラムから実行したときに extensions が search_path に設定されていない理由は Prisma の接続文字列として ?schema=publicを渡して接続先のスキーマを設定しているからのようでした。

解決方法

方法1:接続文字列でスキーマの指定をやめる

使用するスキーマが public の場合はデフォルトの接続先スキーマが public なので単純に ?schema=publicを外せば extensions も対象になります。

ただ、今回のシステムではスキーマを使い分けている都合上、スキーマの指定を外すことができませんでした。

方法2:SQL 実行時にスキーマを指定してオペレータを使用する

search_path に含まれていないスキーマのオペレーターでも、明示的にスキーマを指定してあげることで実行できます。

SELECT * FROM foo WHERE body OPERATOR(extensions.&@) 'aa';

コメント