在PL / pgSQL中使用USING关键字清理用户输入

这就是我创建我的方式search_term

    IF char_length(search_term) > 0 THEN

order_by := 'ts_rank_cd(textsearchable_index_col, to_tsquery(''' || search_term || ':*''))+GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';

search_term := 'to_tsquery(''' || search_term || ':*'') @@ textsearchable_index_col';

ELSE

search_term := 'true';

END IF;

我在使用PLPGSQL函数时遇到了一些麻烦:

    RETURN QUERY EXECUTE '

SELECT

*

FROM

articles

WHERE

$1 AND

' || publication_date_query || ' AND

primary_category LIKE ''' || category_filter || ''' AND

' || tags_query || ' AND

' || districts_query || ' AND

' || capability_query || ' AND

' || push_notification_query || ' AND

' || distance_query || ' AND

' || revision_by || ' AND

' || publication_priority_query || ' AND

' || status_query || ' AND

is_template = ' || only_templates || ' AND

status <> ''DELETED''

ORDER BY ' || order_by || ' LIMIT 500'

USING search_term;

END; $$;

返回错误:

AND的参数必须为布尔型,而不是字符64处的文本

相对于:

        RETURN QUERY EXECUTE '

SELECT

*

FROM

articles

WHERE

' || search_term || ' AND

' || publication_date_query || ' AND

primary_category LIKE ''' || category_filter || ''' AND

' || tags_query || ' AND

' || districts_query || ' AND

' || capability_query || ' AND

' || push_notification_query || ' AND

' || distance_query || ' AND

' || revision_by || ' AND

' || publication_priority_query || ' AND

' || status_query || ' AND

is_template = ' || only_templates || ' AND

status <> ''DELETED''

ORDER BY ' || order_by || ' LIMIT 500';

END; $$;

…有效。我想念什么吗?

我的目标是清理用户输入。

回答:

如果某些输入参数可以为 NULL 或为 空, 并且在这种情况下应被忽略,则最好根据用户输入动态地构建整个语句-

并完全省略各自的WHERE/ORDER BY子句。

关键是在此过程中正确,安全(优雅地)处理NULL和空字符串。对于初学者来说,这search_term <>''

您需要对PL / pgSQL有深入的了解,否则您可能会陷入困境。您的案例的示例代码:

CREATE OR REPLACE FUNCTION my_func(

_search_term text = NULL -- default value NULL to allow short call

, _publication_date_query date = NULL

-- , more parameters

)

RETURNS SETOF articles AS

$func$

DECLARE

sql text;

sql_order text; -- defaults to NULL

BEGIN

sql := concat_ws(' AND '

,'SELECT * FROM articles WHERE status <> ''DELETED''' -- first WHERE clause is immutable

, CASE WHEN _search_term <> '' THEN '$1 @@ textsearchable_index_col' END -- ELSE NULL is implicit

, CASE WHEN _publication_date_query <> '' THEN 'publication_date > $2' END -- or similar ...

-- , more more parameters

);

IF search_term <> '' THEN -- note use of $1!

sql_order := 'ORDER BY ts_rank_cd(textsearchable_index_col, $1) + GREATEST(0,(-1*EXTRACT(epoch FROM age(last_edited)/86400))+60)/60 DESC';

END IF;

RETURN QUERY EXECUTE concat_ws(' ', sql, sql_order, 'LIMIT 500')

USING to_tsquery(_search_term || ':*') -- $1 -- prepare ts_query once here!

, _publication_date_query -- $2 -- order of params must match!

-- , more parameters

;

END

$func$ LANGUAGE plpgsql;

我为函数参数添加了默认值,因此您可以忽略在调用中不适用的参数。喜欢:

SELECT * FROM my_func(_publication_date_query => '2016-01-01');

以上是 在PL / pgSQL中使用USING关键字清理用户输入 的全部内容, 来源链接: utcz.com/qa/408459.html

回到顶部