Декларативная SQLAlchemy: определение триггеров и индексов (Postgres 9) - PullRequest
22 голосов
/ 19 января 2012

Есть ли способ в классе SQLAlchemy таблицы определять / создавать триггеры и индексы для этой таблицы?

Например, если бы у меня была базовая таблица типа ...

class Customer(DeclarativeBase):
    __tablename__ = 'customers'
    customer_id = Column(Integer, primary_key=True,autoincrement=True)
    customer_code = Column(Unicode(15),unique=True)
    customer_name = Column(Unicode(100))
    search_vector = Column(tsvector) ## *Not sure how do this yet either in sqlalchemy*.

Теперь я хочу создать триггер для обновления "search_vector"

CREATE TRIGGER customers_search_vector_update BEFORE INSERT OR UPDATE
ON customers
FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(search_vector,'pg_catalog.english',customer_code,customer_name);

Тогда я хотел бы добавить это поле также в качестве индекса ...

create index customers_search_vector_indx ON customers USING gin(search_vector);

Прямо сейчас, после того, как я выполню любой вид регенерации базы данных из моего приложения, мне нужно сделать столбец добавления для столбца tsvector, определение триггера, а затем инструкцию index из psql. Не конец света, но легко забыть шаг. Я все об автоматизации, так что если я смогу все это сделать во время установки приложений, тогда бонус!

1 Ответ

37 голосов
/ 19 января 2012

Индексы просты в создании.Для одного столбца с параметром index=True, как показано ниже:

customer_code = Column(Unicode(15),unique=True,index=True)

Но если вам нужен больший контроль над именем и параметрами, используйте явную конструкцию Index () :

Index('customers_search_vector_indx', Customer.__table__.c.search_vector, postgresql_using='gin')

Триггеры также могут быть созданы, но они должны быть все еще основаны на SQL и подключены к событиям DDL.См. Настройка DDL для получения дополнительной информации, но код может выглядеть примерно так:

from sqlalchemy import event, DDL
trig_ddl = DDL("""
    CREATE TRIGGER customers_search_vector_update BEFORE INSERT OR UPDATE
    ON customers
    FOR EACH ROW EXECUTE PROCEDURE
    tsvector_update_trigger(search_vector,'pg_catalog.english',customer_code,customer_name);
""")
tbl = Customer.__table__
event.listen(tbl, 'after_create', trig_ddl.execute_if(dialect='postgresql'))

Sidenote: я не знаю, как настроить tsvector тип данных: заслуживаетотдельный вопрос.

...