Estoy implementando una clase de ontología Python que utiliza un back-end de base de datos para almacenar y consultar la ontología. El esquema de la base de datos es fijo (especificado de antemano), pero no sé qué tipo de motor de base de datos se está utilizando. Sin embargo, puedo confiar en el hecho de que la interfaz de Python del motor de base de datos usa Python DB-API 2.0 (PEP 249). Una idea sencilla es dejar que el usuario pase de Connection
objeto PEP 249 compatible con el constructor de mi ontología, que a su vez usar varias consultas SQL codificado para consultar la base de datos:Python DB-API: cómo manejar diferentes paramstyles?
class Ontology(object):
def __init__(self, connection):
self.connection = connection
def get_term(self, term_id):
cursor = self.connection.cursor()
query = "SELECT * FROM term WHERE id = %s"
cursor.execute(query, (term_id,))
[...]
Mi problema es que los diferentes backends de bases de datos están permitidos para soportar marcadores de parámetros diferentes en las consultas, definidas por el atributo paramstyle
del módulo back-end. Por ejemplo, si es paramstyle = 'qmark'
, la interfaz admite el estilo de signo de interrogación (SELECT * FROM term WHERE id = ?
); paramstyle = 'numeric'
significa el estilo posicional numérico (SELECT * FROM term WHERE id = :1
); paramstyle = 'format'
significa el estilo de cadena de formato ANSI C (SELECT * FROM term WHERE id = %s
). Si quiero que mi clase sea capaz de manejar diferentes backends de bases de datos, parece que tengo que prepararme para todos los estilos de marcadores de parámetros. Esto parece frustrar todo el propósito de una API DB común para mí, ya que no puedo usar la misma consulta parametrizada con diferentes backends de bases de datos.
¿Hay alguna forma de evitarlo y, de ser así, cuál es el mejor enfoque? La DB API no especifica la existencia de una función de escape genérica con la que puedo desinfectar mis valores en la consulta, por lo que hacer el escape manualmente no es una opción. No quiero agregar una dependencia adicional al proyecto, ya sea mediante el uso de un nivel aún más alto de abstracción (SQLAlchemy, por ejemplo).
Hmm, no estoy 100% seguro de que el módulo DB API pase la cadena de consulta exacta a la base de datos; por ejemplo, 'BaseCursor.execute' en el módulo' MySQLdb' utiliza 'query = query% db.literal (args)' para formatear la cadena de consulta explícitamente antes de enviarla al motor de DB. Sin embargo, esto podría no ser cierto para otros motores de DB. De todos modos, también me inclino por reemplazar '% s' con otros estilos de marcador explícitamente, sobre la marcha, pero me preguntaba si existe una solución más simple. Si a nadie se le ocurre algo más, aceptaré felizmente tu respuesta. –
"* El módulo DB API pasa la cadena de consulta exacta a la base de datos, junto con los parámetros. *" No creo que ese sea el caso en absoluto. Si nos fijamos en [la especificación de red de PostgreSQL, por ejemplo] (http://www.postgresql.org/docs/8.4/static/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY), cuando se usa, las consultas de param utilizan ' $ 1', '$ 2', ... como marcadores de posición, que no son ninguno de los [paramstyles de Python] (http://www.python.org/dev/peps/pep-0249/#paramstyle). Claramente, las cadenas de consulta se modifican antes de enviarse, de una forma u otra, más aún cuando se usa un estilo param que se basa en un dict (con nombres). – Bruno