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 を実行すると 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';