【问题标题】:How to use prepared statements in DO statements?如何在 DO 语句中使用准备好的语句?
【发布时间】:2018-11-22 20:13:47
【问题描述】:

我有一个相当复杂的查询,我试图使用准备好的语句来保护我的数据库免受 SQL 注入。我基本上已经将多个查询链接在一个 begin-end 块下。

此复合查询首先检查用户会话是否存在,然后检查用户是否已被禁止,然后用户输入的标签是否有效,最后将帖子插入数据库。

这里是查询:

query = "DO
    $$
    BEGIN
        IF 
            (select exists(select user_id from sessions where unqid = $1 and user_id = $2))
        THEN
            IF 
                (select banned_till from users where unqid = $2) > now() 
            THEN
                RAISE EXCEPTION 'User has been banned!';
            ELSE 
                IF (
                    Select ( SELECT array_agg(DISTINCT name) FROM allowed_tags) @> $3) 
                THEN
                    insert into posts (unqid, title, link, content, user_id, user_nick, user_flair, 
                    tags, tags_details, likes, likes_details) 
                        SELECT $4, $5, $6, $7, 
                        $2, user_nick, user_flair, 
                        $8, $9, 1, $10
                        from users where unqid = $2;
                ELSE
                    RAISE EXCEPTION 'Fake tags detected!';
                END IF;
            END IF;
        ELSE
            RAISE EXCEPTION 'User is not logged in';
        END IF;
    END
    $$;"

DB.exec query, 
    session_id, session_user, tags_list, unqid, title, link, content, 
    tags_obj.to_json, tags_details_obj.to_json, likes_obj.to_json

当我使用字符串插值时,此查询工作正常。但是当我尝试使用准备好的语句时,我开始得到;

bind message supplies 10 parameters, but prepared statement "" requires 0

如何在查询中使用准备好的语句?

【问题讨论】:

    标签: postgresql transactions prepared-statement


    【解决方案1】:

    您不能将DO 语句用作预准备语句。

    我建议你使用两个语句:

    • 一个得到三个结果,判断是否存在错误情况

    • 一个运行INSERT 语句

    其中的第二个将是一个常规的准备好的语句。

    在我看来,您在 PL/pgSQL 中混淆了事务和 BEGIN ... END 块。

    【讨论】:

    • 谢谢。我很担心那个。我想我必须回去重构我的查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    相关资源
    最近更新 更多