Skip to content

Commit 5b2addf

Browse files
Lendemoradhami3310
andauthored
Add db status command (#5560)
* add db status command * fix status command --------- Co-authored-by: Khaleel Al-Adhami <khaleel.aladhami@gmail.com>
1 parent c5bfad4 commit 5b2addf

2 files changed

Lines changed: 88 additions & 0 deletions

File tree

reflex/model.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import sqlalchemy.ext.asyncio
2020
import sqlalchemy.orm
2121
from alembic.runtime.migration import MigrationContext
22+
from alembic.script.base import Script
2223

2324
from reflex.base import Base
2425
from reflex.config import get_config
@@ -34,6 +35,41 @@
3435
from sqlmodel.ext.asyncio.session import AsyncSession # noqa: E402
3536

3637

38+
def format_revision(
39+
rev: Script,
40+
current_rev: str | None,
41+
current_reached_ref: list[bool],
42+
) -> str:
43+
"""Format a single revision for display.
44+
45+
Args:
46+
rev: The alembic script object
47+
current_rev: The currently applied revision ID
48+
current_reached_ref: Mutable reference to track if we've reached current revision
49+
50+
Returns:
51+
Formatted string for display
52+
"""
53+
current = rev.revision
54+
message = rev.doc
55+
56+
# Determine if this migration is applied
57+
if current_rev is None:
58+
is_applied = False
59+
elif current == current_rev:
60+
is_applied = True
61+
current_reached_ref[0] = True
62+
else:
63+
is_applied = not current_reached_ref[0]
64+
65+
# Show checkmark or X with colors
66+
status_icon = "[green]✓[/green]" if is_applied else "[red]✗[/red]"
67+
head_marker = " (head)" if rev.is_head else ""
68+
69+
# Format output with message
70+
return f" [{status_icon}] {current}{head_marker}, {message}"
71+
72+
3773
def _safe_db_url_for_logging(url: str) -> str:
3874
"""Remove username and password from the database URL for logging.
3975
@@ -361,6 +397,25 @@ def alembic_init(cls):
361397
directory=str(environment.ALEMBIC_CONFIG.get().parent / "alembic"),
362398
)
363399

400+
@classmethod
401+
def get_migration_history(cls):
402+
"""Get migration history with current database state.
403+
404+
Returns:
405+
tuple: (current_revision, revisions_list) where revisions_list is in chronological order
406+
"""
407+
# Get current revision from database
408+
with cls.get_db_engine().connect() as connection:
409+
context = MigrationContext.configure(connection)
410+
current_rev = context.get_current_revision()
411+
412+
# Get all revisions from base to head
413+
_, script_dir = cls._alembic_config()
414+
revisions = list(script_dir.walk_revisions())
415+
revisions.reverse() # Reverse to get chronological order (base first)
416+
417+
return current_rev, revisions
418+
364419
@classmethod
365420
def alembic_autogenerate(
366421
cls,

reflex/reflex.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,39 @@ def migrate():
540540
prerequisites.check_schema_up_to_date()
541541

542542

543+
@db_cli.command()
544+
def status():
545+
"""Check the status of the database schema."""
546+
from reflex.model import Model, format_revision
547+
from reflex.utils import prerequisites
548+
549+
prerequisites.get_app()
550+
if not prerequisites.check_db_initialized():
551+
console.info(
552+
"Database is not initialized. Run [bold]reflex db init[/bold] to initialize."
553+
)
554+
return
555+
556+
# Run alembic check command and display output
557+
import reflex.config
558+
559+
config = reflex.config.get_config()
560+
console.print(f"[bold]\\[{config.db_url}][/bold]")
561+
562+
# Get migration history using Model method
563+
current_rev, revisions = Model.get_migration_history()
564+
if current_rev is None and not revisions:
565+
return
566+
567+
current_reached_ref = [current_rev is None]
568+
569+
# Show migration history in chronological order
570+
console.print("<base>")
571+
for rev in revisions:
572+
# Format and print the revision
573+
console.print(format_revision(rev, current_rev, current_reached_ref))
574+
575+
543576
@db_cli.command()
544577
@click.option(
545578
"--message",

0 commit comments

Comments
 (0)