いくつかの値(1000)がPostgresクエリオプティマイザーで使用されるMCVリストに属しているかどうかを確認するために、この簡単なクエリを実行しようとしています。
_SELECT array_position(most_common_vals, 1000)
FROM pg_stats
WHERE tablename = 'tenk1'
AND attname = 'unique1';
_
ただし、次のエラーメッセージが表示されます。
_ERROR: function array_position(anyarray, integer) does not exist
_
どうすれば修正できますか?
array_position()
は、説明されている標準関数 here であり、次のステートメントは期待どおり2を返します。
_SELECT array_position('{1,2,3}', 2);
_
列のデータ型を想定すると、_tenk1.unique1
_はinteger
になります。
_SELECT array_position(most_common_vals::text::int[], 1000)
FROM pg_stats
WHERE tablename = 'tenk1'
AND attname = 'unique1';
_
実際の列タイプと対応する配列タイプを使用します。
位置を取得します。値がMCVリストにない場合はNULLを取得します。
解決策は短いです-とは異なり...
関数 array_position()
は_(anyarray, anyelement)
_(または2番目のバリアントの場合は_(anyarray, anyelement, integer)
_)を取るように定義されています。
列 _pg_stats.most_common_vals
_ は多相データ型anyarray
を持ち、あらゆるデータ型の配列を保持できます-明らかな理由があります。
anyarray
およびanyelement
は、ユーザーが作成したテーブルのデータ型として許可されていません。ユーザーの場合、どちらも polymorphic pseudo-types です。 (しかし、Postgresはシステムテーブルでそれらを使用できます。)
同じ関数内の複数のポリモーフィック変数は、同じ(または対応する)データ型に解決される必要があります。マニュアル:
さらに、
anyarray
と宣言された位置とanyelement
と宣言された位置がある場合、anyarray
位置の実際の配列型は、anyelementに現れる要素と同じ型の要素を持つ配列でなければなりません。ポジション。
そして:
したがって、複数の引数の位置がポリモーフィック型で宣言されている場合、最終的な効果は実際の引数の型の特定の組み合わせのみが許可されるです。
大胆な強調鉱山。
多態性anyarray
とinteger
-またはanyの組み合わせで function type resolution が失敗するコーナーケースを見つけました2番目の位置に非ポリモーフィック型。
式の_1000
_ array_position(most_common_vals, 1000)
は、integer
に解決される数値定数です。これらは同様の方法で失敗します:
_array_position(most_common_vals, '1000') -- untyped string literal
_
_ERROR: function array_position(anyarray, unknown) does not exist
_
_array_position(most_common_vals, '1000'::text)
_
_ERROR: function array_position(anyarray, text) does not exist
_
さらに、anyarray
にはキャストが定義されておらず、ユーザーランドの疑似タイプです。
_SELECT * FROM pg_cast WHERE castsource = 'anyarray'::regtype; -- nothing found
_
回避策は、text
にキャストできるため、飛び石としてtext
にキャストすることです。次に_integer[]
_にキャストして、上記のソリューションに到達します。
最後に、私は考えるこれは、(簡単に?)解決できる関数型解決の欠点です。しかし、データ型anyarray
は、ユーザーランドで最初にこのように使用することを想定していないため、開発者がそれに時間を費やすことはないと思います...