3636 flagSet := flag .NewFlagSet ("upload" , flag .ExitOnError )
3737 bucketName := flagSet .String ("bucket" , "" , "destination Cloud Storage bucket name" )
3838 credentialsPath := flagSet .String ("credentials" , "" , "JSON credentials file for Google Cloud service account" )
39+ trimExtensions := flagSet .Bool ("trim-extensions" , true , "trim EXTENSION statements from database dumps for import to Google Cloud SQL" )
3940
4041 snapshotCommands = append (snapshotCommands , & command {
4142 flagSet : flagSet ,
5960 }
6061
6162 type upload struct {
62- file * os.File
63- stat os.FileInfo
63+ file * os.File
64+ stat os.FileInfo
65+ trimExtensions bool
6466 }
6567 var (
6668 uploads []upload // index aligned with progressBars
7678 return errors .Wrap (err , "get file size" )
7779 }
7880 uploads = append (uploads , upload {
79- file : f ,
80- stat : stat ,
81+ file : f ,
82+ stat : stat ,
83+ trimExtensions : false , // not a database dump
8184 })
8285 progressBars = append (progressBars , output.ProgressBar {
8386 Label : stat .Name (),
9598 return errors .Wrap (err , "get file size" )
9699 }
97100 uploads = append (uploads , upload {
98- file : f ,
99- stat : stat ,
101+ file : f ,
102+ stat : stat ,
103+ trimExtensions : * trimExtensions ,
100104 })
101105 progressBars = append (progressBars , output.ProgressBar {
102106 Label : stat .Name (),
@@ -116,7 +120,7 @@ BUCKET
116120 g .Go (func (ctx context.Context ) error {
117121 progressFn := func (p int64 ) { progress .SetValue (i , float64 (p )) }
118122
119- if err := copyToBucket (ctx , u .file , u .stat , bucket , progressFn ); err != nil {
123+ if err := copyDumpToBucket (ctx , u .file , u .stat , bucket , progressFn , u . trimExtensions ); err != nil {
120124 return errors .Wrap (err , u .stat .Name ())
121125 }
122126
@@ -139,26 +143,43 @@ BUCKET
139143 })
140144}
141145
142- func copyToBucket (ctx context.Context , src io.Reader , stat fs.FileInfo , dst * storage.BucketHandle , progressFn func (int64 )) error {
143- writer := dst .Object (stat .Name ()).NewWriter (ctx )
144- writer .ProgressFunc = progressFn
145- defer writer .Close ()
146+ func copyDumpToBucket (ctx context.Context , src io.ReadSeeker , stat fs.FileInfo , dst * storage.BucketHandle , progressFn func (int64 ), trimExtensions bool ) error {
147+ // Set up object to write to
148+ object := dst .Object (stat .Name ()).NewWriter (ctx )
149+ object .ProgressFunc = progressFn
150+ defer object .Close ()
151+
152+ // To assert against actual file size
153+ var totalWritten int64
154+
155+ // Do a partial copy that trims out unwanted statements
156+ if trimExtensions {
157+ written , err := pgdump .PartialCopyWithoutExtensions (object , src , progressFn )
158+ if err != nil {
159+ return errors .Wrap (err , "trim extensions and upload" )
160+ }
161+ totalWritten += written
162+ }
146163
147164 // io.Copy is the best way to copy from a reader to writer in Go, and storage.Writer
148- // has its own chunking mechanisms internally.
149- written , err := io .Copy (writer , src )
165+ // has its own chunking mechanisms internally. io.Reader is stateful, so this copy
166+ // will just continue from where we left off if we use copyAndTrimExtensions.
167+ written , err := io .Copy (object , src )
150168 if err != nil {
151- return err
169+ return errors . Wrap ( err , "upload" )
152170 }
171+ totalWritten += written
153172
154- // Progress is not called on completion, so we call it manually after io.Copy is done
173+ // Progress is not called on completion of io.Copy, so we call it manually after to
174+ // update our pretty progress bars.
155175 progressFn (written )
156176
157- // Validate we have sent all data
177+ // Validate we have sent all data. copyAndTrimExtensions may add some bytes, so the
178+ // check is not a strict equality.
158179 size := stat .Size ()
159- if written != size {
160- return errors .Newf ("expected to write %d bytes, but actually wrote %d bytes" ,
161- size , written )
180+ if totalWritten < size {
181+ return errors .Newf ("expected to write %d bytes, but actually wrote %d bytes (diff: %d bytes) " ,
182+ size , totalWritten , totalWritten - size )
162183 }
163184
164185 return nil
0 commit comments