Sunday 4 October 2020

How can I switch between schemas at the point of a query

By way of an MRE I have a simple module called query that adds a record to the Bet table:

from container_test import Bet, DataAccessLayer

def main():
    dal = DataAccessLayer()
    dal.create_session()
    query_bets(dal)

def add_new_id(dal):
    new_id = {"id_": 3}
    dal.session.add(Bet(**new_id))
    dal.session.commit()

if __name__ == "__main__":
    main()

container_test contains the following:

from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Bet(Base):

    __tablename__ = "bet"
    __table_args__ = ({"schema": "belgarath", "extend_existing": True})

    id_ = Column(Integer, primary_key=True)

class DataAccessLayer():

    def __init__(self):
        conn_string = "mysql+mysqlconnector://root:root@localhost/"
        self.engine = create_engine(conn_string)

    def create_session(self):
        Base.metadata.create_all(self.engine)
        Session = sessionmaker()
        Session.configure(bind=self.engine)
        self.session = Session()

I want to be able to test the query_bets function and to do this I have created a simple pytest function in another file:

def test_add_new_id(
    create_dal, # creates an instance of a dal via conftest
    setup_teardown, # creates a blank belgarath_test schema and deletes afterwards via conftest
):
    expected = 3
    sandpit.add_new_id(create_dal)
    actual = query_bet(create_dal) # function that will return a scalar result
    assert actual == expected

However, I want to be able to change the standard belgarath schema to a test schema; belgarath_test so I don't risk the integrity of the main database. I think I need some kind of 'switch' I can activate in the test_add_new_id test function but I'm not sure how to create one.

I've been trying to follow the solution set out in this post: How do I change the schema for both a table and a foreign key? however I'm struggling. I don't understand what it is that I need to do in the test_add_new_id test function to change the schema.

For reference I have created the following modules as per the solution:

container_test:


from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.orm import sessionmaker

from base_class import SCHEMA_TEST, Base, declared_attr


class Bet(Base):

    @declared_attr
    def __table_args__(cls):
        return {'schema': SCHEMA_TEST}

    __tablename__ = "bet"

    id_ = Column(Integer, primary_key=True)


class DataAccessLayer():

    def __init__(self):
        conn_string = "mysql+mysqlconnector://root:root@localhost/"
        self.engine = create_engine(conn_string)

    def create_session(self):
        Base.metadata.create_all(self.engine)
        Session = sessionmaker()
        Session.configure(bind=self.engine)
        self.session = Session()

base_class(I got an error trying to use __init__.py):

from sqlalchemy.ext.declarative import declarative_base, declared_attr

SCHEMA_MAIN = 'belgarath'  # figure out how you want to retrieve this
SCHEMA_TEST = 'belgarath_test'


class _Base():

    @declared_attr
    def __table_args__(cls):
        return {'schema': SCHEMA_MAIN}


Base = declarative_base(cls=_Base)
Base.metadata.schema = SCHEMA_MAIN

This successfully changes belgarath to belgarath_test but I only want that to happen when I'm running the test_add_new_id test function.



from How can I switch between schemas at the point of a query

No comments:

Post a Comment