目的
ストアードプロシージャを使っていると入力パラメーターのチェックがしたくなります。
プログラム
CREATE OR REPLACE FUNCTION uv_set_test (
p_uuid UUID DEFAULT NULL
,p_start_at TIMESTAMPTZ DEFAULT NULL
,p_content TEXT DEFAULT NULL
) RETURNS VOID AS $FUNCTION$
DECLARE
BEGIN
-- パラメーターチェック
IF NOT (
p_uuid IS NOT NULL
AND p_start_at IS NOT NULL AND p_start_at >= '2000-01-01'
AND p_content IS NOT NULL AND p_content <> ''
) THEN
RAISE SQLSTATE 'U0002' USING MESSAGE = 'Invalid Parameter';
END IF;
-- 処理
END;
$FUNCTION$ LANGUAGE plpgsql;
毎回書くのは大変なので、共通化したいです。以下のようにします。
CREATE OR REPLACE FUNCTION uv_set_test (
p_uuid UUID DEFAULT NULL
,p_start_at TIMESTAMPTZ DEFAULT NULL
,p_content TEXT DEFAULT NULL
) RETURNS VOID AS $FUNCTION$
DECLARE
BEGIN
-- パラメーターチェック
PERFORM uv_check_parameter(
p_ary := ARRAY[
('uuid', p_uuid IS NOT NULL)
,('start_at', p_start_at IS NOT NULL AND p_start_at >= '2000-01-01')
,('content', p_content IS NOT NULL AND p_content <> '')
]::type_uv_check_parameter[]
);
-- 処理
END;
$FUNCTION$ LANGUAGE plpgsql;
結果は以下の通りです。
SELECT * FROM uv_set_test();
ERROR: Invalid parameter uuid, start_at, content
p_aryのパラメーターはエラーの時に表示する文字列と満たすべき条件になります。
条件が満たされない場合にペアの文字列が表示されます。
複数件チェックしてエラーを返すようにします。
DROP TYPE IF EXISTS type_uv_check_parameter CASCADE;
CREATE TYPE type_uv_check_parameter AS (
name TEXT
,value BOOLEAN
);
CREATE OR REPLACE FUNCTION uv_check_parameter(
p_ary type_uv_check_parameter[] DEFAULT NULL
,p_message TEXT DEFAULT 'Invalid parameter '
) RETURNS VOID AS $FUNCTION$
DECLARE
w_invalid_name_ary TEXT[] := ARRAY[]::TEXT[];
w_length BIGINT := COALESCE(array_length(p_ary, 1), 0);
BEGIN
-- 入力パラメーターチェック
IF w_length = 0 THEN
RAISE SQLSTATE 'U0002' USING MESSAGE = p_message || 'ary is empty';
END IF;
FOR i IN 1..w_length LOOP
IF p_ary[i].value IS TRUE THEN
NULL;
ELSE
w_invalid_name_ary:= w_invalid_name_ary || p_ary[i].name;
END IF;
END LOOP;
IF COALESCE(array_length(w_invalid_name_ary, 1), 0) > 0 THEN
RAISE SQLSTATE 'U0002' USING MESSAGE = p_message || array_to_string(w_invalid_name_ary, ', ');
END IF;
END;
$FUNCTION$ LANGUAGE plpgsql;