web-dev-qa-db-ja.com

PostgreSQLエラー:リモート関数呼び出しで、リモートクエリ結果の行タイプが指定されたFROM句の行タイプと一致しません

これは私のリモート機能です:

CREATE OR REPLACE FUNCTION public._test1()
RETURNS record
LANGUAGE plpgsql
AS $function$
DECLARE
 rec record;
BEGIN
  select 1,2 into rec;
  return rec;
END $function$;

これは私のlocal関数呼び出しです。

SELECT x.a, x.b
FROM dblink('conn_str', 'select public._test1();')
as x(a int ,b int);

これはスローされたエラーです:

ERROR: remote query result rowtype does not match the specified FROM clause rowtype

DBLINKでは、関数の戻りアイテムを配置するスキーマを定義する必要があるため、関数から返されているrecord型を認識するための呼び出しを行うにはどうすればよいですか?

1
Kenobi

何が起こっているのかを理解するには、まずリモートで何が行われているかを確認します。

_SELECT _test1();
 _test1 
────────
 (1,2)
_

これは、2つの整数ではなく、レコードを返します。 dblink()呼び出しがレポートするとき

_ERROR:  remote query result rowtype does not match the specified FROM clause rowtype
_

これは、ローカルで行タイプをx(a int, b int)として定義したためですが、リモートのレコードと一致しません。その理由は、dblink()自体が(_SETOF record_戻り型を持っているため)自分自身が認識していないため、この情報をリモートにプッシュできないためです。だからあなたがしなければならないことは次のとおりです:

_SELECT * 
  FROM dblink('local', 'SELECT * FROM _test1() AS x(a int, b int)') AS t(a int, b int);

 a │ b 
───┼───
 1 │ 2
_

レコードタイプを2回指定することは不必要に思えますが、ローカルレコードタイプを省略した場合、別のエラーが発生します。

_SELECT * FROM dblink('local', 'SELECT * FROM _test1() AS x(a int, b int)') AS t;
ERROR:  a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM dblink('local', 'SELECT * FROM _test1() AS x(a...
                      ^
_

リモートレコード定義の省略:

_SELECT * FROM dblink('local', 'SELECT * FROM _test1() ') AS t(a int, b int);
ERROR:  a column definition list is required for functions returning "record"
CONTEXT:  Error occurred on dblink connection named "local": could not execute query.
_

(エラーメッセージの違いは、今回はリモート側に問題があることを示しています。)

私のバージョンで異なる鉱石の1つはSELECT * FROM _test()です。 SELECT句の代わりにFROMリストで関数を呼び出すとどうなるかを確認します。

_SELECT * FROM dblink('local', 'SELECT _test1() AS x(a int, b int)') AS t(a int, b int);
ERROR:  syntax error at or near "("
CONTEXT:  Error occurred on dblink connection named "local": could not execute query.
_

リモート関数を_RETURNS TABLE_として作成した場合(または、同等にOUT引数を定義した場合)、これをより良くすることができます。

_-- on the remote
CREATE FUNCTION bla() 
    RETURNS TABLE (a int, b int) LANGUAGE SQL AS $$
    SELECT 1, 2
$$;


SELECT * FROM dblink('local', 'SELECT * FROM bla() ') AS t(a int, b int);
 a │ b 
───┼───
 1 │ 2
_

recordタイプは柔軟に設計されていますが、価格が高くなります。ただし、dblink()を使用してこの価格を支払うことは避けられません。戻り値の型に対応できる必要があるためです。

1
dezso