提供されたパラメーターに基づいて条件付きでデータを削除する関数を作成しようとしています。デフォルトのパラメーターを使用できるようにしたいので、明示的に指定されていない場合、関数はフィルタリングを実行しません。2つのフィルタリングタイプの最初のタイプは時間範囲であり、2番目のタイプは主キーの配列です。
時間範囲については、デフォルトのセンチネル変数を使用できます+/- infinity
。これはすべてのデータと一致し、本質的にフィルターを無効にします。これらはpostgresによって提供されます。配列ベースのフィルターを無効にするために使用できるもの(ある種の番兵)はありますか?
具体的には、関数に整数の配列を渡しますが、デフォルトでこのフィルターを無効にします(つまり、配列を渡さない場合)。明らかな選択は、デフォルトのパラメータとして配列を空の配列に設定することです。ただし、where in
空の配列では何にも一致しません(空の配列が有効なplpgqlでさえある場合)。したがって、明らかな選択は、IF
ステートメントまたは動的SQLを使用することです。しかし、postgresを知っていると、私が見逃したかもしれないトリックや構文が必要です。
編集:
私の最初の計画は、私が望む動作をエミュレートするブールUDFを作成することでした。の線に沿った何か:
CREATE OR REPLACE FUNCTION filter_category(
category_array INTEGER[],
current_category INTEGER
)
RETURNS
BOOLEAN AS $$
BEGIN
IF category_array = '{}' THEN
RETURN TRUE;
ELSE
-- if in set return true, else false.
RETURN FALSE;
END IF;
END;
$$ LANGUAGE plpgsql;
ただし、この問題についてさらに検討した後、クエリはより複雑になる必要があると思います。節、または上記のwhere in array
関数は、おそらくあまり効率的ではありません。したがって、存在する可能性のあるインデックスを使用することになるには、主キーの配列をアンネストして結合を実行する必要があります。
そして、配列がnullでない場合にのみこれを行う必要があります。したがって、クエリには少なくとも1つの `IF ... ELSE ... ENDIF'ステートメントが必要です。さらにフィルタリングを行う必要がある場合は、中間のローカルデータセットを実装する必要があるかもしれません。それでも私はアドバイスに興味があります:D
編集2:
私の動的クエリは次のようになります。
CREATE OR REPLACE FUNCTION get_paginated_search_results(
forum_id_ INTEGER,
query_ CHARACTER VARYING,
from_date_ TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
to_date_ TIMESTAMP WITHOUT TIME ZONE DEFAULT NULL,
in_categories_ INTEGER[] DEFAULT '{}')
RETURNS SETOF post_result_entry AS $$
DECLARE
join_string CHARACTER VARYING := ' ';
from_where_date CHARACTER VARYING := ' ';
to_where_date CHARACTER VARYING := ' ';
query_string_ CHARACTER VARYING := ' ';
BEGIN
IF NOT from_date_ IS NULL THEN
from_where_date := ' AND fp.posted_at > ''' || from_date_ || '''';
END IF;
IF NOT to_date_ IS NULL THEN
to_where_date := ' AND fp.posted_at < ''' || to_date_ || '''';
END IF;
CREATE LOCAL TEMP TABLE un_cat(id) ON COMMIT DROP AS (select * from unnest(in_categories_)) ;
if in_categories_ != '{}' THEN
join_string := ' INNER JOIN forum_topics ft ON fp.topic_id = ft.id ' ||
' INNER JOIN un_cat uc ON uc.id = ft.category_id ' ;
END IF;
query_string_ := '
SELECT index,posted_at,post_text,name,join_date,quotes
FROM forum_posts fp
INNER JOIN forum_user fu ON
fu.forum_id = fp.forum_id AND fu.id = fp.user_id' ||
join_string
||
'WHERE fu.forum_id = ' || forum_id_ || ' AND
to_tsvector(''english'',fp.post_text) @@ to_tsquery(''english'','''|| query_||''')' ||
from_where_date ||
to_where_date
||';';
RAISE NOTICE '%', query_string_ ;
RETURN QUERY
EXECUTE query_string_;
END;
$$ LANGUAGE plpgsql;