次のエラーが発生しています。
_ERROR: functions in index expression must be marked IMMUTABLE
_
このようなインデックスを作成しようとすると:
_CREATE INDEX full_phone_number ON orders_clientphone (concat(area_code, phone));
_
一方、連結に代替構文を使用する場合:
_CREATE INDEX full_phone_number ON orders_clientphone ((area_code || phone));
_
Postgresはそれでかなり大丈夫です。
両方の列はcharacter varying(256)
として定義されています。
Postgresの決定要因は、関数concat()
が定義されていることですstableおよびではありません不変システムカタログ_pg_proc
_:
_SELECT proname, provolatile, proargtypes, proargtypes[0]::regtype AS argtype, prosrc
FROM pg_proc
WHERE proname = 'concat';
proname | provolatile | proargtypes| argtype | prosrc
--------+-------------+------------+---------+-----------
concat | s | 2276 | "any" | text_concat
_
_pg_proc.provolatile
_: のマニュアル
provolatile
は、関数の結果が入力引数のみに依存するのか、それとも外部要因の影響を受けるのかを示します。 「不変」関数の場合はi
であり、常に同じ入力に対して同じ結果を提供します。これは「安定した」関数の場合はs
であり、その結果(固定入力の場合)はスキャン内で変化しません。
また、関数の引数タイプ(_"any"
_)を追加して、@ dezsoおよび@jjanesの回答に接続しました。これにより、この関数のみを安定させるという決定の背後にある根拠が提供されます。そして、内部関数の名前(_text_concat
_)。
以下は、インデックス式の不変性が正弦非条件である理由を説明するための関連質問です。
演算子_||
_の使用について:
_ SELECT o.oprname, o.oprleft::regtype, o.oprright::regtype, o.oprcode, p.provolatile
FROM pg_operator o
JOIN pg_proc p ON p.oid = o.oprcode
WHERE oprname = '||';
oprname | oprleft | oprright | oprcode | provolatile
---------+-------------+-------------+-----------------+-------------
|| | anyarray | anyelement | array_append | i
|| | anyelement | anyarray | array_prepend | i
|| | anyarray | anyarray | array_cat | i
|| | text | text | textcat | i
|| | bit varying | bit varying | bitcat | i
|| | bytea | bytea | byteacat | i
|| | text | anynonarray | textanycat | s
|| | anynonarray | text | anytextcat | s
|| | tsvector | tsvector | tsvector_concat | i
|| | tsquery | tsquery | tsquery_or | i
|| | jsonb | jsonb | jsonb_concat | i
_
内部で使用する関数は、オペランドの実際のデータ型によって異なります。演算子の定義には、Postgresのオペランドのデータ型が含まれます。すべての関数は異なり、上記の_text_concat
_とも異なります。演算子の1つがanynonarray
の場合、_||
_も安定します。カーテンの後ろでは物事はそれほど簡単ではありません。
character varying(256)
(他のvarchar
バリアントと同様)はbinary-coercibleto text
so function type resolution デフォルトはtext
です。
次のように、concat、 ドキュメントで定義 と考えています。
FUNCTION RETURN TYPE DESCRIPTION
-----------------------------------------------------------------------------------
concat(str "any" [, str "any" [, ...] ]) text Concatenate the text repre-
sentations of all the arguments.
NULL arguments are ignored.
テキスト表現はデータベース設定に依存する可能性があるため、不変ではありません 日付またはタイムスタンプのように 。
Dezsoの答えを記入するために、データベースの状態に応じて異なる出力を生成する同じ入力の例を次に示します。
select concat(1.0000000000003::float8,56);
1.000000000000356
set extra_float_digits TO 3;
select concat(1.0000000000003::float8,56);
1.0000000000002999856