Pergunta

Por algumas razões, eu gostaria de fazer uma explícita citação de um valor string (tornando-se uma parte da consulta SQL construído) em vez de esperar para a citação implícita realizada pelo método cursor.execute no conteúdo de seu segundo parâmetro.

Por "citação implícita" Quero dizer:

value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;"
cursor.execute( query, (value,) ) # value will be correctly quoted

Eu preferiria algo assim:

value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
    READY_TO_USE_QUOTING_FUNCTION(value)
cursor.execute( query ) # value will be correctly quoted, too

É tal READY_TO_USE_QUOTING_FUNCTION baixo nível esperado pela especificação API Python DB (eu não poderia encontrar tal funcionalidade em PEP 249 documento ). Se não, talvez psycopg2 fornece tal função? Se não, talvez Django fornece tal função? Eu preferiria não escrever essa função me ...

Foi útil?

Solução

Ok, então eu estava curioso e fui e olhei para a fonte de psycopg2. Acontece que eu não tinha que ir mais longe do que os exemplos de pastas:)

E sim, este é específico do psycopg2. Basicamente, se você quiser apenas para citar uma seqüência que você faria isso:

from psycopg2.extensions import adapt

print adapt("Hello World'; DROP DATABASE World;")

Mas o que você provavelmente vai querer fazer é escrever e registrar o seu próprio adaptador;

Nos exemplos pasta de psycopg2 você encontrar o arquivo 'myfirstrecipe.py' há um exemplo de como elenco e citar um tipo específico de uma maneira especial.

Se você tem objetos para as coisas que você quer fazer, você pode simplesmente criar um adaptador que está em conformidade com o protocolo 'IPsycopgSQLQuote' (ver pydocs para o myfirstrecipe.py-exemplo ... na verdade, que é a única referência que eu posso encontrar a esse nome), que cita o seu objeto e, em seguida, registrá-lo assim:

from psycopg2.extensions import register_adapter

register_adapter(mytype, myadapter)

Além disso, os outros exemplos são interessantes; esp. 'dialtone.py' e 'simple.py' .

Outras dicas

Eu acho que você está procurando a função mogrify .

Exemplo:

>>> cur.mogrify("INSERT INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT INTO test (num, data) VALUES (42, E'bar')"

Você deve tentar evitar fazer seu próprio citando. Não só vai ser específico-DB como as pessoas têm apontado, mas falhas na citando são a fonte de erros de injeção SQL.

Se você não quer passar em torno de consultas e valores separadamente, em seguida, passar em torno de uma lista dos parâmetros:

def make_my_query():
    # ...
    return sql, (value1, value2)

def do_it():
    query = make_my_query()
    cursor.execute(*query)

(I provavelmente tem a sintaxe de errado cursor.execute) O ponto aqui é que só porque cursor.execute leva uma série de argumentos, isso não significa que você tem que lidar com todos eles separadamente. Você pode lidar com eles como uma lista.

Eu não acho que você dá qualquer fundamentação suficiente por trás de sua evitação de fazer isso Way The Right. Por favor, use a API como ele é projetado e não tentar tão duro para fazer o seu código menos legível para o próximo cara e mais frágil.

Este vai ser DB dependente. No caso de MySQLdb, por exemplo, a classe connection tem um método literal que irá converter o valor para a representação escapou correto para passar para o MySQL (que é o que os usos cursor.execute).

Eu imagino Postgres tem algo semelhante, mas eu não acho que há uma função para escapar valores como parte da API DB 2.0 spec.

Este vai ser dependente de banco de dados (IIRC, mysql permite \ como um caractere de escape, enquanto algo como Oracle espera aspas para ser duplicada: 'my '' quoted string').

Alguém me corrija se eu estiver errado, mas o método de colocar aspas é o método padrão.

Pode valer a pena olhar para o que as bibliotecas outro db abstração fazer (sqlalchemy, cx_Oracle, SQLite, etc).

Eu tenho que perguntar - por que você quer para inline os valores em vez de aprisioná-los

O trecho de código iria ficar apenas como este, de acordo com psycopg extensão docs

from psycopg2.extensions import adapt

value = "Unsafe string"
query = "SELECT * FROM some_table WHERE some_char_field = %s;" % \
    adapt(value).getquoted()
cursor.execute( query ) # value will be correctly quoted, too

A função getquoted retorna o value como citado e escapou corda, assim que você também pode ir:. "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted()

PyPika em outra boa opção para a construção de instruções SQL. Exemplo de uso (com base em um exemplo na página inicial do projeto):

>>> from pypika import Order, Query
>>> Query.from_('customers').select('id', 'fname', 'lname', 'phone').orderby('id', order=Order.desc)
SELECT "id","fname","lname","phone" FROM "customers" ORDER BY "id" DESC

Se você usar o Django você pode querer usar a função citando que é automaticamente adaptado às DBMS atualmente configurados:

from django.db import backend
my_quoted_variable = backend.DatabaseOperations().quote_name(myvar)
import re

def db_quote(s):
  return "\"" + re.escape(s) + "\""

pode fazer o trabalho de simples citando que as obras, pelo menos, com o MySQL. O que realmente precisamos, porém, é função cursor.format () que funcionaria como cursor.execute () exceto que ele voltaria a consulta resultante em vez de executá-lo. Há momentos em que você não quer que a consulta para ser executado bastante ainda -. Por exemplo você pode querer registrá-lo primeiro, ou imprimi-lo para depuração antes de ir em frente com ela

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top