Source code for squabble.rules.require_concurrent_index

import logging

import pglast

import squabble.rule
from squabble.message import Message
from squabble.rules import BaseRule

logger = logging.getLogger(__name__)

[docs]class RequireConcurrentIndex(BaseRule): """ Require all new indexes to be created with ``CONCURRENTLY`` so they won't block. By default, tables created in the same file as the index are exempted, since they are known to be empty. This can be changed with the option ``"include_new_tables": true``. Configuration: :: { "RequireConcurrentIndex": { "include_new_tables": false } } """
[docs] class IndexNotConcurrent(Message): """ Adding a new index to an existing table may hold a full table lock while the index is being built. On large tables, this may take a long time, so the preferred approach is to create the index concurrently instead. .. code-block:: sql -- Don't do this CREATE INDEX users_by_name ON users(name); -- Try this instead CREATE INDEX CONCURRENTLY users_by_name ON users(name); """ CODE = 1001 TEMPLATE = 'index "{name}" not created `CONCURRENTLY`'
def enable(self, ctx, config): include_new = config.get('include_new_tables', False) tables = set() # Keep track of CREATE TABLE statements if we're not including # them in our check. if not include_new: ctx.register('CreateStmt', self._create_table(tables)) ctx.register('IndexStmt', self._create_index(tables)) @squabble.rule.node_visitor def _create_table(self, ctx, node, tables): table = node.relation.relname.value.lower() logger.debug('found a new table: %s', table) tables.add(table) @squabble.rule.node_visitor def _create_index(self, ctx, node, tables): index_name = 'unnamed' if node.idxname != pglast.Missing: index_name = node.idxname.value concurrent = node.concurrent # Index was created concurrently, nothing to do here if concurrent != pglast.Missing and concurrent.value is True: return table = node.relation.relname.value.lower() # This is a new table, don't alert on it if table in tables: return self.IndexNotConcurrent(name=index_name), node=node.relation)