Skip to main content

systemprompt_cli/commands/infrastructure/db/
commands.rs

1//! `infra db` command dispatch.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use clap::Subcommand;
7use systemprompt_identifiers::ExtensionId;
8
9#[derive(Debug, Subcommand)]
10pub enum DbCommands {
11    #[command(about = "Execute SQL query (read-only)")]
12    Query {
13        sql: String,
14        #[arg(long)]
15        limit: Option<u32>,
16        #[arg(long)]
17        offset: Option<u32>,
18    },
19    #[command(about = "Execute write operation (INSERT, UPDATE, DELETE)")]
20    Execute {
21        sql: String,
22        #[arg(short = 'y', long, help = "Skip the confirmation prompt")]
23        yes: bool,
24    },
25    #[command(
26        about = "List all tables with row counts and sizes",
27        long_about = "List all tables. Row counts come from the planner statistics \
28                      (pg_stat_user_tables) and can lag or read zero on a table that \
29                      was never analysed; pass --exact to COUNT(*) every table instead."
30    )]
31    Tables {
32        #[arg(long, help = "Filter tables by pattern")]
33        filter: Option<String>,
34        #[arg(
35            long,
36            help = "COUNT(*) each table instead of reading the statistics estimate"
37        )]
38        exact: bool,
39    },
40    #[command(about = "Describe table schema with columns and indexes")]
41    Describe { table_name: String },
42    #[command(about = "Show database information")]
43    Info,
44    #[command(about = "Run database migrations")]
45    Migrate {
46        #[arg(
47            long,
48            help = "Continue past migration checksum mismatches with a warning instead of \
49                    erroring (use with caution)"
50        )]
51        allow_checksum_drift: bool,
52        #[arg(
53            long,
54            conflicts_with = "allow_checksum_drift",
55            help = "If the install fails on checksum drift, and only then, re-apply the drifted \
56                    migrations (as `migrate-repair --apply`) and retry once. Any other failure \
57                    is reported as-is: repair cannot fix it"
58        )]
59        repair_drift: bool,
60    },
61    #[command(about = "Revert the most recently applied migrations for an extension")]
62    MigrateDown {
63        #[arg(help = "Extension ID", value_parser = crate::shared::parse_extension_id)]
64        extension: ExtensionId,
65        #[arg(help = "Number of migrations to revert")]
66        count: u32,
67    },
68    #[command(about = "Show migration status and history")]
69    Migrations {
70        #[command(subcommand)]
71        cmd: MigrationsCommands,
72    },
73    #[command(
74        about = "Show pending migrations (dry-run / plan, no DB writes)",
75        name = "migrate-plan"
76    )]
77    MigratePlan {
78        #[arg(
79            help = "Filter by extension ID (default: all extensions)",
80            value_parser = crate::shared::parse_extension_id
81        )]
82        extension: Option<ExtensionId>,
83        #[arg(long, help = "Emit JSON instead of a text table")]
84        json: bool,
85    },
86    #[command(
87        about = "Detailed introspectable migration status (applied, pending, drift)",
88        name = "migrate-status"
89    )]
90    MigrateStatus {
91        #[arg(
92            help = "Filter by extension ID (default: all extensions)",
93            value_parser = crate::shared::parse_extension_id
94        )]
95        extension: Option<ExtensionId>,
96        #[arg(long, help = "Emit JSON instead of a text table")]
97        json: bool,
98    },
99    #[command(
100        about = "Repair migration checksum drift — re-applies edited migrations in place, or with \
101                 --reconcile-only rewrites stored checksums without executing SQL",
102        name = "migrate-repair"
103    )]
104    MigrateRepair {
105        #[arg(
106            help = "Limit repair to a single extension (default: all extensions)",
107            value_parser = crate::shared::parse_extension_id
108        )]
109        extension: Option<ExtensionId>,
110        #[arg(
111            long,
112            help = "Apply the repair: re-execute the SQL of each drifted migration and rewrite \
113                    its stored checksum. Without this flag, the command is a dry-run that only \
114                    lists drift."
115        )]
116        apply: bool,
117        #[arg(
118            long,
119            help = "Bookkeeping only: rewrite stored checksums to match the current migration \
120                    files without executing any SQL. Asserts the schema already matches the \
121                    edited files; nothing verifies that."
122        )]
123        reconcile_only: bool,
124        #[arg(long, help = "Emit JSON instead of a text table")]
125        json: bool,
126    },
127    #[command(
128        about = "Record a migration as already applied without running its SQL (recovers partial \
129                 state where schema is applied but tracking row is missing)",
130        name = "migrate-mark-applied"
131    )]
132    MigrateMarkApplied {
133        #[arg(
134            long,
135            help = "Extension ID owning the migration",
136            value_parser = crate::shared::parse_extension_id
137        )]
138        extension: ExtensionId,
139        #[arg(long, help = "Migration version to mark as applied")]
140        version: u32,
141        #[arg(long, help = "Emit JSON instead of a text summary")]
142        json: bool,
143    },
144    #[command(about = "Assign admin role to a user")]
145    AssignAdmin { user: String },
146    #[command(about = "Show database connection status")]
147    Status,
148    #[command(about = "Get row count for a table")]
149    Count { table_name: String },
150    #[command(about = "List all indexes")]
151    Indexes {
152        #[arg(long, help = "Filter by table name")]
153        table: Option<String>,
154    },
155    #[command(about = "Show database and table sizes")]
156    Size,
157    #[command(about = "Diff live schema against extension declarations")]
158    Doctor,
159}
160
161#[derive(Debug, Subcommand)]
162pub enum MigrationsCommands {
163    #[command(about = "Show migration status for all extensions", alias = "list")]
164    Status,
165    #[command(about = "Show migration history for an extension")]
166    History {
167        #[arg(help = "Extension ID", value_parser = crate::shared::parse_extension_id)]
168        extension: ExtensionId,
169    },
170}