Source code for squabble.rules.disallow_change_column_type
from pglast.enums import AlterTableType
from squabble.message import Message
from squabble.rules import BaseRule
[docs]class DisallowChangeColumnType(BaseRule):
"""
Prevent changing the type of an existing column.
Configuration: ::
{ "DisallowChangeColumnType": {} }
"""
[docs] class ChangeTypeNotAllowed(Message):
"""
Trying to change the type of an existing column may hold a
full table lock while all of the rows are modified.
Additionally, changing the type of a column may not be
backwards compatible with code that has already been deployed.
Instead, try adding a new column with the updated type, and
then migrate over.
For example, to migrate a column from ``type_a`` to ``type_b``.
.. code-block:: sql
ALTER TABLE foo ADD COLUMN bar_new type_b;
UPDATE foo SET bar_new = cast(bar_old, type_b);
-- Deploy server code to point to new column
ALTER TABLE foo DROP COLUMN bar_old;
"""
CODE = 1003
TEMPLATE = 'cannot change type of existing column "{col}"'
def enable(self, ctx, _config):
ctx.register('AlterTableCmd', lambda c, n: self._check(c, n))
def _check(self, ctx, node):
"""
Node is an `AlterTableCmd`:
{
'AlterTableCmd': {
'def': {
'ColumnDef': {
'colname': 'bar',
'constraints': [{'Constraint': {'contype': 2, 'location': 35}}]
}
}
}
}
"""
# We only care about changing the type of a column
if node.subtype != AlterTableType.AT_AlterColumnType:
return
ty = node['def'].typeName
issue = self.ChangeTypeNotAllowed(col=node.name.value)
ctx.report(issue, node=ty)