私はSQLAlchemy ORMマッパーを使ってアプリケーションにカスタムタイプを持っています。複雑なクエリの場合は、SQL式モジュールを使用する必要がありますが、これによりカスタムタイプの処理が不透明になります。 がORMを使用しないでない場合、マッピングに私のカスタムタイプを使用するようにSQLAlchemyに指示するにはどうすればいいですか?SQL式ステートメントでカスタム型を適用するにはどうすればよいですか?
以下は、この問題を示す簡単な例です。
最初のクエリが機能することに注意してください。ただし、カスタムタイプが定義されていても、最初にstr
をPythonに、INET
をPostgreSQLに手動でキャストしなければなりません。
私は、SQL式モジュールがORMの1つ上に定義されているため、カスタムタイプを認識していないことを理解します。しかし、どうやってそのカスタムタイプをSQLレイヤーに配線して、タイプと値の使用をより透明にする方法がないのだろうかと思います。また、どのタイプのSAが使用されていても、カスタムタイプで定義されている操作(クリーンアップなど)が一貫して適用されることを保証します。
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql.expression import any_
from sqlalchemy.types import TypeDecorator
Base = declarative_base()
class PgIpInterface(TypeDecorator):
"""
A codec for :py:mod:`ipaddress` interfaces.
"""
impl = INET
def process_bind_param(self, value, dialect):
return str(value) if value else None
def process_result_value(self, value, dialect):
return ip_interface(value) if value else None
def process_literal_param(self, value, dialect):
raise NotImplementedError('Not yet implemented')
class Network(Base):
__tablename__ = 'example_table'
cidr = Column(PgIpInterface, primary_key=True)
def execute(query):
import logging
LOG = logging.getLogger()
try:
print(query)
print(query.all())
except:
LOG.exception('!!! failed')
engine = create_engine('postgresql://[email protected]/malbert')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
ranges = [
ip_interface('192.168.1.0/24'),
ip_interface('192.168.3.0/24'),
]
# Query with manual casting
print(' Manual Casting via "str" '.center(80, '-'))
arr = array([cast(str(_), INET) for _ in ranges])
query1 = session.query(Network).filter(Network.cidr.op("<<=")(any_(arr)))
execute(query1)
print(' Manual Casting '.center(80, '-'))
arr = array([cast(_, INET) for _ in ranges])
query2 = session.query(Network).filter(Network.cidr.op("<<=")(any_(arr)))
execute(query2)
# Query without casting
print(' No Casting '.center(80, '-'))
query3 = session.query(Network).filter(Network.cidr.op("<<=")(any_(ranges)))
execute(query3)
ありがとうございます。これは機能します。しかし、私は 'psycopg'レイヤーに実装しないと思います。追加されたSLOCの量は問題にはならない。しかし、あなたの最初のヒントは、カスタムタイプにキャスティングは魅力のように動作します。私は両方のソリューションをテストしましたが、どちらも機能します。投稿を編集してPython 3と互換性を持たせ、他の人がこれを見ている場合は、必要な 'psycopg2'インポートを追加します。本当にありがとう! – exhuma