Названия квалификационных таблиц с именами баз данных в sqlalchemy - PullRequest
2 голосов
/ 23 февраля 2012

Я использую sqlalchemy с эликсиром для нескольких баз данных. В настоящее время все хорошо работает с несколькими сессиями - одна привязка к другой базе данных. Однако в некоторых случаях я хочу использовать один сеанс для запроса к другой базе данных (это означает поддержку нескольких серверов с разными реплицированными базами данных).

Проблема заключается в том, что при выполнении запроса к одному сеансу имена таблиц не указываются с правильным именем базы данных, и я не знаю, как определить, к какому имени базы данных добавить префикс. Есть ли способ сделать это?

Ответы [ 2 ]

2 голосов
/ 23 февраля 2012

Хит похожую проблему с Oracle в качестве базы данных. Имя схемы в экземплярах БД было разным, поэтому, надеюсь, это аналогично вашей ситуации.

Метод решения этой проблемы состоял в том, чтобы сначала запустить простой запрос к БД, чтобы определить владельца объектов схемы:

SELECT owner FROM ALL_OBJECTS WHERE object_name = :obj_name AND object_type = :obj_type

Затем используйте полученный скаляр в качестве значения параметра схемы в ваших отраженных таблицах:

mytable = Table(name='my_table_name',
                metadata=my_bound_metadata,
                autoload=True,
                schema=schema_owner)
1 голос
/ 23 февраля 2012

Это может быть сложно, так как у вас уже есть все сопоставленное с точки зрения различных связей. Аргумент «schema» для Table - это способ отображения синтаксиса «schemaname.tablename», однако это будет означать, что вы будете использовать сопоставленные классы, отличные от обычных классов, сопоставленных с таблицей без имени схемы. 1001 *

Итак, сначала несколько платформо-зависимых методов, которые облегчили бы это. Если вы работаете в Oracle, используйте Oracle CREATE SYNONYM, чтобы сопоставить «somedb.sometable» с «sometable» в удаленной схеме. Если вы работаете в Postgresql, манипулируйте search_path так, чтобы поиск по нескольким схемам осуществлялся по заданному имени (см. http://www.postgresql.org/docs/8.1/static/ddl-schemas.html#DDL-SCHEMAS-PATH).

Ни одна из этих работ? Хорошо, тогда вам нужно сделать что-то в соответствии с рецептом здесь http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName (извините, это не использует Elixir, я не уверен, какие возможности Elixir в этом отношении). Есть разные способы добиться этого в зависимости от специфики. Вот один из способов создания нового анонимного класса, сопоставленного с исходной таблицей:

# regular class
class ClassOne(Base):
    __tablename__ = 'one'
    id = Column(Integer, primary_key=True)

class ClassTwo(Base):
    __tablename__ = 'two'
    id = Column(Integer, primary_key=True)

def map_to_alt_tb(cls, metadata, schemaname):
    m = class_mapper(cls)
    cls2 = type(
        "AltClass",
        (object, ),
        {}
    )
    table = m.local_table.tometadata(metadata, schemaname)
    mapper(cls2, table)
    return cls2

alt_cls = map_to_alt_db(ClassTwo, somemetadata, "alt_schema")

map_to_alt_db() извлечет таблицу, с которой сопоставлен ClassTwo, изменит ее схему на «alt_schema», затем сопоставит ее с новым классом.

Однако этот подход теряет все, что является особенным в ClassTwo. Если вам нужно, вы можете использовать более конкретный подход, который есть на этой вики-странице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...