@@ -13,9 +13,11 @@ import (
1313var (
1414 snapshotCwd string
1515 snapshotOutput string
16+ snapshotOutputDir string
1617 snapshotFormat string
1718 snapshotSchemaOnly bool
1819 snapshotSection string
20+ snapshotSections bool
1921 snapshotInput string
2022 snapshotClean bool
2123 snapshotBuildFixtures []string
@@ -36,13 +38,21 @@ Examples:
3638 regresql snapshot capture
3739 regresql snapshot capture --output snapshots/mydata.dump
3840 regresql snapshot capture --schema-only
39- regresql snapshot capture --format plain --output snapshots/schema.sql` ,
41+ regresql snapshot capture --format plain --output snapshots/schema.sql
42+ regresql snapshot capture --section pre-data --output snapshots/pre-data.sql
43+ regresql snapshot capture --sections --output-dir snapshots/` ,
4044 Run : func (cmd * cobra.Command , args []string ) {
4145 if err := checkDirectory (snapshotCwd ); err != nil {
4246 fmt .Print (err .Error ())
4347 os .Exit (1 )
4448 }
45- if err := runSnapshotCapture (); err != nil {
49+ var err error
50+ if snapshotSections {
51+ err = runSnapshotCaptureSections ()
52+ } else {
53+ err = runSnapshotCapture ()
54+ }
55+ if err != nil {
4656 fmt .Printf ("Error: %s\n " , err .Error ())
4757 os .Exit (1 )
4858 }
@@ -123,9 +133,11 @@ func init() {
123133 snapshotCmd .PersistentFlags ().StringVarP (& snapshotCwd , "cwd" , "C" , "." , "Change to directory" )
124134
125135 snapshotCaptureCmd .Flags ().StringVarP (& snapshotOutput , "output" , "o" , "" , "Output file path" )
136+ snapshotCaptureCmd .Flags ().StringVar (& snapshotOutputDir , "output-dir" , "" , "Output directory for sectioned capture" )
126137 snapshotCaptureCmd .Flags ().StringVarP (& snapshotFormat , "format" , "f" , "" , "Dump format: custom, plain, or directory" )
127138 snapshotCaptureCmd .Flags ().BoolVar (& snapshotSchemaOnly , "schema-only" , false , "Dump only schema, no data" )
128139 snapshotCaptureCmd .Flags ().StringVar (& snapshotSection , "section" , "" , "Dump specific section: pre-data, data, or post-data" )
140+ snapshotCaptureCmd .Flags ().BoolVar (& snapshotSections , "sections" , false , "Capture all sections to separate SQL files" )
129141
130142 snapshotRestoreCmd .Flags ().StringVar (& snapshotInput , "from" , "" , "Input file path" )
131143 snapshotRestoreCmd .Flags ().StringVarP (& snapshotFormat , "format" , "f" , "" , "Snapshot format: custom, plain, or directory" )
@@ -137,18 +149,26 @@ func init() {
137149 snapshotBuildCmd .Flags ().BoolVarP (& snapshotBuildVerbose , "verbose" , "v" , false , "Print detailed progress" )
138150}
139151
152+ func validateSnapshotPrereqs (pguri string ) error {
153+ if pguri == "" {
154+ return fmt .Errorf ("pguri not configured in regress.yaml" )
155+ }
156+ if err := regresql .TestConnectionString (pguri ); err != nil {
157+ return fmt .Errorf ("database connection failed: %w" , err )
158+ }
159+ if err := regresql .CheckPgTool ("pg_dump" , snapshotCwd ); err != nil {
160+ return err
161+ }
162+ return nil
163+ }
164+
140165func runSnapshotCapture () error {
141166 cfg , err := regresql .ReadConfig (snapshotCwd )
142167 if err != nil {
143168 return fmt .Errorf ("failed to read config: %w (have you run 'regresql init'?)" , err )
144169 }
145-
146- if cfg .PgUri == "" {
147- return fmt .Errorf ("pguri not configured in regress.yaml" )
148- }
149-
150- if err := regresql .TestConnectionString (cfg .PgUri ); err != nil {
151- return fmt .Errorf ("database connection failed: %w" , err )
170+ if err := validateSnapshotPrereqs (cfg .PgUri ); err != nil {
171+ return err
152172 }
153173
154174 outputPath := snapshotOutput
@@ -165,10 +185,6 @@ func runSnapshotCapture() error {
165185 format = regresql .GetSnapshotFormat (cfg .Snapshot )
166186 }
167187
168- if err := regresql .CheckPgTool ("pg_dump" , snapshotCwd ); err != nil {
169- return err
170- }
171-
172188 opts := regresql.SnapshotOptions {
173189 OutputPath : outputPath ,
174190 Format : format ,
@@ -206,6 +222,52 @@ func runSnapshotCapture() error {
206222 return nil
207223}
208224
225+ func runSnapshotCaptureSections () error {
226+ cfg , err := regresql .ReadConfig (snapshotCwd )
227+ if err != nil {
228+ return fmt .Errorf ("failed to read config: %w (have you run 'regresql init'?)" , err )
229+ }
230+ if err := validateSnapshotPrereqs (cfg .PgUri ); err != nil {
231+ return err
232+ }
233+
234+ outputDir := snapshotOutputDir
235+ if outputDir == "" {
236+ outputDir = regresql .GetSnapshotsDir (snapshotCwd )
237+ } else if ! filepath .IsAbs (outputDir ) {
238+ outputDir = filepath .Join (snapshotCwd , outputDir )
239+ }
240+
241+ fmt .Printf ("Capturing database sections...\n " )
242+ fmt .Printf (" Database: %s\n " , maskConnectionString (cfg .PgUri ))
243+ fmt .Printf (" Output dir: %s\n " , outputDir )
244+ fmt .Printf (" Sections: pre-data, data, post-data\n " )
245+ fmt .Println ()
246+
247+ result , err := regresql .CaptureSections (cfg .PgUri , regresql.SectionsOptions {
248+ OutputDir : outputDir ,
249+ })
250+ if err != nil {
251+ return err
252+ }
253+
254+ fmt .Printf ("Sections captured successfully.\n " )
255+ fmt .Printf (" Time: %s\n " , result .Created .Format ("2006-01-02 15:04:05 UTC" ))
256+ fmt .Println ()
257+
258+ var totalSize int64
259+ for _ , s := range result .Sections {
260+ fmt .Printf (" %s.sql\n " , s .Section )
261+ fmt .Printf (" Size: %s\n " , regresql .FormatBytes (s .SizeBytes ))
262+ fmt .Printf (" Hash: %s\n " , s .Hash )
263+ totalSize += s .SizeBytes
264+ }
265+ fmt .Println ()
266+ fmt .Printf (" Total: %s\n " , regresql .FormatBytes (totalSize ))
267+
268+ return nil
269+ }
270+
209271func maskConnectionString (pguri string ) string {
210272 masked := pguri
211273 if idx := findPasswordEnd (pguri ); idx > 0 {
0 commit comments