如何将 SQLAlchemy @compiles 装饰器用于 geoalchemy2 类型

问题描述

我正在尝试使用最初为 Postgres 数据库设计的 sqlAlchemy ORM 创建内存中的 sqlite 数据库。为了让 sqlite 引擎能够转换 postgres 特定的数据类型,我依赖于 sqlAlchemy @compiles 装饰器,该装饰器适用于 sqlalchemy.dialects.postgresql 命名空间中的类型。

如何将 geoalchemy2.Raster 数据类型转换为与引擎无关的数据类型(对于我而言,它可能是 sqlalchemy.BLOB 类型。重要的是我可以创建类似的表,它们不需要精确)?

此示例代码按预期转换 DOUBLE_PRECISION 类型,但我不知道如何修改 geoalchemy2.Raster 数据类型,即 UserDefinedType。我希望能够编写与 compile_DOUBLE_PRECISION() 类似的方法,将 Raster 更改为 BLOB 类型。

import sqlalchemy
from sqlalchemy import Column,Integer
from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.dialects.sqlite.base import sqliteTypeCompiler
from geoalchemy2 import Raster

Base = declarative_base()

class SomeModel(Base):
    __tablename__ = "some_model"
    id = Column(Integer,primary_key=True)
    double_precision = Column(DOUBLE_PRECISION)
    raster = Column(Raster)

# The following @compiles works as intended
@compiles(DOUBLE_PRECISION,'sqlite')
def compile_DOUBLE_PRECISION(element,compiler: sqliteTypeCompiler,**kw):
    """ Handles postgres DOUBLE_PRECISION datatype as REAL in sqlite. """
    return compiler.visit_real(element,**kw)

def test_throws_error_due_to_raster_data_type():
    engine = sqlalchemy.create_engine("sqlite:///:memory:")
    Base.Metadata.create_all(engine)

解决方法

我不熟悉 postgresql 但也许这样的东西可以工作

import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from geoalchemy2 import Raster

Base = declarative_base()


def raster_if_postgresql_else_blob():
    return sa.BLOB().with_variant(Raster,"postgresql")


class SomeModel(Base):
    __tablename__ = "some_model"
    id = sa.Column(sa.Integer,primary_key=True)
    raster = sa.Column(raster_if_postgresql_else_blob())


lite_engine = sa.create_engine("sqlite:///:memory:",echo=True)
Base.metadata.create_all(lite_engine)