Use uma consulta parametrizada conforme descrito nos documentos
Como você já tem um dict, você pode fazer:
sql_data_sample = """select * from %(table_name)s
where dt = %(date_from)s
and target in ('ACTIVE')
----------------------------------------------------
union all
----------------------------------------------------
(select * from %(table_name)s
where dt = %(date_to)s
and target in (%(class_target)s));"""
cur.execute(sql_data_sample, query_params)
Eu não testei se funciona com um dict odered, mas acho que deveria. Caso contrário, você pode tornar seu dict ordenado um dict regular antes de passá-lo como mapeamento de parâmetros.
EDITAR A menos que você precise que seus parâmetros sejam um OrderedDict mais tarde, use um dict regular. Até onde posso ver, você optou apenas por um OrderedDict para preservar a ordem de valor para o
list(query_params.values())[0]
. EDIT2 Nomes de tabela e nomes de campo não podem ser passados usando associações. Antoine Dusséaux apontou esta resposta que o psycopg2 oferece uma maneira mais ou menos segura de fazer isso desde a versão 2.7.
from psycopg2 import sql
sql_data_sample = """select * from {0}
where dt = %(date_from)s
and target in ('ACTIVE')
----------------------------------------------------
union all
----------------------------------------------------
(select * from {0}
where dt = %(date_to)s
and target in (%(class_target)s));"""
cur.execute(sql.SQL(sql_data_sample)
.format(sql.Identifier(query_params['table_name'])),
query_params)
Você pode ter que remover o
table_name
do seu dict, não tenho certeza de como o psycopg2 reage em itens adicionais no dict de parâmetros e não posso testá-lo agora. Deve-se ressaltar que isso ainda apresenta o risco de injeção de SQL e deve ser evitado, a menos que seja absolutamente necessário. Normalmente, os nomes de tabelas e campos são uma parte fixa de uma string de consulta.
Aqui está a documentação relevante para o
sql
módulo
.