【问题标题】:Why doesn't schema_translate_map change schema?为什么 schema_translate_map 不更改架构?
【发布时间】:2021-01-29 08:42:36
【问题描述】:

我正在尝试使用 schema_translate_map 更改架构:

Base = declarative_base()


class DataAccessLayer():

    def __init__(self):
        conn_string = "mysql+mysqlconnector://root:root@localhost/"
        self.engine = create_engine(conn_string)
        Session = sessionmaker()
        Session.configure(bind=self.engine)
        self.session = Session()

    def change_schema(self):
        self.session.connection(execution_options={"schema_translate_map": {"belgarath": "belgarath_test"}})


class Player(Base):
    __tablename__ = "player"
    __table_args__ = {'schema': "belgarath"}

    id_ = Column(Integer, primary_key=True)


dal = DataAccessLayer()
dal.change_schema()
qry = dal.session.query(Player.id_)
print(qry)

但是,SQL 输出如下:

SELECT belgarath.player.id_ AS belgarath_player_id_ 
FROM belgarath.player

代替:

SELECT belgarath_test.player.id_ AS belgarath_test_player_id_ 
FROM belgarath_test.player

我哪里出错了?

【问题讨论】:

    标签: python mysql orm sqlalchemy


    【解决方案1】:

    我猜查询 API 不知道 execution_options 的连接。尽量不要混合使用这两种方法。

    dal = DataAccessLayer()
    dal.change_schema()
    qry = dal.session.connection().execute(Player.__table__.select())
    print(qry)
    

    结果:

    sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: belgarath_test.player
    [SQL: SELECT belgarath_test.player.id_ 
    FROM belgarath_test.player]
    (Background on this error at: http://sqlalche.me/e/13/e3q8)
    

    【讨论】:

    • 谢谢。我真的在寻找一种解决方案,我可以更改任何后续查询的配置,而不是修改每个查询
    【解决方案2】:

    试试如果你只是将.all() 附加到你的qry 会发生什么:

    from sqlalchemy import Integer
    from sqlalchemy import Column
    from sqlalchemy import create_engine
    from sqlalchemy.orm import sessionmaker
    from sqlalchemy.ext.declarative import declarative_base
    
    Base = declarative_base()
    
    class DataAccessLayer():
    
        def __init__(self):
            conn_string = "sqlite:///:memory:"
            #conn_string = "mysql+mysqlconnector://root:root@localhost/"
            self.engine = create_engine(conn_string)
            Session = sessionmaker()
            Session.configure(bind=self.engine)
            self.session = Session()
    
        def change_schema(self):
            self.session.connection(execution_options={"schema_translate_map": {"belgarath": "belgarath_test"}})
    
    
    class Player(Base):
        __tablename__ = "player"
        __table_args__ = {'schema': "belgarath"}
    
        id_ = Column(Integer, primary_key=True)
    
    
    dal = DataAccessLayer()
    dal.change_schema()
    qry = dal.session.query(Player.id_)
    print(qry.all())
    

    输出(无痕迹):

    OperationalError: (sqlite3.OperationalError) no such table: belgarath_test.player
    [SQL: SELECT belgarath_test.player.id_ AS belgarath_player_id_ 
    FROM belgarath_test.player]
    (Background on this error at: http://sqlalche.me/e/13/e3q8)
    

    我不是专家,但我猜这可能与以下issue有关:

    模式转换功能发生在编译器中,这显然是错误的。模式分配应该在 SQL 生成之后进行,这样我们只需要一个缓存键。这与#5002 的思路一致,但是我认为即使是与烘焙等一起使用的现有缓存密钥机制也需要将架构转换完全从编译器中拉出 1.4,并将其添加到从 ExecutionContext 发生的转换中,以及扩展逻辑参数集。模式翻译旨在为数百/数千个模式提供服务,因此发生这种情况时,预缓存必须更改。

    【讨论】:

    • 是的 - 添加 .all() 会生成正确的查询 :) 不过不太清楚问题的含义。当它说schema assignment should be taking place after the SQL is generated - 对我来说,你所确定的实际上是有意的?
    • 看起来是这样 - 但我也不太确定。该问题与 1.4 版进一步相关,但仍处于测试阶段。也许其他人会澄清幕后发生的事情。无论如何,很高兴我能帮上忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    相关资源
    最近更新 更多