Необработанные запросы Django и переменная, объявляемая Postgres
У меня есть файл с множеством необработанных sql-запросов, в котором используется подстановка текста, т.е.
select * from table1 where date_col between '%%from_date%%' and '%%to_date%%'
затем эти %%date_from%% и %%date_to%% заменяются значениями с помощью функции python string replace. Это работает нормально, и запросы работают. Однако это не является бездействием, так как может быть открыто для sql-инъекций. (и нет, я не могу использовать модели или что-то еще, кроме необработанного sql), что еще хуже, я не могу использовать %s и параметризировать запросы, потому что переменные меняют порядок, а %s работает по порядку (насколько я могу судить)
Я думал об использовании declare, чтобы иметь мои переменные в начале блока select, т.е.
sql -
declare from_date date:= %s
declare to_date date:= %s
select * from table1 where date_col between to_date and from_date
python -
with with connection.cursor() as cursor:
cursor.execute(query, [from_date, to_date'])
но это выдает
django.db.utils.ProgrammingError: syntax error at or near "date"
LINE 1: DECLARE from_date date := '2022-01-01'::date DECLARE to_date...
^
Я не знаю, что я делаю неправильно и буду рад любой помощи. насколько я могу судить, я правильно понял синтаксис, возможно django raw queries поддерживает только select? есть ли другой способ заставить его работать с параметризацией? буду признателен за помощь
Попробуйте сделать верхний CTE для хранения ваших переменных, вместо этого:
with invars as (
select (%s)::date as from_date, (%s)::date as to_date
)
select *
from invars i
join table1 t
on t.date_col between i.to_date and i.from_date;
Если проблема в том, что иногда from_date
и to_date
путаются, то можно использовать BETWEEN SYMMETRIC
.
Если вам нужно использовать эти переменные в запросе или другом CTE, который не имеет ничего для присоединения к invars
, то используйте cross join
, чтобы сделать столбцы invar
доступными.