web-dev-qa-db-ja.com

動的SQLの関数でパラメーターを使用するワイルドカード検索

動的SQLを使用する関数でパラメーターを使用する場合、PostgreSQLでワイルドカード検索を実装する適切な方法は何ですか?

開始点として、以下は、スタックオーバーフローに関する別の質問に答えるErwin Brandstetterの例です。

https://stackoverflow.com/a/12047277/538962

CREATE OR REPLACE FUNCTION report_get_countries_new (starts_with text
                                                   , ends_with   text = NULL)
RETURNS SETOF lookups.countries AS
$func$
DECLARE
   sql text := 'SELECT * FROM lookups.countries WHERE country_name >= $1';
BEGIN
   IF ends_with IS NOT NULL THEN
      sql := sql || ' AND country_name <= $2';
   END IF;

   RETURN QUERY EXECUTE sql
   USING starts_with, ends_with;
END
$func$ LANGUAGE plpgsql;

country_name先頭と末尾のワイルドカード検索を実行したいと考えていました。

たとえば、パラメータを使用せずに、AND country_name LIKE '%ic%'

SQLインジェクションのリスクを否定することに関して、このシナリオでワイルドカード検索を実装する最良の方法は何ですか?

2
mg1075

country_nameで、先頭と末尾のワイルドカード検索を実行したいとします。

これには動的SQLは必要ありません。ただ:

CREATE OR REPLACE FUNCTION report_get_countries_new (_pattern text)
  RETURNS SETOF lookups.countries AS
$func$
   SELECT *
   FROM   lookups.countries
   WHERE  country_name LIKE '%' || _pattern || '%'
$func$ LANGUAGE sql;

コール:

SELECT * FROM report_get_countries_new ('ic');  -- without wildcards!

これは、SQLインジェクションのリスクを完全に無効にします

呼び出し元はワイルドカードを自由に含めることができます(パラメーターを処理してワイルドカードをフィルター処理しない限り)。ただし、ハードコーディングされた先頭のワイルドカードと後続のワイルドカードがあります(パラメーターが\で終了し、末尾の%から特別な意味が削除されている場合を除く)。

PL/pgSQLで動的SQLとEXECUTEを使用する場合でも、USING句を使用して値をvaluesとして渡す限り、SQLインジェクションのリスクはありません。

関連:

4