PythonベースのAPI取り扱いなど異なるparamstyles?
-
26-09-2019 - |
質問
私の実施Pythonオントロジーのクラスを使用するデータベースバックエンドがアクエリオントロジー.データベースのスキーマ固定(指定があらかじめがどうなるかはわからないタイプのデータベースエンジンを使っています。しかし、でももちろん、PythonインターフェースのデータベースエンジンのPython DB-API2.0(PEP249).率直してもらうにはユーザーのパスは、PEP249対応 Connection
オブジェクトのコンストラクタのオントロジーは、その利用の様々なハードコードSQL文をデータベースに問い合わせ:
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, ))
[...]
私の問題は異なるデータベースの除去をサポートされるパラメータのマーカーのクエリで定義され paramstyle
属性のバックエンドモジュールです。例えば、 paramstyle = 'qmark'
, インターフェイスのマークスタイル(SELECT * FROM term WHERE id = ?
); paramstyle = 'numeric'
手段の数字の位置(SELECT * FROM term WHERE id = :1
); paramstyle = 'format'
とはANSI Cフォーマット文字列タイプ(SELECT * FROM term WHERE id = %s
).したい場合は自分の講できるということは異なるデータベースの除去、このいろいろ準備した全てのパラメータのマーカーのメーカーです。このように全体の目的は共通のDBのAPIとして利用できないのと同じparameterisedクエリの異なるデータベースの除去.
があるので、場合に、どのような最高のアプローチを考えていますか。DBのAPIを指定していない存在の一般的脱出させるための機能でサニタイズ私の価値観は、クエリー、その脱出手という選択肢はないと思います。僕はキャリー依存のプロジェクトのいずれかを使用し、一段高いレベルの抽象化(SQLAlchemy、インスタンス).
解決
は厳密に言えば、問題はこれを許可するDBのAPIによって引き起こされるが、異なるSQL構文を使用して別のデータベースによるされていません。 DB APIモジュールは、パラメータとともに、データベースに正確なクエリ文字列を渡します。パラメータマーカーを「解決」をデータベース自体によってではなく、DB APIモジュールによって実行されます。
あなたはこれを解決したい場合は、あなたが持っているということが紹介するために、そのの抽象化のいくつかののより高いレベル。あなたは、余分な依存関係を追加したくない場合は、それを自分で行う必要があります。むしろ手動でエスケープと置き換えるよりも、あなたは動的にバックエンドモジュールのparamstyleに基づいて、所望のパラメータマーカー、とのクエリ文字列にパラメーター・マーカーを置き換えるために試みることができます。そして、DBへのパラメーター・マーカーを使用すると、文字列を渡します。たとえば、あなたは「%s」はどこでも使用することができ、かつ使用Pythonの文字列置換を置き換えるために「%s」を持つ「:1」、「:2」などのDBが使用する「数値」スタイルであれば、というように。.. ..
他のヒント
このPythonのレシピ することができます。について紹介し、余分な抽象の層を包むパラメータを独自の
Param
クラスです。の PyDal プロジェクトにも近いを実現しようとしてい:"PyDalの使用が可能と同paramstyle、datetime型を任意のモジュールに準拠しているDBAPI2.0にアクセスしてください。また、paramstyles、datetime種類を設定します。"
SQLAlchemyのは、この問題のために完璧なソリューションになるので、私が使用していずれかのプロジェクトに余分な依存関係を追加する必要はありません (例えばsqlalchemyの)抽象化のより高いレベル
それは、あまりにも悪いです。理論的には、DB-API 2.0は、このような柔軟性を提供するために構築されています。しかし、それは彼らのドライバーにすべての異なるparamstylesを実装する(オラクル、MySQLdbは、Postgresの、などのための)すべてのドライバの開発者が必要となります。彼らはそうではありません。あなたは、各データベースエンジンの「好ましい」paramstyleで立ち往生してます。
あなたはSQLAlchemyのか、他の高い抽象化層や近代的なMVCのクラスライブラリを使用することを拒否した場合、は、はい、あなたは、このための抽象化の独自の高いレベルを記述する必要があります。私はここにあなたの選択したソリューションであるにもかかわらず、それをお勧めしません。あなたはそこにいくつかの悪魔のような細部に直面している、と他の人がすでに解決しているというバグを考え出す時間を無駄にされます。
悪いことなどの外部ライブラリの依存関係を表示しないでください。それは、Pythonへのアプローチなら、あなたは言語の最も強力な機能のいくつかを逃ししようとしている。
あなたの毒を選びます。
ここで私をトリップの事はあなたのコードだけで、接続やカーソルオブジェクトを渡されている場合には必要とされるものparamstyle把握する方法でした。ここに私が思い付いたものです。
import importlib
def get_paramstyle(conn):
name = conn.__class__.__module__.split('.')[0]
mod = importlib.import_module(name)
return mod.paramstyle
あなたはおそらくCONNオブジェクトのより健全性のチェックを行う、あるいは少なくとも作るためにあなたがしている喜んでどのような仮定に依存し、try
ブロックでこれまでをラップする必要があります。