Skip to content

Commit 9b191b9

Browse files
committed
Change organization PK to auto-increment integer
Replace the UUID primary key on the organizations table with an auto-incrementing integer. The id field is now treated as an internal implementation detail: it remains in the domain model and ORM layer but is removed from all public-facing API response models (client and handler models). Includes an Alembic migration to drop and recreate the column.
1 parent f0b5be8 commit 9b191b9

File tree

6 files changed

+48
-11
lines changed

6 files changed

+48
-11
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
"""Change organization id from UUID to auto-incrementing integer.
2+
3+
Revision ID: a1b2c3d4e5f6
4+
Revises: cf3b3f99916b
5+
Create Date: 2026-03-11 00:00:00.000000+00:00
6+
"""
7+
8+
import sqlalchemy as sa
9+
10+
from alembic import op
11+
12+
# revision identifiers, used by Alembic.
13+
revision: str = "a1b2c3d4e5f6"
14+
down_revision: str | None = "cf3b3f99916b"
15+
branch_labels: str | None = None
16+
depends_on: str | None = None
17+
18+
19+
def upgrade() -> None:
20+
# Early development — no production data to migrate.
21+
# Drop the UUID column and recreate as auto-incrementing integer.
22+
op.drop_constraint("organizations_pkey", "organizations", type_="primary")
23+
op.drop_column("organizations", "id")
24+
op.add_column(
25+
"organizations",
26+
sa.Column(
27+
"id",
28+
sa.Integer(),
29+
sa.Identity(always=False),
30+
nullable=False,
31+
),
32+
)
33+
op.create_primary_key("organizations_pkey", "organizations", ["id"])
34+
35+
36+
def downgrade() -> None:
37+
op.drop_constraint("organizations_pkey", "organizations", type_="primary")
38+
op.drop_column("organizations", "id")
39+
op.add_column(
40+
"organizations",
41+
sa.Column("id", sa.Uuid(), nullable=False),
42+
)
43+
op.create_primary_key("organizations_pkey", "organizations", ["id"])

client/src/docverse/client/models/organizations.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from datetime import datetime, timedelta
66
from enum import StrEnum
77
from typing import Annotated, Any
8-
from uuid import UUID
98

109
from pydantic import BaseModel, ConfigDict, Field, field_validator
1110

@@ -91,8 +90,6 @@ class Organization(BaseModel):
9190

9291
self_url: str = Field(description="URL to this organization resource.")
9392

94-
id: UUID = Field(description="Unique identifier for the organization.")
95-
9693
slug: str = Field(description="URL-safe identifier for the organization.")
9794

9895
title: str = Field(description="Display title for the organization.")

src/docverse/dbschema/organization.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@
22

33
from __future__ import annotations
44

5-
import uuid
65
from datetime import datetime
76
from typing import Any
87

9-
from sqlalchemy import DateTime, Enum, Index, Integer, String, Text, Uuid
8+
from sqlalchemy import DateTime, Enum, Index, Integer, String, Text
109
from sqlalchemy.dialects.postgresql import JSONB
1110
from sqlalchemy.orm import Mapped, mapped_column
1211
from sqlalchemy.sql import func
@@ -21,8 +20,8 @@ class SqlOrganization(Base):
2120

2221
__tablename__ = "organizations"
2322

24-
id: Mapped[uuid.UUID] = mapped_column(
25-
Uuid, primary_key=True, default=uuid.uuid4
23+
id: Mapped[int] = mapped_column(
24+
Integer, primary_key=True, autoincrement=True
2625
)
2726

2827
slug: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)

src/docverse/domain/organization.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from datetime import datetime, timedelta
66
from typing import Any
7-
from uuid import UUID
87

98
from pydantic import BaseModel, ConfigDict, Field
109

@@ -16,7 +15,7 @@ class Organization(BaseModel):
1615

1716
model_config = ConfigDict(from_attributes=True)
1817

19-
id: UUID = Field(description="Unique identifier for the organization.")
18+
id: int = Field(description="Unique identifier for the organization.")
2019

2120
slug: str = Field(description="URL-safe identifier for the organization.")
2221

src/docverse/handlers/admin/models.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ def from_domain(cls, domain: OrganizationDomain, request: Request) -> Self:
2020
self_url=str(
2121
request.url_for("get_organization", org_slug=domain.slug)
2222
),
23-
id=domain.id,
2423
slug=domain.slug,
2524
title=domain.title,
2625
base_domain=domain.base_domain,

tests/handlers/admin_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ async def test_create_organization(client: AsyncClient) -> None:
2424
assert data["url_scheme"] == "subdomain"
2525
assert data["root_path_prefix"] == "/"
2626
assert data["purgatory_retention"] == 2592000
27-
assert data["id"] is not None
27+
assert "id" not in data
2828
assert data["date_created"] is not None
2929
assert data["date_updated"] is not None
3030
assert data["self_url"].endswith("/admin/orgs/test-org")

0 commit comments

Comments
 (0)