Почему schema_translate_map не изменяет схему?

#python #mysql #orm #sqlalchemy

#python #mysql #orm #sqlalchemy

Вопрос:

Я пытаюсь использовать 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
  

Где я ошибаюсь?

Ответ №1:

Попробуйте, что произойдет, если вы просто добавите .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)
  

Я не эксперт, но я предполагаю, что это может быть связано со следующей проблемой:

функция перевода схемы выполняется внутри компилятора, и это явно неправильно. назначение схемы должно выполняться после генерации SQL, поэтому нам нужен только один ключ кэша. Это похоже на # 5002, однако я думаю, что даже существующий механизм ключей кэша, используемый с baked и т. Д., Должен Полностью извлекать перевод схемы из компилятора для версии 1.4 и добавлять его к переводам, которые происходят из ExecutionContext, вместе с расширяющимися наборами параметров логики. schema translate предназначен для обслуживания многих сотен / тысяч схем, поэтому при возникновении этого предварительного кэша необходимо изменить.

Комментарии:

1. Да — добавление .all() генерирует правильный запрос 🙂 Не совсем уверен, что означает проблема. Когда он говорит schema assignment should be taking place after the SQL is generated — это для меня говорит о том, что то, что вы определили, на самом деле предназначено?

2. Похоже, что так, но я тоже не совсем уверен. Проблема также связана с версией 1.4, но она все еще находится в бета-версии. Может быть, кто-то еще прояснит, что происходит за кулисами. В любом случае, рад, что я смог помочь!

Ответ №2:

Я предполагаю, что 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)
  

Комментарии:

1. Спасибо за это. Я действительно ищу решение, в котором я могу изменить конфигурацию для любого последующего запроса, а не изменять каждый запрос