Как использовать подготовленные заявления в заявлениях DO? - PullRequest
0 голосов
/ 22 ноября 2018

У меня довольно запутанный запрос, в котором я пытаюсь использовать подготовленные операторы для защиты своей базы данных от внедрения SQL.По сути, я связал несколько запросов в одном блоке начала и конца.

Этот составной запрос сначала проверяет, существуют ли сеансы пользователя, затем, если пользователь был забанен, затем, если введенные пользователем теги действительны, и, наконец, вставляет сообщение в базу данных.

Вот запрос:

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

Как использовать подготовленный оператор в моем запросе?

1 Ответ

0 голосов
/ 23 ноября 2018

Вы не можете использовать оператор DO как подготовленный оператор.

Я рекомендую использовать два оператора:

  • один получить три результата, которые вам нужнычтобы определить, существует ли условие ошибки

  • один для запуска оператора INSERT

Вторым из них будет обычный подготовленный оператор.

Мне кажется, что вы смешиваете транзакции и BEGIN ... END блоки в PL / pgSQL.

...