Add core data model (12 tables) and initial Alembic migration
All core entities from ARCHITECTURE §5: tenancy (User, Tree, TreeMembership), people (Person, Name, Relationship), facts (Event, Place, PlaceName), provenance (Source, Citation), and the append-only AuditEntry. Cross-cutting mixins give every row a UUID key, timestamps, soft delete, and (where tree-owned) a tree_id for uniform tenant isolation. Modeling choices: parentage as qualified edges (biological/adoptive/step/foster/donor/guardian) so non-traditional families are first-class; events keep both a verbatim date string and a normalized start/end range; closed sets are PG enums while GEDCOM-extensible vocabularies (event/name/source type) stay strings; CHECK constraints enforce single-subject events and single-target citations. Place is tree-scoped in Phase 0 (see ARCHITECTURE note). The migration is verified reversible (upgrade/downgrade drops tables and enum types) and matches the models (alembic check clean); applied on the deploy target. Dockerfile now ships migrations. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Justin Paul <justin@jpaul.me>
This commit is contained in:
@@ -0,0 +1,304 @@
|
||||
"""core data model
|
||||
|
||||
Revision ID: ec43c338e155
|
||||
Revises:
|
||||
Create Date: 2026-06-06 10:27:41.671787
|
||||
|
||||
"""
|
||||
from collections.abc import Sequence
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = 'ec43c338e155'
|
||||
down_revision: str | None = None
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('users',
|
||||
sa.Column('email', sa.String(length=320), nullable=False),
|
||||
sa.Column('email_verified_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('display_name', sa.String(length=255), nullable=True),
|
||||
sa.Column('hashed_password', sa.String(length=255), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_users'))
|
||||
)
|
||||
op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
|
||||
op.create_table('trees',
|
||||
sa.Column('owner_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('visibility', sa.Enum('public', 'unlisted', 'private', name='tree_visibility'), server_default='private', nullable=False),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.ForeignKeyConstraint(['owner_id'], ['users.id'], name=op.f('fk_trees_owner_id_users'), ondelete='RESTRICT'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_trees'))
|
||||
)
|
||||
op.create_index(op.f('ix_trees_owner_id'), 'trees', ['owner_id'], unique=False)
|
||||
op.create_table('audit_entries',
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('actor_type', sa.Enum('user', 'assistant', name='audit_actor_type'), server_default='user', nullable=False),
|
||||
sa.Column('actor_user_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('action', sa.String(length=64), nullable=False),
|
||||
sa.Column('entity_type', sa.String(length=64), nullable=False),
|
||||
sa.Column('entity_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('before', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('after', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['actor_user_id'], ['users.id'], name=op.f('fk_audit_entries_actor_user_id_users'), ondelete='SET NULL'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_audit_entries_tree_id_trees'), ondelete='SET NULL'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_audit_entries'))
|
||||
)
|
||||
op.create_index(op.f('ix_audit_entries_actor_user_id'), 'audit_entries', ['actor_user_id'], unique=False)
|
||||
op.create_index(op.f('ix_audit_entries_created_at'), 'audit_entries', ['created_at'], unique=False)
|
||||
op.create_index(op.f('ix_audit_entries_tree_id'), 'audit_entries', ['tree_id'], unique=False)
|
||||
op.create_table('persons',
|
||||
sa.Column('gender', sa.String(length=32), nullable=True),
|
||||
sa.Column('is_living', sa.Boolean(), nullable=True),
|
||||
sa.Column('privacy', sa.Enum('inherit', 'private', 'public', name='person_privacy'), server_default='inherit', nullable=False),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_persons_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_persons'))
|
||||
)
|
||||
op.create_index(op.f('ix_persons_tree_id'), 'persons', ['tree_id'], unique=False)
|
||||
op.create_table('places',
|
||||
sa.Column('name', sa.String(length=512), nullable=False),
|
||||
sa.Column('parent_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('place_type', sa.String(length=64), nullable=True),
|
||||
sa.Column('latitude', sa.Float(), nullable=True),
|
||||
sa.Column('longitude', sa.Float(), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.ForeignKeyConstraint(['parent_id'], ['places.id'], name=op.f('fk_places_parent_id_places'), ondelete='SET NULL'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_places_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_places'))
|
||||
)
|
||||
op.create_index(op.f('ix_places_parent_id'), 'places', ['parent_id'], unique=False)
|
||||
op.create_index(op.f('ix_places_tree_id'), 'places', ['tree_id'], unique=False)
|
||||
op.create_table('sources',
|
||||
sa.Column('title', sa.String(length=512), nullable=False),
|
||||
sa.Column('author', sa.String(length=255), nullable=True),
|
||||
sa.Column('source_type', sa.String(length=64), nullable=True),
|
||||
sa.Column('repository', sa.String(length=255), nullable=True),
|
||||
sa.Column('url', sa.String(length=1024), nullable=True),
|
||||
sa.Column('citation_text', sa.Text(), nullable=True),
|
||||
sa.Column('publication_info', sa.Text(), nullable=True),
|
||||
sa.Column('quality_note', sa.String(length=255), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_sources_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_sources'))
|
||||
)
|
||||
op.create_index(op.f('ix_sources_tree_id'), 'sources', ['tree_id'], unique=False)
|
||||
op.create_table('tree_memberships',
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('user_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('role', sa.Enum('owner', 'editor', 'viewer', name='membership_role'), nullable=False),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_tree_memberships_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], name=op.f('fk_tree_memberships_user_id_users'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_tree_memberships')),
|
||||
sa.UniqueConstraint('tree_id', 'user_id', name='uq_tree_memberships_tree_user')
|
||||
)
|
||||
op.create_index(op.f('ix_tree_memberships_tree_id'), 'tree_memberships', ['tree_id'], unique=False)
|
||||
op.create_index(op.f('ix_tree_memberships_user_id'), 'tree_memberships', ['user_id'], unique=False)
|
||||
op.create_table('names',
|
||||
sa.Column('person_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('name_type', sa.String(length=32), server_default='birth', nullable=False),
|
||||
sa.Column('given', sa.String(length=255), nullable=True),
|
||||
sa.Column('surname', sa.String(length=255), nullable=True),
|
||||
sa.Column('prefix', sa.String(length=64), nullable=True),
|
||||
sa.Column('suffix', sa.String(length=64), nullable=True),
|
||||
sa.Column('nickname', sa.String(length=128), nullable=True),
|
||||
sa.Column('display_name', sa.String(length=512), nullable=True),
|
||||
sa.Column('is_primary', sa.Boolean(), server_default=sa.text('false'), nullable=False),
|
||||
sa.Column('sort_order', sa.Integer(), server_default='0', nullable=False),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.ForeignKeyConstraint(['person_id'], ['persons.id'], name=op.f('fk_names_person_id_persons'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_names_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_names'))
|
||||
)
|
||||
op.create_index(op.f('ix_names_person_id'), 'names', ['person_id'], unique=False)
|
||||
op.create_index(op.f('ix_names_tree_id'), 'names', ['tree_id'], unique=False)
|
||||
op.create_table('place_names',
|
||||
sa.Column('place_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('name', sa.String(length=512), nullable=False),
|
||||
sa.Column('valid_from', sa.Date(), nullable=True),
|
||||
sa.Column('valid_to', sa.Date(), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.ForeignKeyConstraint(['place_id'], ['places.id'], name=op.f('fk_place_names_place_id_places'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_place_names_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_place_names'))
|
||||
)
|
||||
op.create_index(op.f('ix_place_names_place_id'), 'place_names', ['place_id'], unique=False)
|
||||
op.create_index(op.f('ix_place_names_tree_id'), 'place_names', ['tree_id'], unique=False)
|
||||
op.create_table('relationships',
|
||||
sa.Column('type', sa.Enum('parent_child', 'partnership', 'sibling', name='relationship_type'), nullable=False),
|
||||
sa.Column('person_from_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('person_to_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('qualifier', sa.Enum('biological', 'adoptive', 'step', 'foster', 'donor', 'guardian', name='parent_child_qualifier'), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.CheckConstraint('person_from_id <> person_to_id', name=op.f('ck_relationships_different_persons')),
|
||||
sa.ForeignKeyConstraint(['person_from_id'], ['persons.id'], name=op.f('fk_relationships_person_from_id_persons'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['person_to_id'], ['persons.id'], name=op.f('fk_relationships_person_to_id_persons'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_relationships_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_relationships'))
|
||||
)
|
||||
op.create_index(op.f('ix_relationships_person_from_id'), 'relationships', ['person_from_id'], unique=False)
|
||||
op.create_index(op.f('ix_relationships_person_to_id'), 'relationships', ['person_to_id'], unique=False)
|
||||
op.create_index(op.f('ix_relationships_tree_id'), 'relationships', ['tree_id'], unique=False)
|
||||
op.create_table('events',
|
||||
sa.Column('event_type', sa.String(length=64), nullable=False),
|
||||
sa.Column('person_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('relationship_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('place_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('date_value', sa.String(length=255), nullable=True),
|
||||
sa.Column('date_start', sa.Date(), nullable=True),
|
||||
sa.Column('date_end', sa.Date(), nullable=True),
|
||||
sa.Column('date_precision', sa.String(length=32), nullable=True),
|
||||
sa.Column('calendar', sa.String(length=32), server_default='gregorian', nullable=False),
|
||||
sa.Column('detail', sa.String(length=512), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.CheckConstraint('(person_id IS NOT NULL) <> (relationship_id IS NOT NULL)', name=op.f('ck_events_subject_person_xor_relationship')),
|
||||
sa.ForeignKeyConstraint(['person_id'], ['persons.id'], name=op.f('fk_events_person_id_persons'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['place_id'], ['places.id'], name=op.f('fk_events_place_id_places'), ondelete='SET NULL'),
|
||||
sa.ForeignKeyConstraint(['relationship_id'], ['relationships.id'], name=op.f('fk_events_relationship_id_relationships'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_events_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_events'))
|
||||
)
|
||||
op.create_index(op.f('ix_events_event_type'), 'events', ['event_type'], unique=False)
|
||||
op.create_index(op.f('ix_events_person_id'), 'events', ['person_id'], unique=False)
|
||||
op.create_index(op.f('ix_events_place_id'), 'events', ['place_id'], unique=False)
|
||||
op.create_index(op.f('ix_events_relationship_id'), 'events', ['relationship_id'], unique=False)
|
||||
op.create_index(op.f('ix_events_tree_id'), 'events', ['tree_id'], unique=False)
|
||||
op.create_table('citations',
|
||||
sa.Column('source_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('person_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('event_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('name_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('relationship_id', sa.Uuid(), nullable=True),
|
||||
sa.Column('page', sa.String(length=255), nullable=True),
|
||||
sa.Column('detail', sa.Text(), nullable=True),
|
||||
sa.Column('confidence', sa.Enum('high', 'medium', 'low', name='citation_confidence'), nullable=True),
|
||||
sa.Column('id', sa.Uuid(), nullable=False),
|
||||
sa.Column('tree_id', sa.Uuid(), nullable=False),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
||||
sa.Column('deleted_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.CheckConstraint('(person_id IS NOT NULL)::int + (event_id IS NOT NULL)::int + (name_id IS NOT NULL)::int + (relationship_id IS NOT NULL)::int = 1', name=op.f('ck_citations_exactly_one_target')),
|
||||
sa.ForeignKeyConstraint(['event_id'], ['events.id'], name=op.f('fk_citations_event_id_events'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['name_id'], ['names.id'], name=op.f('fk_citations_name_id_names'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['person_id'], ['persons.id'], name=op.f('fk_citations_person_id_persons'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['relationship_id'], ['relationships.id'], name=op.f('fk_citations_relationship_id_relationships'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['source_id'], ['sources.id'], name=op.f('fk_citations_source_id_sources'), ondelete='CASCADE'),
|
||||
sa.ForeignKeyConstraint(['tree_id'], ['trees.id'], name=op.f('fk_citations_tree_id_trees'), ondelete='CASCADE'),
|
||||
sa.PrimaryKeyConstraint('id', name=op.f('pk_citations'))
|
||||
)
|
||||
op.create_index(op.f('ix_citations_event_id'), 'citations', ['event_id'], unique=False)
|
||||
op.create_index(op.f('ix_citations_name_id'), 'citations', ['name_id'], unique=False)
|
||||
op.create_index(op.f('ix_citations_person_id'), 'citations', ['person_id'], unique=False)
|
||||
op.create_index(op.f('ix_citations_relationship_id'), 'citations', ['relationship_id'], unique=False)
|
||||
op.create_index(op.f('ix_citations_source_id'), 'citations', ['source_id'], unique=False)
|
||||
op.create_index(op.f('ix_citations_tree_id'), 'citations', ['tree_id'], unique=False)
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f('ix_citations_tree_id'), table_name='citations')
|
||||
op.drop_index(op.f('ix_citations_source_id'), table_name='citations')
|
||||
op.drop_index(op.f('ix_citations_relationship_id'), table_name='citations')
|
||||
op.drop_index(op.f('ix_citations_person_id'), table_name='citations')
|
||||
op.drop_index(op.f('ix_citations_name_id'), table_name='citations')
|
||||
op.drop_index(op.f('ix_citations_event_id'), table_name='citations')
|
||||
op.drop_table('citations')
|
||||
op.drop_index(op.f('ix_events_tree_id'), table_name='events')
|
||||
op.drop_index(op.f('ix_events_relationship_id'), table_name='events')
|
||||
op.drop_index(op.f('ix_events_place_id'), table_name='events')
|
||||
op.drop_index(op.f('ix_events_person_id'), table_name='events')
|
||||
op.drop_index(op.f('ix_events_event_type'), table_name='events')
|
||||
op.drop_table('events')
|
||||
op.drop_index(op.f('ix_relationships_tree_id'), table_name='relationships')
|
||||
op.drop_index(op.f('ix_relationships_person_to_id'), table_name='relationships')
|
||||
op.drop_index(op.f('ix_relationships_person_from_id'), table_name='relationships')
|
||||
op.drop_table('relationships')
|
||||
op.drop_index(op.f('ix_place_names_tree_id'), table_name='place_names')
|
||||
op.drop_index(op.f('ix_place_names_place_id'), table_name='place_names')
|
||||
op.drop_table('place_names')
|
||||
op.drop_index(op.f('ix_names_tree_id'), table_name='names')
|
||||
op.drop_index(op.f('ix_names_person_id'), table_name='names')
|
||||
op.drop_table('names')
|
||||
op.drop_index(op.f('ix_tree_memberships_user_id'), table_name='tree_memberships')
|
||||
op.drop_index(op.f('ix_tree_memberships_tree_id'), table_name='tree_memberships')
|
||||
op.drop_table('tree_memberships')
|
||||
op.drop_index(op.f('ix_sources_tree_id'), table_name='sources')
|
||||
op.drop_table('sources')
|
||||
op.drop_index(op.f('ix_places_tree_id'), table_name='places')
|
||||
op.drop_index(op.f('ix_places_parent_id'), table_name='places')
|
||||
op.drop_table('places')
|
||||
op.drop_index(op.f('ix_persons_tree_id'), table_name='persons')
|
||||
op.drop_table('persons')
|
||||
op.drop_index(op.f('ix_audit_entries_tree_id'), table_name='audit_entries')
|
||||
op.drop_index(op.f('ix_audit_entries_created_at'), table_name='audit_entries')
|
||||
op.drop_index(op.f('ix_audit_entries_actor_user_id'), table_name='audit_entries')
|
||||
op.drop_table('audit_entries')
|
||||
op.drop_index(op.f('ix_trees_owner_id'), table_name='trees')
|
||||
op.drop_table('trees')
|
||||
op.drop_index(op.f('ix_users_email'), table_name='users')
|
||||
op.drop_table('users')
|
||||
# ### end Alembic commands ###
|
||||
|
||||
# Enum types are created implicitly by create_table() but not dropped by
|
||||
# drop_table(); drop them explicitly so downgrade is fully reversible.
|
||||
for enum_name in (
|
||||
"tree_visibility",
|
||||
"membership_role",
|
||||
"person_privacy",
|
||||
"relationship_type",
|
||||
"parent_child_qualifier",
|
||||
"citation_confidence",
|
||||
"audit_actor_type",
|
||||
):
|
||||
op.execute(f"DROP TYPE IF EXISTS {enum_name}")
|
||||
Reference in New Issue
Block a user