1

ジャンゴ 1.5
PostgreSQL 9.2
psycopg2 2.4.6

私は QuerySet API の追加機能を使用して、Postgres のキューブ拡張から関数を使用できるようにしています。追加機能は移植性の理由からあまり良くないことはわかっていますが、とにかく別の DB を使用するつもりはありません (Postgres の後ではなく、 !)。問題は、このコードから間違った SQL クエリを取得していることです。

return self.select_related('item_place').extra(
            select={ 'distance': 'round(earth_distance(ll_to_earth(%s, %s), ll_to_earth(%s.latitude, %s.longitude))::numeric, 0)' },
            select_params=[latitude, longitude, ItemPlace._meta.db_table, ItemPlace._meta.db_table],
            where=['round(earth_distance(ll_to_earth(%s, %s), ll_to_earth(%s.latitude, %s.longitude))::numeric, 0) <= %s'],
            params=[latitude, longitude, ItemPlace._meta.db_table, ItemPlace._meta.db_table, radius])

psycopg2 はテーブル名を一重引用符で囲んでいるようですが、これは Postgres では正しくありません。スクリプトを実行すると、次のようになります。

round(earth_distance(ll_to_earth(%s, %s), ll_to_earth('item_place'.latitude, 'item_place'.longitude))::numeric, 0)

別のテーブルに緯度と経度があり、それがないと「あいまいな列」エラーが発生するため、テーブル名を使用する必要があります。今はわかりませんが、おそらく私は完全に間違っているので、このエラーが発生するのですか、それともpsycopg2のバグですか? 何か案は?

4

1 に答える 1

2

docによると、paramsselect_paramsは Psycopg2 がパラメーターを引用することを示すために使用されます。テーブル名を引用するためのものではありません (これは二重引用符によって行われます)。

Psycopg2のドキュメントを引用します。

このメソッドを介してバインドする必要があるのは変数値のみです。テーブルまたはフィールド名の設定には使用しないでください。これらの要素については、execute() を実行する前に通常の文字列フォーマットを使用する必要があります。

さらに、通常、テーブル名として二重引用符で囲む必要がある識別子は使用しません。この回答のコメントを参照してください。したがって、テーブル名をコードで直接使用しても安全です。

return self.select_related('item_place').extra(
        select={ 'distance': 'round(earth_distance(ll_to_earth(%s, %s), ll_to_earth({tbl}.latitude, {tbl}.longitude))::numeric, 0)'.format(tbl=ItemPlace._meta.db_table) },
        select_params=[latitude, longitude],
        where=['round(earth_distance(ll_to_earth(%s, %s), ll_to_earth({tbl}.latitude, {tbl}.longitude))::numeric, 0) <= %s'.format(tbl=ItemPlace._meta.db_table)],
        params=[latitude, longitude])
于 2013-03-28T15:42:12.190 に答える