5

PHP配列を次の関数に渡すことにほとんど成功していません。

$recipients = array();
$recipients['6c2f7451-bac8-4cdd-87ce-45d55d152078'] = 5.00;
$recipients['8c2f3421-bac8-4cdd-87ce-45d55d152074'] = 10.00;

$originator = '5630cc6d-f994-43ff-abec-1ebb74d39a3f';
$params = array($originator, $recipients);

pg_query_params(_conn, 'SELECT widgetallocationrequest($1, $2)', $params);

$results = pg_fetch_all(pg_query_params);
...

この関数は、カスタム タイプの配列を受け入れます。

CREATE TYPE widgetallocationrequest AS (id uuid, amount numeric(13,4));

各項目を列挙し、アクションを実行します。

CREATE FUNCTION distributeWidgets(pid uuid, precipients widgetallocationrequest[])
 RETURNS BOOLEAN AS
 $BODY$
{
FOREACH v_recipient IN ARRAY precipients
LOOP
    ...do something
END LOOP;
}
  RETURN TRUE;
END;
$BODY$
LANGUAGE plpgsql VOLATILE STRICT
COST 100;

***(if the specific code sample contains errors it's only pseudocode, i'm really just looking for the best way to pass a php array to a postgres custom type array as a parameter so it can be enumerated in the postgres function)***

更新: 次のようにして、postgres から直接 (PHP からではなく) 関数を正常に呼び出すことができます。

SELECT distributeWidgets('5630cc6d-f994-43ff-abec-1ebb74d39a3f',
ARRAY[('ac747f0e-93d4-43a9-bc5b-09df06593239', '5.00'), ('8c2f3421-bac8-4cdd-87ce-45d55d152074', '10.00')]::widgetallocationrequest[]);

しかし、この postgres の例を PHP に変換する方法がまだわかりません

以下の提案を試してみましたが、参照された関数からの出力で次のエラーが発生します。

ここに画像の説明を入力

関数からの文字列は次のとおりです。

'SELECT account.hldtoexpalloc('0d6311cc-0d74-4a32-8cf9-87835651e1ee', '0124a045-b2e8-4a9f-b8c4-43b1e4cf638d', '{{\"6c2f7451-bac8-4cdd-87ce-45d55d152078\",5.00},{\"8c2f3421-bac8-4cdd-87ce-45d55d152074\",10.00}}')'
4

2 に答える 2

4

更新:配列だけでなく、複合型の配列を使用する必要があることに気付きました。イク。私は彼らと一緒に仕事をする必要がなかったので、少し確認する必要がありました。

配列の正しい PostgreSQL 構文は次のようにwidgetallocationrequestなります。

'{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}'::widgetallocationrequest[]

複合型の各行が"(col1,col2)"配列{a,b,c}コンテナー内にどのように含まれているかがわかりますか?

値を作成する方法の PostgreSQL SQL の例を次に示します。

-- Create the array of composites from a VALUES() statement
--
SELECT array_agg(x::widgetallocationrequest) 
FROM (VALUES 
    ('8c2f3421-bac8-4cdd-87ce-45d55d152074',10.00),
    ('6c2f7451-bac8-4cdd-87ce-45d55d152078',5.00)
) x;

...そして、それが有効であることをどのように確認したか:

-- Unpack it back into a row-set of columns
SELECT * FROM unnest('{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}'::widgetallocationrequest[]);

現在、Pg 用の PHP ドライバーは、複合型の配列は言うまでもなく、配列もサポートしていません。信頼できるパーサーを書くことは「楽しい」ものであり、生産的な時間の使い方ではありません。

widgetallocationrequest[]別のアプローチを取りましょう:内部 PostgreSQLへの変換を行うことにより、正常に関数を呼び出すことができるクエリを作成します。

これは、呼び出しターゲットとして使用する実際の関数と同じ引数を持つダミー関数です。

CREATE OR REPLACE FUNCTION distributeWidgets(pid uuid, precipients widgetallocationrequest[]) RETURNS boolean AS $$
SELECT 't'::boolean;
$$ LANGUAGE 'sql';

非常に面倒な複合配列の構文で呼び出すことができることがわかります。

SELECT distributewidgets(null, '{"(8c2f3421-bac8-4cdd-87ce-45d55d152074,10.0000)","(6c2f7451-bac8-4cdd-87ce-45d55d152078,5.0000)"}');

...しかし、理想的には、PHP からそのような恐ろしいものを生成することは避けたいと考えており、ドライバーには重要な機能が欠けているため、それを行うことはできません。

代わりに、TEMPORARYテーブルを使用して引数を生成し、INSERT各引数行を通常のパラメーター化されたINSERTs でテーブルに入れ、クエリを実行して関数を実行できます。

BEGIN;

CREATE TEMPORARY TABLE dw_args ( id uuid, amount numeric(13,4) );

-- Use proper parameterized INSERTs from PHP, this is just an example
INSERT INTO dw_args(id,amount) VALUES ('8c2f3421-bac8-4cdd-87ce-45d55d152074',10.00);
INSERT INTO dw_args(id,amount) VALUES ('6c2f7451-bac8-4cdd-87ce-45d55d152078',5.00);

SELECT distributewidgets(null, array_agg(ROW(x.*)::widgetallocationrequest)) 
FROM dw_args x;

DROP TABLE dw_args;

COMMIT;

警告: 以下は、慎重に処理しないと、 SQL インジェクションに対して脆弱です。可能であれば、上記の一時テーブルのアプローチを使用してください。ボビーの次の犠牲者にならないでください。SQL インジェクションに関する PHP ドキュメントを読んでください。

なんらかの理由ですべてを 1 つのステートメントで実行することが絶対に必要な場合は、代わりに PHP からセットを使用してクエリを作成し、それを PostgreSQL クエリを使用してVALUES変換することができます。widgetallocationrequest[]上記で説明しましたが、これを の呼び出しと組み合わせる方法は次の distributeWidgets(...)とおりです。

SELECT distributewidgets(null, array_agg(x::widgetallocationrequest)) 
FROM (VALUES 
        ('8c2f3421-bac8-4cdd-87ce-45d55d152074',10.00),
        ('6c2f7451-bac8-4cdd-87ce-45d55d152078',5.00)
) x;

これは、 SQL インジェクションに細心の注意を払っている限り、文字列操作を使用して PHP で非常に簡単に構築できるものです。

可能であれば、一時テーブル アプローチを使用してください。

PHP 配列から postgres 配列も参照してください

于 2012-08-21T02:19:46.067 に答える
3

«現在、PHPのPgドライバーは、複合型の配列は言うまでもなく配列もサポートしていないため、必要なものを作成した人を見つけるか、自分で作成する必要があります。信頼できるパーサーを作成することは「楽しい」ことであり、時間の生産的な使用ではありません。»»

Pommのコンバーターシステムを使用できます。配列とHStoreを解析し、独自の型コンバーターを定義することもでき、その配列を処理します。

お役に立てば幸いです。

于 2012-08-21T07:52:48.643 に答える