Skip to content

Commit 07c7ffa

Browse files
committed
add migration
1 parent 059323c commit 07c7ffa

1 file changed

Lines changed: 64 additions & 0 deletions

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""
2+
Widen existing integer custom-object columns from 32-bit to 64-bit (bigint).
3+
4+
Integer fields previously mapped to Django's IntegerField, i.e. a 32-bit signed
5+
PostgreSQL ``integer`` column (max 2_147_483_647). They now map to BigIntegerField
6+
(``bigint``). New columns are created as bigint automatically by the schema editor,
7+
but columns on already-created custom_objects_* tables must be widened in place.
8+
9+
``integer -> bigint`` is a lossless widening (every int32 value fits in int64), so
10+
no USING clause or data transformation is needed. The conversion rewrites the table
11+
under an ACCESS EXCLUSIVE lock; this is fine for typical custom-object table sizes.
12+
13+
The reverse is intentionally a no-op: narrowing bigint back to integer could fail or
14+
lose data for any value outside the 32-bit range.
15+
16+
See issue #532.
17+
"""
18+
19+
from django.db import migrations
20+
21+
22+
def widen_integer_columns(apps, schema_editor):
23+
"""ALTER every integer-typed custom-object column to bigint, in place."""
24+
CustomObjectTypeField = apps.get_model("netbox_custom_objects", "CustomObjectTypeField")
25+
26+
# Drive off field metadata (not blind introspection of every custom_objects_*
27+
# column) so we only touch user integer fields, never base-model columns
28+
# inherited from NetBox mixins. After migration 0014 all field names are
29+
# lowercase and the scalar column name equals the field name exactly.
30+
integer_fields = CustomObjectTypeField.objects.filter(type="integer")
31+
32+
with schema_editor.connection.cursor() as cursor:
33+
for field in integer_fields:
34+
table_name = f"custom_objects_{field.custom_object_type_id}"
35+
column_name = field.name
36+
37+
# Idempotent + safe: only act on a column that exists and is still a
38+
# 32-bit integer. A no-op on fresh installs (already bigint) and on
39+
# partial re-runs.
40+
cursor.execute(
41+
"""
42+
SELECT 1 FROM information_schema.columns
43+
WHERE table_schema = current_schema()
44+
AND table_name = %s
45+
AND column_name = %s
46+
AND data_type = 'integer'
47+
""",
48+
[table_name, column_name],
49+
)
50+
if cursor.fetchone():
51+
cursor.execute(
52+
f'ALTER TABLE "{table_name}" ALTER COLUMN "{column_name}" TYPE bigint'
53+
)
54+
55+
56+
class Migration(migrations.Migration):
57+
58+
dependencies = [
59+
("netbox_custom_objects", "0014_fix_mixed_case_field_names"),
60+
]
61+
62+
operations = [
63+
migrations.RunPython(widen_integer_columns, migrations.RunPython.noop),
64+
]

0 commit comments

Comments
 (0)