Why doesn't schema_translate_map change schema?

Viewed 565

I'm trying to use schema_translate_map to change a schema:

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)

However, the SQL comes out as:

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

Instead of:

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

Where am I going wrong?

2 Answers

Try what happens if you simply append .all() to your 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())

Output (without trace):

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)

I'm not an expert, but I guess this might be related to the following issue:

the schema translate feature takes place within the compiler and this is plainly wrong. the schema assignment should be taking place after the SQL is generated so that we only need one cache key. This is along the lines of #5002 however I think even the existing cache key mechanism used with baked etc. needs to pull the schema translate out of the compiler entirely for 1.4 and add it to the translations which occur from the ExecutionContext, along with the expanding parameter sets of logic. schema translate is intended to service many hundreds / thousands of schemas so having this occur pre-cache has to change.

I guess that Query API is not aware of execution_options in connection. Try not to mix this two approaches.

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

Result:

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)
Related