#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. Спасибо за это. Я действительно ищу решение, в котором я могу изменить конфигурацию для любого последующего запроса, а не изменять каждый запрос