sqlalchemy на postgresql сбрасывает search_path в сеансе после вызова get_bind () - это ожидается? - PullRequest
0 голосов
/ 04 октября 2018

Рассмотрим следующий пример:

import unittest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine('postgresql://user:password@host:5432/dbname')
session_maker = sessionmaker(bind=engine)

def print_search_path(label, session):
print("{} -- search path: {}".format(label, session.execute('show search_path').fetchall()[0][0]))

class TestSearchPath(unittest.TestCase):

    def create_schema(self):
        sql = """\
        create schema if not exists test_schema;

        drop table if exists test_schema.foo;

        create table test_schema.foo(
            foo_id serial primary key 
          , name varchar unique
        );

        insert into test_schema.foo(name) values ('foo1');
        insert into test_schema.foo(name) values ('foo2');
        """
        print(sql)
        engine.execute(sql)

    def drop_schema(self):
        sql = "drop schema test_schema cascade;"
        print(sql)
        engine.execute(sql)

    def setUp(self):
        self.create_schema()

    def tearDown(self):
        self.drop_schema()

    def test_search_path(self):

        session = session_maker()
        try:
            print_search_path('beginning', session)
            session.execute('set search_path to test_schema')
            print_search_path('after initialize path', session)

            # execute a read
            session.get_bind().execute("select * from test_schema.foo where name='foo2'")
            print_search_path('before commit', session)
            session.commit()
            print_search_path('after commit', session)
        except:
            session.rollback()
            raise
        finally:
            session.close()

Я получаю следующий вывод:

beginning -- search path: "$user", public
after initialize path -- search path: test_schema
before commit -- search path: test_schema
after commit -- search path: "$user", public

Так что это меня удивляет, поэтому, возможно, у меня неправильное представление.Наивно, я бы ожидал, что схема останется test_schema для всей программы;однако после фиксации кажется, что путь поиска сбрасывается на public.

Мой вопрос

  1. Это ожидаемое поведение?
  2. Если это не так, есть ли способ обеспечить, чтобы сессия всегда имела одинаковый путь_поиска в течение всего времени жизни?

Спасибо, Райан

1 Ответ

0 голосов
/ 04 октября 2018

Согласно документации кажется, что инициализация sessionmaker () автоматически сбрасывает сессии, поэтому, если вы захотите снова сослаться на вашу сессию позже в программе, вы можете попробовать добавить autoflush = False к аргументу sessionmaker ()в строке 6. То есть попробуйте заменить строку 6 на:

session_maker = sessionmaker(bind=engine,autoflush=False)

Надеюсь, это поможет!

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

РЕДАКТИРОВАТЬ: Этот подход не работает.Как было отмечено в комментариях, автозаполнение относится к чему-то еще.На той же странице документации также показано, что expire_on_commit = True устанавливается автоматически, если не указано иное, поэтому мой новый ответ заключается в замене исходного фрагмента кода, который я предложил, на:

session_maker = sessionmaker(bind=engine,expire_on_commit=False)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...