@cached_propertydefengine(self):engine=create_async_engine(self.url)ifengine.dialect.name!="postgresql":raiseRuntimeError("This optional is only available for PostgreSQL databases.")returnengine@cached_propertydefurl(self):returnmake_url(self._url)
[docs]@overrideasyncdefinstall(self):"""Install this optional feature in the database. This will install the pg_trgm extension and create optimized index for search."""is_pg_trm_available=awaitself._is_pg_trgm_extension_installed()ifnotis_pg_trm_available:try:awaitself._install_pg_trgm_extension_if_possible()is_pg_trm_available=awaitself._is_pg_trgm_extension_installed()exceptDatabaseErrorase:logger.error(f"Failed to install pg_trgm extension: {e}")ifnotis_pg_trm_available:logger.error("pg_trgm extension is not available, cannot create optimized indexes, will still create regular one.")else:awaitself._create_gin_index("messages","summary")awaitself._create_gin_index("transactions","endpoint")
[docs]@overrideasyncdefuninstall(self):"""Remove this optional feature from database. Please note that the extension is not uninstalled, as it may have more side effect than we'd like too. Some deeper understanding of what is a PG extension and how scoped there are would be great."""awaitself._drop_index("messages","summary")awaitself._drop_index("transactions","endpoint")ifawaitself._is_pg_trgm_extension_installed():logger.warning("pg_trgm extension is installed and wont be removed, if you need to, you can remove it by hand.")
asyncdef_is_pg_trgm_extension_installed(self)->bool:"""Check if pg_trgm extension is already installed in the database."""result=awaitself._run_sql("SELECT 1 FROM pg_extension WHERE extname='pg_trgm'")returnresult.rowcount>0asyncdef_run_sql(self,sql):"""Run a SQL statement on the database (via sqlalchemy DBAL engine)."""returnawaitrun_sql(self.engine,sql)asyncdef_install_pg_trgm_extension_if_possible(self):"""Make sure the pg_trgm extension is installed in the database. This may fail, we'll alert the user about that, although there may be good reasons for this to fail (no privilege ...)."""try:awaitself._run_sql("CREATE EXTENSION IF NOT EXISTS pg_trgm;")exceptDatabaseErrorase:logger.error(f"Failed to install pg_trgm extension: {e}")asyncdef_create_gin_index(self,table_name,column_name):"""Create a GIN index on a column, using the pg_trgm extension."""awaitself._run_sql(f"CREATE INDEX {table_name}_{column_name}_gin ON {table_name} USING gin ({column_name} gin_trgm_ops);")asyncdef_drop_index(self,table_name,column_name):"""Drop an index on a column."""awaitself._run_sql(f"DROP INDEX IF EXISTS {table_name}_{column_name}_gin;")