バージョンごとのドキュメント一覧

10.2. 演算子 #

<title>Operators</title>

The specific operator that is referenced by an operator expression is determined using the following procedure. Note that this procedure is indirectly affected by the precedence of the operators involved, since that will determine which sub-expressions are taken to be the inputs of which operators. See <xref linkend="sql-precedence"/> for more information. 演算式に参照される特定の演算子は、以下の手順を用いて決定されます。 関連する演算子の優先順位によりどの下位式をどの演算子の入力と見なすかが決定されますので、この手順はこの優先順位により間接的な影響を受けることに注意してください。 詳細は4.1.6を参照してください。

演算子における型の解決

<title>Operator Type Resolution</title>
  1. Select the operators to be considered from the <classname>pg_operator</classname> system catalog. If a non-schema-qualified operator name was used (the usual case), the operators considered are those with the matching name and argument count that are visible in the current search path (see <xref linkend="ddl-schemas-path"/>). If a qualified operator name was given, only operators in the specified schema are considered. pg_operatorシステムカタログから、調査の対象とする演算子を選択します。 スキーマ修飾がされていない演算子名が使用される場合(通常の場合)、現行の検索パスで可視になっていて、同一の名前と引数の数を持つ演算子が調査対象であるとみなされます (5.10.3を参照してください)。 修飾された演算子名が与えられている場合、指定されたスキーマの演算子のみが調査対象とみなされます。

    1. If the search path finds multiple operators with identical argument types, only the one appearing earliest in the path is considered. Operators with different argument types are considered on an equal footing regardless of search path position. 検索パスで引数のデータ型が同じである複数の演算子を検出した場合、そのパスで最初に検出された演算子のみを調査対象とみなします。 引数のデータ型が異なる演算子は、検索パス内の位置に関係なく、同じように調べられます。

  2. Check for an operator accepting exactly the input argument types. If one exists (there can be only one exact match in the set of operators considered), use it. Lack of an exact match creates a security hazard when calling, via qualified name 正確に入力引数型を受け付ける演算子があるかどうか検査します。 該当する演算子があれば(調査される演算子の集合内で正確に一致するものは1つしかあり得ません)、それを使用します。 正確に一致するものがない場合、信用できないユーザにオブジェクトの作成を許可しているスキーマで見つかる演算子を、(典型的なものではないですが)修飾された名前で [9] (not typical), any operator found in a schema that permits untrusted users to create objects. In such situations, cast arguments to force an exact match. 呼び出す時にセキュリティの危険が発生します。 そのような状況では、強制的に正確に一致するように引数をキャストしてください。

    1. If one argument of a binary operator invocation is of the <type>unknown</type> type, then assume it is the same type as the other argument for this check. Invocations involving two <type>unknown</type> inputs, or a prefix operator with an <type>unknown</type> input, will never find a match at this step. 二項演算子の1つの引数がunknown型であった場合、この検査のもう片方の引数と同一の型であると仮定します。 2つのunknown入力、もしくはunknown入力を伴う前置演算子が呼び出された場合、この段階で対を見つけることはありません。

    2. If one argument of a binary operator invocation is of the <type>unknown</type> type and the other is of a domain type, next check to see if there is an operator accepting exactly the domain's base type on both sides; if so, use it. 二項演算子の1つの引数がunknown型であり、もう1つがドメイン型の場合、次に両側でドメインの基本型を厳密に受け付ける演算子があるかを確認します。

  3. Look for the best match. 最もよく合うものを検索します。

    1. Discard candidate operators for which the input types do not match and cannot be converted (using an implicit conversion) to match. <type>unknown</type> literals are assumed to be convertible to anything for this purpose. If only one candidate remains, use it; else continue to the next step. 演算子の候補のうち、入力値のデータ型が一致せず、また、(暗黙的な変換を使用して)一致するように変換できないものを破棄します。 unknownリテラルは、上記の目的で何にでも変換可能とみなされます。 1つの候補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    2. If any input argument is of a domain type, treat it as being of the domain's base type for all subsequent steps. This ensures that domains act like their base types for purposes of ambiguous-operator resolution. 入力引数のいずれかがドメイン型であれば、以降の段階すべてでドメインの基本型であるかのように扱います。 これにより、曖昧な演算子を解決するのを目的としてその基本型であるかのようにドメインが振る舞うことが確実になります。

    3. Run through all candidates and keep those with the most exact matches on input types. Keep all candidates if none have exact matches. If only one candidate remains, use it; else continue to the next step. 全ての候補を検索し、入力型に最も正確に合うものを残します。 正確に合うものが何もなければ全ての候補を残します。 1つの候補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    4. Run through all candidates and keep those that accept preferred types (of the input data type's type category) at the most positions where type conversion will be required. Keep all candidates if none accept preferred types. If only one candidate remains, use it; else continue to the next step. 全ての候補を検索し、型変換が必要とされる所で(入力データ型カテゴリの)優先される型を受け付けるものを残します。 優先される型を受け付けるものが何もなければ全ての候補を残します。 1つの候補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    5. If any input arguments are <type>unknown</type>, check the type categories accepted at those argument positions by the remaining candidates. At each position, select the <type>string</type> category if any candidate accepts that category. (This bias towards string is appropriate since an unknown-type literal looks like a string.) Otherwise, if all the remaining candidates accept the same type category, select that category; otherwise fail because the correct choice cannot be deduced without more clues. Now discard candidates that do not accept the selected type category. Furthermore, if any candidate accepts a preferred type in that category, discard candidates that accept non-preferred types for that argument. Keep all candidates if none survive these tests. If only one candidate remains, use it; else continue to the next step. 入力引数でunknownのものがあった場合、それらの残った候補に引数位置で受け入れられる型カテゴリを検査します。 各位置において、候補がstringカテゴリを受け付ける場合は、そのカテゴリを選択します (unknown 型のリテラルは文字列のようなものですので、この文字列への重み付けは適切です)。 そうでなければ、もし残った全ての候補が同じ型カテゴリを受け入れる場合はそのカテゴリを選択します。 そうでもなければ、さらに手掛かりがなければ正しい選択が演繹されることができませんので、失敗となります。 ここで、選択された型カテゴリを受け付けない演算子候補は破棄されます。 さらに、それらカテゴリ内の優先される型を受け付ける候補が1つでもある場合、その引数の優先されない型を受け付ける候補は破棄されます。 これらの検査をどれも通らなかったら全ての候補を残します。 1つの候補しか残らない場合、それを使います。 それ以外の場合は次の段階に進みます。

    6. If there are both <type>unknown</type> and known-type arguments, and all the known-type arguments have the same type, assume that the <type>unknown</type> arguments are also of that type, and check which candidates can accept that type at the <type>unknown</type>-argument positions. If exactly one candidate passes this test, use it. Otherwise, fail. もしunknownと既知の型の引数の両方があり、そして全ての既知の型の引数が同じ型を持っていた場合、unknown引数も同じ型であると仮定し、 どの候補がunknown引数の位置にある型を受け付けることができるかを検査します。 正確に1つの候補がこの検査を通過した場合、それを使います。それ以外は失敗します。

Some examples follow. 以下に例を示します。

例10.1 平方根演算子の型解決

<title>Square Root Operator Type Resolution</title>

There is only one square root operator (prefix <literal>|/</literal>) defined in the standard catalog, and it takes an argument of type <type>double precision</type>. The scanner assigns an initial type of <type>integer</type> to the argument in this query expression: 平方根演算子として、double precisionを引数とするものが標準カタログ内に1つのみ定義されています(|/を前に付けます)。 スキャナは、以下の問い合わせ式の引数にまずinteger型を割り当てます。

SELECT |/ 40 AS "square root of 40";
 square root of 40
-------------------
 6.324555320336759
(1 row)

So the parser does a type conversion on the operand and the query is equivalent to: パーサはオペランドを型変換し、問い合わせは以下と等価になります。

SELECT |/ CAST(40 AS double precision) AS "square root of 40";


例10.2 文字列連結演算子の型解決

<title>String Concatenation Operator Type Resolution</title>

A string-like syntax is used for working with string types and for working with complex extension types. Strings with unspecified type are matched with likely operator candidates. 文字列類似構文は、文字列の作業の他、複雑な拡張型の作業にも使用されます。 型の指定がない文字列は、類似演算子候補に一致します。

An example with one unspecified argument: 例えば、以下は指定がない引数が1つあります。

SELECT text 'abc' || 'def' AS "text and unknown";

 text and unknown
------------------
 abcdef
(1 row)

In this case the parser looks to see if there is an operator taking <type>text</type> for both arguments. Since there is, it assumes that the second argument should be interpreted as type <type>text</type>. この場合、パーサは両引数でtextを取る演算子があるかどうかを検索します。 この演算子は存在しますので、第二引数はtext型として解釈されるものと仮定されます。

Here is a concatenation of two values of unspecified types: 以下は型の指定がない2つの値の連結です。

SELECT 'abc' || 'def' AS "unspecified";

 unspecified
-------------
 abcdef
(1 row)

In this case there is no initial hint for which type to use, since no types are specified in the query. So, the parser looks for all candidate operators and finds that there are candidates accepting both string-category and bit-string-category inputs. Since string category is preferred when available, that category is selected, and then the preferred type for strings, <type>text</type>, is used as the specific type to resolve the unknown-type literals as. この場合、問い合わせ内に型が指定されていませんので、どの型を使用すべきかについての初期の指針がありません。 ですから、パーサは全ての演算子候補を検索し、文字列カテゴリとビット列カテゴリ入力を受け付ける候補を見つけます。 使用できる場合は文字列カテゴリが優先されますので、文字列カテゴリが選択され、それから文字列に対して優先される型であるtextが、不明のリテラルを解決する型として使用されます。


例10.3 絶対値と否定演算子の型解決

<title>Absolute-Value and Negation Operator Type Resolution</title>

The <productname>PostgreSQL</productname> operator catalog has several entries for the prefix operator <literal>@</literal>, all of which implement absolute-value operations for various numeric data types. One of these entries is for type <type>float8</type>, which is the preferred type in the numeric category. Therefore, <productname>PostgreSQL</productname> will use that entry when faced with an <type>unknown</type> input: PostgreSQLの演算子カタログには、前置演算子@用に複数の項目があります。 これは全て各種数値データ型に対する絶対値計算を実装するものです。 その1つは、数値カテゴリの優先される型であるfloat8型用の項目です。 したがって、PostgreSQLは、unknownの入力があった場合にこれを使用します。

SELECT @ '-4.5' AS "abs";
 abs
-----
 4.5
(1 row)

Here the system has implicitly resolved the unknown-type literal as type <type>float8</type> before applying the chosen operator. We can verify that <type>float8</type> and not some other type was used: ここでシステムは、選択した演算子を適用する前に、unknown型のリテラルをfloat8へ暗黙的に型変換します。 以下のようにfloat8が使用され、他の型が使用されていないことを検証できます。

SELECT @ '-4.5e500' AS "abs";

ERROR:  "-4.5e500" is out of range for type double precision

On the other hand, the prefix operator <literal>~</literal> (bitwise negation) is defined only for integer data types, not for <type>float8</type>. So, if we try a similar case with <literal>~</literal>, we get: 一方、前置演算子~(ビット否定)は、整数データ型のみで定義され、float8用は定義されていません。 ですから、~における上と同様の場合では、以下のような結果になります。

SELECT ~ '20' AS "negation";

ERROR:  operator is not unique: ~ "unknown"
HINT:  Could not choose a best candidate operator. You might need to add
explicit type casts.

This happens because the system cannot decide which of the several possible <literal>~</literal> operators should be preferred. We can help it out with an explicit cast: これは、システムが、複数の~演算子候補のうちどれが優先されるかを決定することができなかったため発生します。 明示的なキャストを使用することで補助することができます。

SELECT ~ CAST('20' AS int8) AS "negation";

 negation
----------
      -21
(1 row)


例10.4 配列包含演算子の型解決

<title>Array Inclusion Operator Type Resolution</title>

Here is another example of resolving an operator with one known and one unknown input: 一方は既知でありもう一方は未知である入力を伴った演算子の解決のもう一つの例です。

SELECT array[1,2] <@ '{1,2,3}' as "is subset";

 is subset
-----------
 t
(1 row)

The <productname>PostgreSQL</productname> operator catalog has several entries for the infix operator <literal>&lt;@</literal>, but the only two that could possibly accept an integer array on the left-hand side are array inclusion (<type>anyarray</type> <literal>&lt;@</literal> <type>anyarray</type>) and range inclusion (<type>anyelement</type> <literal>&lt;@</literal> <type>anyrange</type>). Since none of these polymorphic pseudo-types (see <xref linkend="datatype-pseudo"/>) are considered preferred, the parser cannot resolve the ambiguity on that basis. However, <xref linkend="op-resol-last-unknown"/> tells it to assume that the unknown-type literal is of the same type as the other input, that is, integer array. Now only one of the two operators can match, so array inclusion is selected. (Had range inclusion been selected, we would have gotten an error, because the string does not have the right format to be a range literal.) PostgreSQLの演算子カタログは、<@中置演算子のためのいくつかのエントリを持っていますが、 数値型配列を左側に受け付けることができるのは配列包含(anyarray <@ anyarray)と範囲包含(anyelement <@ anyrange)の2つのみです。 これらの多様な擬似データ型(8.21を参照)は優先されると見なされないため、このような方法ではパーサは曖昧さを解決することができません。 しかし、ステップ 3.fでは、未知の型のリテラルを別の入力と同じ型であると仮定するために数値配列とみなします。 今のところ2つのうち一つの演算子だけがマッチできるため、配列包含が選択されます。(範囲包含が選択された場合、演算子の右側にある文字列は正しい範囲型のリテラルではないため、エラーとなるでしょう。)


例10.5 ドメイン型の独自の演算子

<title>Custom Operator on a Domain Type</title>

Users sometimes try to declare operators applying just to a domain type. This is possible but is not nearly as useful as it might seem, because the operator resolution rules are designed to select operators applying to the domain's base type. As an example consider 利用者はときどきドメイン型にのみ適用される演算子を宣言しようとします。 これは可能ですが、思ったほど便利ではありません。演算子の解決規則がドメイン基本型に適用される演算子を選ぶように設計されているからです。 例として、以下を考えてください。

CREATE DOMAIN mytext AS text CHECK(...);
CREATE FUNCTION mytext_eq_text (mytext, text) RETURNS boolean AS ...;
CREATE OPERATOR = (procedure=mytext_eq_text, leftarg=mytext, rightarg=text);
CREATE TABLE mytable (val mytext);

SELECT * FROM mytable WHERE val = 'foo';

This query will not use the custom operator. The parser will first see if there is a <type>mytext</type> <literal>=</literal> <type>mytext</type> operator (<xref linkend="op-resol-exact-unknown"/>), which there is not; then it will consider the domain's base type <type>text</type>, and see if there is a <type>text</type> <literal>=</literal> <type>text</type> operator (<xref linkend="op-resol-exact-domain"/>), which there is; so it resolves the <type>unknown</type>-type literal as <type>text</type> and uses the <type>text</type> <literal>=</literal> <type>text</type> operator. The only way to get the custom operator to be used is to explicitly cast the literal: この問い合わせには独自の演算子を使いません。 パーサはまずmytext = mytext演算子(ステップ 2.a)があるか確認しますが、ありません。次にドメイン基本型textを考慮してtext = text演算子(ステップ 2.b)があるか確認すると、あります。そのためunknown型はtextとして解決され、text = text演算子が使われます。 独自の演算子を使う唯一の方法は、リテラルを明示的にキャストすることだけです。

SELECT * FROM mytable WHERE val = text 'foo';

so that the <type>mytext</type> <literal>=</literal> <type>text</type> operator is found immediately according to the exact-match rule. If the best-match rules are reached, they actively discriminate against operators on domain types. If they did not, such an operator would create too many ambiguous-operator failures, because the casting rules always consider a domain as castable to or from its base type, and so the domain operator would be considered usable in all the same cases as a similarly-named operator on the base type. これにより、「正確な一致」規則に従ってmytext = text演算子がすぐに見つかります。 もし、「最善の一致」規則に達した場合、ドメイン型の演算子を積極的に差別します。 そうでなければ、そのような演算子は非常に多くの「曖昧な演算子」の失敗を引き起こします。キャストの規則はドメインをその基本型からもしくは基本型へキャスト可能と考え、ドメイン演算子は基本型の似たような名前の演算子とすべて同じ状況で利用できると考えられるからです。




If you edit this, consider editing func-qualified-security.

[9] The hazard does not arise with a non-schema-qualified name, because a search path containing schemas that permit untrusted users to create objects is not a <link linkend="ddl-schemas-patterns">secure schema usage pattern</link>. 信用できないユーザにオブジェクトの作成を許可するスキーマを含む検索パスは、安全なスキーマ使用パターンではありませんので、スキーマで修飾されていない名前では危険は起こりません。