次の postgresql スキーマがあるとします。
CREATE TABLE "temp" (id int, fields text[]);
INSERT INTO "temp" VALUES
(1, array['abc', 'def']),
(2, array['abc', 'def', 'jkl']),
(3, array['abd', 'def']),
(4, '{"1{c}1", a}');
以下はプレーン SQL で機能し、行 1 と 2 を返します (@>
は pg の「含む」演算子です)。
SELECT id, fields FROM temp WHERE "fields" @> '{def, abc}';
しかし、Doobieでも同じです(postgresql 拡張を使用):
import doobie._
import doobie.implicits._
import doobie.postgres.implicits._
val searchTerms = List("def", "abc")
fr"SELECT id, fields FROM temp WHERE fields @> $searchTerms"
次の場合に失敗します。
org.postgresql.util.PSQLException: ERROR: operator does not exist: text[] @> character varying[]
Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
searchTerms
補間された値をキャストtext[]
すると、問題が解決するようです。
val searchTerms = List("def", "abc")
fr"SELECT id, fields FROM temp WHERE fields @> CAST($searchTerms AS text[])"
同様に、データベース スキーマでfields
列の型を からtext[]
に変更しvarchar[]
て、キャストを回避することもできます。これにより、正しい行がコンパイルされて返されます。
私の主な問題は、なぜ Doobie がそのように振る舞うかがわからないことです。カスタム型で同じ問題に再び遭遇する可能性があるため、なぜ が に$searchTerms
デコードされて にデコードされvarying[]
ないのかを理解する必要があります。また、この動作を変更して、列の型を維持し、キャストを回避text[]
できるようにするために何ができるかを理解する必要があります。text[]
おそらくこれを制御する暗黙のインスタンスがどこかにあると思いますが、それが何であるかはわかりませんでした。