SQLAlchemy declarative: определение триггеров и индексов (Postgres 9)
Есть ли способ в классе 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, определение триггера, а затем оператор индекса из psql. Не конец света, но его легко забыть шаг. Я все о автоматизации, поэтому, если я смогу получить все это во время установки приложений, то бонус!
Ответы
Ответ 1
Индикаторы прямолинейны для создания. Для одного столбца с параметром 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
тип данных: заслуживает отдельного вопроса.