• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 18558080767

16 Oct 2025 10:20AM UTC coverage: 54.579% (-0.008%) from 54.587%
18558080767

Pull #4319

github

web-flow
Merge 73845860d into af399f974
Pull Request #4319: feat: add flag to skip linking pooler

23 of 29 new or added lines in 4 files covered. (79.31%)

7 existing lines in 2 files now uncovered.

6389 of 11706 relevant lines covered (54.58%)

6.09 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/cmd/db.go
1
package cmd
2

3
import (
4
        "fmt"
5
        "os"
6
        "os/signal"
7
        "path/filepath"
8

9
        "github.com/spf13/afero"
10
        "github.com/spf13/cobra"
11
        "github.com/spf13/viper"
12
        "github.com/supabase/cli/internal/db/branch/create"
13
        "github.com/supabase/cli/internal/db/branch/delete"
14
        "github.com/supabase/cli/internal/db/branch/list"
15
        "github.com/supabase/cli/internal/db/branch/switch_"
16
        "github.com/supabase/cli/internal/db/diff"
17
        "github.com/supabase/cli/internal/db/dump"
18
        "github.com/supabase/cli/internal/db/lint"
19
        "github.com/supabase/cli/internal/db/pull"
20
        "github.com/supabase/cli/internal/db/push"
21
        "github.com/supabase/cli/internal/db/reset"
22
        "github.com/supabase/cli/internal/db/start"
23
        "github.com/supabase/cli/internal/db/test"
24
        "github.com/supabase/cli/internal/utils"
25
        "github.com/supabase/cli/internal/utils/flags"
26
        "github.com/supabase/cli/pkg/migration"
27
)
28

29
var (
30
        dbCmd = &cobra.Command{
31
                GroupID: groupLocalDev,
32
                Use:     "db",
33
                Short:   "Manage Postgres databases",
34
                PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
×
35
                        ctx, _ := signal.NotifyContext(cmd.Context(), os.Interrupt)
×
36
                        cmd.SetContext(ctx)
×
37
                        return cmd.Root().PersistentPreRunE(cmd, args)
×
38
                },
×
39
        }
40

41
        dbBranchCmd = &cobra.Command{
42
                Hidden: true,
43
                Use:    "branch",
44
                Short:  "Manage local database branches",
45
                Long:   "Manage local database branches. Each branch is associated with a separate local database. Forking remote databases is NOT supported.",
46
        }
47

48
        dbBranchCreateCmd = &cobra.Command{
49
                Deprecated: "use \"branches create <name>\" instead.\n",
50
                Use:        "create <branch name>",
51
                Short:      "Create a branch",
52
                Args:       cobra.ExactArgs(1),
53
                RunE: func(cmd *cobra.Command, args []string) error {
×
54
                        return create.Run(args[0], afero.NewOsFs())
×
55
                },
×
56
        }
57

58
        dbBranchDeleteCmd = &cobra.Command{
59
                Deprecated: "use \"branches delete <branch-id>\" instead.\n",
60
                Use:        "delete <branch name>",
61
                Short:      "Delete a branch",
62
                Args:       cobra.ExactArgs(1),
63
                RunE: func(cmd *cobra.Command, args []string) error {
×
64
                        return delete.Run(args[0], afero.NewOsFs())
×
65
                },
×
66
        }
67

68
        dbBranchListCmd = &cobra.Command{
69
                Deprecated: "use \"branches list\" instead.\n",
70
                Use:        "list",
71
                Short:      "List branches",
72
                RunE: func(cmd *cobra.Command, args []string) error {
×
73
                        return list.Run(afero.NewOsFs(), os.Stdout)
×
74
                },
×
75
        }
76

77
        dbSwitchCmd = &cobra.Command{
78
                Deprecated: "use \"branches create <name>\" instead.\n",
79
                Use:        "switch <branch name>",
80
                Short:      "Switch the active branch",
81
                Args:       cobra.ExactArgs(1),
82
                RunE: func(cmd *cobra.Command, args []string) error {
×
83
                        return switch_.Run(cmd.Context(), args[0], afero.NewOsFs())
×
84
                },
×
85
        }
86

87
        useMigra    bool
88
        usePgAdmin  bool
89
        usePgSchema bool
90
        schema      []string
91
        file        string
92

93
        dbDiffCmd = &cobra.Command{
94
                Use:   "diff",
95
                Short: "Diffs the local database for schema changes",
96
                RunE: func(cmd *cobra.Command, args []string) error {
×
97
                        if usePgAdmin {
×
98
                                return diff.RunPgAdmin(cmd.Context(), schema, file, flags.DbConfig, afero.NewOsFs())
×
99
                        }
×
100
                        differ := diff.DiffSchemaMigra
×
101
                        if usePgSchema {
×
102
                                differ = diff.DiffPgSchema
×
103
                                fmt.Fprintln(os.Stderr, utils.Yellow("WARNING:"), "--use-pg-schema flag is experimental and may not include all entities, such as views and grants.")
×
104
                        } else if !viper.GetBool("EXPERIMENTAL") {
×
105
                                differ = diff.DiffSchemaMigraBash
×
106
                        }
×
107
                        return diff.Run(cmd.Context(), schema, file, flags.DbConfig, differ, afero.NewOsFs())
×
108
                },
109
        }
110

111
        dataOnly     bool
112
        useCopy      bool
113
        roleOnly     bool
114
        keepComments bool
115
        excludeTable []string
116

117
        dbDumpCmd = &cobra.Command{
118
                Use:   "dump",
119
                Short: "Dumps data or schemas from the remote database",
120
                PreRun: func(cmd *cobra.Command, args []string) {
×
121
                        if useCopy || len(excludeTable) > 0 {
×
122
                                cobra.CheckErr(cmd.MarkFlagRequired("data-only"))
×
123
                        }
×
124
                },
125
                RunE: func(cmd *cobra.Command, args []string) error {
×
126
                        opts := []migration.DumpOptionFunc{
×
127
                                migration.WithSchema(schema...),
×
128
                                migration.WithoutTable(excludeTable...),
×
129
                                migration.WithComments(keepComments),
×
130
                                migration.WithColumnInsert(!useCopy),
×
131
                        }
×
132
                        return dump.Run(cmd.Context(), file, flags.DbConfig, dataOnly, roleOnly, dryRun, afero.NewOsFs(), opts...)
×
133
                },
×
134
                PostRun: func(cmd *cobra.Command, args []string) {
×
135
                        if len(file) > 0 {
×
136
                                if absPath, err := filepath.Abs(file); err != nil {
×
137
                                        fmt.Fprintln(os.Stderr, "Dumped schema to "+utils.Bold(file)+".")
×
138
                                } else {
×
139
                                        fmt.Fprintln(os.Stderr, "Dumped schema to "+utils.Bold(absPath)+".")
×
140
                                }
×
141
                        }
142
                },
143
        }
144

145
        dryRun       bool
146
        includeAll   bool
147
        includeRoles bool
148
        includeSeed  bool
149

150
        dbPushCmd = &cobra.Command{
151
                Use:   "push",
152
                Short: "Push new migrations to the remote database",
153
                RunE: func(cmd *cobra.Command, args []string) error {
×
154
                        return push.Run(cmd.Context(), dryRun, includeAll, includeRoles, includeSeed, flags.DbConfig, afero.NewOsFs())
×
155
                },
×
156
        }
157

158
        dbPullCmd = &cobra.Command{
159
                Use:   "pull [migration name]",
160
                Short: "Pull schema from the remote database",
161
                RunE: func(cmd *cobra.Command, args []string) error {
×
162
                        name := "remote_schema"
×
163
                        if len(args) > 0 {
×
164
                                name = args[0]
×
165
                        }
×
166
                        return pull.Run(cmd.Context(), schema, flags.DbConfig, name, afero.NewOsFs())
×
167
                },
168
                PostRun: func(cmd *cobra.Command, args []string) {
×
169
                        fmt.Println("Finished " + utils.Aqua("supabase db pull") + ".")
×
170
                },
×
171
        }
172

173
        dbRemoteCmd = &cobra.Command{
174
                Hidden: true,
175
                Use:    "remote",
176
                Short:  "Manage remote databases",
177
        }
178

179
        dbRemoteChangesCmd = &cobra.Command{
180
                Deprecated: "use \"db diff --use-migra --linked\" instead.\n",
181
                Use:        "changes",
182
                Short:      "Show changes on the remote database",
183
                Long:       "Show changes on the remote database since last migration.",
184
                RunE: func(cmd *cobra.Command, args []string) error {
×
185
                        return diff.Run(cmd.Context(), schema, file, flags.DbConfig, diff.DiffSchemaMigra, afero.NewOsFs())
×
186
                },
×
187
        }
188

189
        dbRemoteCommitCmd = &cobra.Command{
190
                Deprecated: "use \"db pull\" instead.\n",
191
                Use:        "commit",
192
                Short:      "Commit remote changes as a new migration",
193
                RunE: func(cmd *cobra.Command, args []string) error {
×
194
                        return pull.Run(cmd.Context(), schema, flags.DbConfig, "remote_commit", afero.NewOsFs())
×
195
                },
×
196
        }
197

198
        noSeed      bool
199
        lastVersion uint
200

201
        dbResetCmd = &cobra.Command{
202
                Use:   "reset",
203
                Short: "Resets the local database to current migrations",
204
                RunE: func(cmd *cobra.Command, args []string) error {
×
205
                        if noSeed {
×
206
                                utils.Config.Db.Seed.Enabled = false
×
207
                        }
×
208
                        return reset.Run(cmd.Context(), migrationVersion, lastVersion, flags.DbConfig, afero.NewOsFs())
×
209
                },
210
        }
211

212
        level = utils.EnumFlag{
213
                Allowed: lint.AllowedLevels,
214
                Value:   lint.AllowedLevels[0],
215
        }
216

217
        lintFailOn = utils.EnumFlag{
218
                Allowed: append([]string{"none"}, lint.AllowedLevels...),
219
                Value:   "none",
220
        }
221

222
        dbLintCmd = &cobra.Command{
223
                Use:   "lint",
224
                Short: "Checks local database for typing error",
225
                RunE: func(cmd *cobra.Command, args []string) error {
×
226
                        return lint.Run(cmd.Context(), schema, level.Value, lintFailOn.Value, flags.DbConfig, afero.NewOsFs())
×
227
                },
×
228
        }
229

230
        fromBackup string
231

232
        dbStartCmd = &cobra.Command{
233
                Use:   "start",
234
                Short: "Starts local Postgres database",
235
                RunE: func(cmd *cobra.Command, args []string) error {
×
236
                        return start.Run(cmd.Context(), fromBackup, afero.NewOsFs())
×
237
                },
×
238
        }
239

240
        dbTestCmd = &cobra.Command{
241
                Hidden: true,
242
                Use:    "test [path] ...",
243
                Short:  "Tests local database with pgTAP",
244
                RunE: func(cmd *cobra.Command, args []string) error {
×
245
                        return test.Run(cmd.Context(), args, flags.DbConfig, afero.NewOsFs())
×
246
                },
×
247
        }
248
)
249

250
func init() {
×
251
        // Build branch command
×
252
        dbBranchCmd.AddCommand(dbBranchCreateCmd)
×
253
        dbBranchCmd.AddCommand(dbBranchDeleteCmd)
×
254
        dbBranchCmd.AddCommand(dbBranchListCmd)
×
255
        dbBranchCmd.AddCommand(dbSwitchCmd)
×
256
        dbCmd.AddCommand(dbBranchCmd)
×
257
        // Build diff command
×
258
        diffFlags := dbDiffCmd.Flags()
×
259
        diffFlags.BoolVar(&useMigra, "use-migra", true, "Use migra to generate schema diff.")
×
260
        diffFlags.BoolVar(&usePgAdmin, "use-pgadmin", false, "Use pgAdmin to generate schema diff.")
×
261
        diffFlags.BoolVar(&usePgSchema, "use-pg-schema", false, "Use pg-schema-diff to generate schema diff.")
×
262
        dbDiffCmd.MarkFlagsMutuallyExclusive("use-migra", "use-pgadmin")
×
263
        diffFlags.String("db-url", "", "Diffs against the database specified by the connection string (must be percent-encoded).")
×
264
        diffFlags.Bool("linked", false, "Diffs local migration files against the linked project.")
×
265
        diffFlags.Bool("local", true, "Diffs local migration files against the local database.")
×
266
        dbDiffCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
267
        diffFlags.StringVarP(&file, "file", "f", "", "Saves schema diff to a new migration file.")
×
268
        diffFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
269
        dbCmd.AddCommand(dbDiffCmd)
×
270
        // Build dump command
×
271
        dumpFlags := dbDumpCmd.Flags()
×
272
        dumpFlags.BoolVar(&dryRun, "dry-run", false, "Prints the pg_dump script that would be executed.")
×
273
        dumpFlags.BoolVar(&dataOnly, "data-only", false, "Dumps only data records.")
×
NEW
274
        dumpFlags.BoolVar(&useCopy, "use-copy", false, "Use copy statements in place of inserts.")
×
275
        dumpFlags.StringSliceVarP(&excludeTable, "exclude", "x", []string{}, "List of schema.tables to exclude from data-only dump.")
×
276
        dumpFlags.BoolVar(&roleOnly, "role-only", false, "Dumps only cluster roles.")
×
277
        dbDumpCmd.MarkFlagsMutuallyExclusive("role-only", "data-only")
×
278
        dumpFlags.BoolVar(&keepComments, "keep-comments", false, "Keeps commented lines from pg_dump output.")
×
279
        dbDumpCmd.MarkFlagsMutuallyExclusive("keep-comments", "data-only")
×
280
        dumpFlags.StringVarP(&file, "file", "f", "", "File path to save the dumped contents.")
×
281
        dumpFlags.String("db-url", "", "Dumps from the database specified by the connection string (must be percent-encoded).")
×
282
        dumpFlags.Bool("linked", true, "Dumps from the linked project.")
×
283
        dumpFlags.Bool("local", false, "Dumps from the local database.")
×
284
        dbDumpCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
285
        dumpFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
286
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", dumpFlags.Lookup("password")))
×
287
        dumpFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
288
        dbDumpCmd.MarkFlagsMutuallyExclusive("schema", "role-only")
×
289
        dbCmd.AddCommand(dbDumpCmd)
×
290
        // Build push command
×
291
        pushFlags := dbPushCmd.Flags()
×
292
        pushFlags.BoolVar(&includeAll, "include-all", false, "Include all migrations not found on remote history table.")
×
293
        pushFlags.BoolVar(&includeRoles, "include-roles", false, "Include custom roles from "+utils.CustomRolesPath+".")
×
294
        pushFlags.BoolVar(&includeSeed, "include-seed", false, "Include seed data from your config.")
×
295
        pushFlags.BoolVar(&dryRun, "dry-run", false, "Print the migrations that would be applied, but don't actually apply them.")
×
296
        pushFlags.String("db-url", "", "Pushes to the database specified by the connection string (must be percent-encoded).")
×
297
        pushFlags.Bool("linked", true, "Pushes to the linked project.")
×
298
        pushFlags.Bool("local", false, "Pushes to the local database.")
×
299
        dbPushCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
300
        pushFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
301
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", pushFlags.Lookup("password")))
×
302
        dbCmd.AddCommand(dbPushCmd)
×
303
        // Build pull command
×
304
        pullFlags := dbPullCmd.Flags()
×
305
        pullFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
306
        pullFlags.String("db-url", "", "Pulls from the database specified by the connection string (must be percent-encoded).")
×
307
        pullFlags.Bool("linked", true, "Pulls from the linked project.")
×
308
        pullFlags.Bool("local", false, "Pulls from the local database.")
×
309
        dbPullCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
310
        pullFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
311
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", pullFlags.Lookup("password")))
×
312
        dbCmd.AddCommand(dbPullCmd)
×
313
        // Build remote command
×
314
        remoteFlags := dbRemoteCmd.PersistentFlags()
×
315
        remoteFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
316
        remoteFlags.String("db-url", "", "Connect using the specified Postgres URL (must be percent-encoded).")
×
317
        remoteFlags.Bool("linked", true, "Connect to the linked project.")
×
318
        dbRemoteCmd.MarkFlagsMutuallyExclusive("db-url", "linked")
×
319
        remoteFlags.StringVarP(&dbPassword, "password", "p", "", "Password to your remote Postgres database.")
×
320
        cobra.CheckErr(viper.BindPFlag("DB_PASSWORD", remoteFlags.Lookup("password")))
×
321
        dbRemoteCmd.AddCommand(dbRemoteChangesCmd)
×
322
        dbRemoteCmd.AddCommand(dbRemoteCommitCmd)
×
323
        dbCmd.AddCommand(dbRemoteCmd)
×
324
        // Build reset command
×
325
        resetFlags := dbResetCmd.Flags()
×
326
        resetFlags.String("db-url", "", "Resets the database specified by the connection string (must be percent-encoded).")
×
327
        resetFlags.Bool("linked", false, "Resets the linked project with local migrations.")
×
328
        resetFlags.Bool("local", true, "Resets the local database with local migrations.")
×
329
        resetFlags.BoolVar(&noSeed, "no-seed", false, "Skip running the seed script after reset.")
×
330
        dbResetCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
331
        resetFlags.StringVar(&migrationVersion, "version", "", "Reset up to the specified version.")
×
332
        resetFlags.UintVar(&lastVersion, "last", 0, "Reset up to the last n migration versions.")
×
333
        dbResetCmd.MarkFlagsMutuallyExclusive("version", "last")
×
334
        dbCmd.AddCommand(dbResetCmd)
×
335
        // Build lint command
×
336
        lintFlags := dbLintCmd.Flags()
×
337
        lintFlags.String("db-url", "", "Lints the database specified by the connection string (must be percent-encoded).")
×
338
        lintFlags.Bool("linked", false, "Lints the linked project for schema errors.")
×
339
        lintFlags.Bool("local", true, "Lints the local database for schema errors.")
×
340
        dbLintCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
341
        lintFlags.StringSliceVarP(&schema, "schema", "s", []string{}, "Comma separated list of schema to include.")
×
342
        lintFlags.Var(&level, "level", "Error level to emit.")
×
343
        lintFlags.Var(&lintFailOn, "fail-on", "Error level to exit with non-zero status.")
×
344
        dbCmd.AddCommand(dbLintCmd)
×
345
        // Build start command
×
346
        startFlags := dbStartCmd.Flags()
×
347
        startFlags.StringVar(&fromBackup, "from-backup", "", "Path to a logical backup file.")
×
348
        dbCmd.AddCommand(dbStartCmd)
×
349
        // Build test command
×
350
        dbCmd.AddCommand(dbTestCmd)
×
351
        testFlags := dbTestCmd.Flags()
×
352
        testFlags.String("db-url", "", "Tests the database specified by the connection string (must be percent-encoded).")
×
353
        testFlags.Bool("linked", false, "Runs pgTAP tests on the linked project.")
×
354
        testFlags.Bool("local", true, "Runs pgTAP tests on the local database.")
×
355
        dbTestCmd.MarkFlagsMutuallyExclusive("db-url", "linked", "local")
×
356
        rootCmd.AddCommand(dbCmd)
×
357
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc