Como citar um valor de string explicitamente (Python DB API / psycopg2)

votos
24

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 por cursor.executemétodo em conteúdo de seu segundo parâmetro.

Por citação implícito eu 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 baixo nível READY_TO_USE_QUOTING_FUNCTIONesperado pela especificação API Python DB (eu não poderia encontrar tal funcionalidade em PEP 249 documentos). 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 ...

Publicado 21/11/2008 em 20:47
fonte usuário
Em outras línguas...                            


9 respostas

votos
26

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 a pasta de exemplos :)

E sim, isso é 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;

Na pasta exemplos de psycopg2 você encontrar o arquivo 'myfirstrecipe.py' não é um exemplo de como lançar 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, essa é 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' .

Respondeu 23/11/2008 em 12:47
fonte usuário

votos
13

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

Exemplo:

>>> cur.mogrify("INSERT IGNORE  INTO test (num, data) VALUES (%s, %s)", (42, 'bar'))
"INSERT IGNORE  INTO test (num, data) VALUES (42, E'bar')"
Respondeu 05/07/2014 em 21:46
fonte usuário

votos
2

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)

(Eu provavelmente tenho a sintaxe errada 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.

Respondeu 22/11/2008 em 01:01
fonte usuário

votos
1

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.

Respondeu 23/11/2008 em 16:17
fonte usuário

votos
0

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

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 getquotedfunção retorna a valuestring como um citado e escapou, assim que você também pode ir: "SELECT * FROM some_table WHERE some_char_field = " + adapt(value).getquoted().

Respondeu 12/12/2012 em 22:09
fonte usuário

votos
0

Isso vai ser banco de dados dependente (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 outras bibliotecas de abstração db fazer (sqlalchemy, cx_Oracle, SQLite, etc).

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

Respondeu 21/11/2008 em 21:25
fonte usuário

votos
0

Este vai ser DB dependente. No caso de MySQLdb, por exemplo, a connectionclasse tem um literalmétodo que irá converter o valor para a representação escapou correto para passar para o MySQL (que é o que cursor.executeusa).

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

Respondeu 21/11/2008 em 21:07
fonte usuário

votos
-1
import re

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

pode fazer o trabalho de simples citando que funciona, 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.

Respondeu 08/02/2013 em 00:32
fonte usuário

votos
-1

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)
Respondeu 23/11/2008 em 15:39
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more