web-dev-qa-db-ja.com

CITEXTとTEXTの比較が失敗するのはなぜですか?

予想通り、このような等価テストを実行すると、比較は成功します。

CREATE TABLE citext_test (
    value citext PRIMARY KEY
);

INSERT INTO citext_test VALUES ('one');
INSERT INTO citext_test VALUES ('two');

SELECT * FROM citext_test WHERE value = 'One';

ただし、比較対象の値のタイプが「テキスト」の場合、比較は失敗します。

SELECT * FROM citext_test WHERE value = 'One'::text;

EXPLAINを使用すると、最初の例の未加工の値がCITEXTにキャストされているように見えます。

Index Only Scan using citext_test_pkey on citext_test  (cost=0.15..8.17 rows=1 width=32)
  Index Cond: (value = 'One'::citext)

結合されたテーブルのTEXT列と比較したいのですが。比較を機能させるために、これらの列をCITEXTにキャストする必要がありますか? CITEXTを使用する利点の一部は、このようなものを追加することを覚えておく必要がないことだと思いました(例:LOWER(some_value));

3
antsyawn

比較を機能させるために、これらの列をCITEXTにキャストする必要がありますか?

はい、それはあなたがしなければならないことです。これは、オペレーターの動作方法ではありません。このタイプをテーブルに設定する必要があるため、これを行う必要はありません。 1つが大文字と小文字を区別しないテキストであり、もう1つが大文字と小文字を区別するテキストであると言う場合、大文字と小文字を区別するテキストが優先されます。最初の例が機能する理由は、

SELECT * FROM citext_test WHERE value = 'One';

本質的に同じです

SELECT * FROM citext_test WHERE value = 'One'::unknown;

内部的には、オペレーターによってcitextに昇格されます。キャストで曖昧さをなくすことができます。

SELECT * FROM citext_test WHERE value = 'One'::citext;

または機能的な形

SELECT * FROM citext_test WHERE citext_eq(value, 'One');

しかし、適切な解決策はALTER TABLEは、結合するテーブルのタイプで、citextにも設定します。

4
Evan Carroll

最初の比較を実行するために内部で発生することは、 演算子タイプの解決

https://www.postgresql.org/docs/current/static/typeconv-oper.html

2.入力引数の型を正確に受け入れる演算子を確認します。存在する場合(考慮される演算子のセットで完全に一致するものは1つだけ存在できる)、それを使用します。

a。 2項演算子呼び出しの1つの引数が不明なタイプである場合、このチェックのもう1つの引数と同じタイプであると想定します。 2つの不明な入力を含む呼び出し、または不明な入力を伴う単項演算子は、このステップで一致を見つけることはありません。

2番目の比較では、いくつかのルールが説明されているため、falseと評価されます。 3.最適な一致を探します どうやらtextへのキャストにつながる。しかし、正確に型が一致する関数/演算子の組み合わせを追加することで、PostgreSQLにtext=citextを思いどおりに評価させることができます。

CREATE FUNCTION my_citext_eq_text(citext,text) returns boolean as
  'select $1=cast($2 as citext)' language sql immutable;

CREATE OPERATOR = (procedure=my_citext_eq_text,
   leftarg=citext, rightarg=text);

型の数に比例して演算子の数が二次的に増加するのを避けるために、拡張機能は一般にデフォルトでこれを実行しないと思います。

citextで定義された演算子と暗黙のキャストについては、拡張ディレクトリにインストールされているcitext--<latest-version-number>.sqlを参照してください。

2
Daniel Vérité